dispatch_test.c 9.81 KB
Newer Older
Michael Graff's avatar
Michael Graff committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
 * Copyright (C) 1998, 1999  Internet Software Consortium.
 * 
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */

#include <config.h>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

Michael Graff's avatar
Michael Graff committed
25
#include <isc/app.h>
Michael Graff's avatar
Michael Graff committed
26
27
#include <isc/assertions.h>
#include <isc/error.h>
Michael Graff's avatar
Michael Graff committed
28
#include <isc/inet.h>
Michael Graff's avatar
Michael Graff committed
29
30
31
32
33
34
35
36
#include <isc/mem.h>
#include <isc/task.h>
#include <isc/thread.h>
#include <isc/result.h>
#include <isc/socket.h>
#include <isc/timer.h>

#include <dns/dispatch.h>
Michael Graff's avatar
Michael Graff committed
37
#include <dns/message.h>
Michael Graff's avatar
Michael Graff committed
38
39
40
41
42
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
#include <dns/rdatatype.h>
Michael Graff's avatar
Michael Graff committed
43
44
45
46
47
48
49
50

#include <sys/types.h>
#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

Michael Graff's avatar
Michael Graff committed
51
52
#include "printmsg.h"

Michael Graff's avatar
Michael Graff committed
53
54
55
56
isc_mem_t *mctx;
isc_taskmgr_t *manager;
isc_socketmgr_t *socketmgr;
dns_dispatch_t *disp;
Michael Graff's avatar
Michael Graff committed
57
isc_task_t *t0, *t1, *t2;
Michael Graff's avatar
Michael Graff committed
58
59
60
61
isc_buffer_t render;
unsigned char render_buffer[1024];
dns_rdataset_t rdataset;
dns_rdatalist_t rdatalist;
Michael Graff's avatar
Michael Graff committed
62

Michael Graff's avatar
Michael Graff committed
63
64
65
void got_request(isc_task_t *, isc_event_t *);
void got_response(isc_task_t *, isc_event_t *);
void start_response(void);
Michael Graff's avatar
Michael Graff committed
66
static inline void CHECKRESULT(dns_result_t, char *);
Michael Graff's avatar
Michael Graff committed
67
void send_done(isc_task_t *, isc_event_t *);
Michael Graff's avatar
Michael Graff committed
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
void hex_dump(isc_buffer_t *);

void
hex_dump(isc_buffer_t *b)
{
	unsigned int len;
	isc_region_t r;

	isc_buffer_remaining(b, &r);

	printf("Buffer %p:  used region base %p, length %d",
	       b, r.base, r.length);
	for (len = 0 ; len < r.length ; len++) {
		if (len % 16 == 0)
			printf("\n");
		printf("%02x ", r.base[len]);
	}
	printf("\n");
}
Michael Graff's avatar
Michael Graff committed
87
88
89
90
91
92
93
94
95
96

static inline void
CHECKRESULT(dns_result_t result, char *msg)
{
	if (result != DNS_R_SUCCESS) {
		printf("%s: %s\n", msg, isc_result_totext(result));

		exit(1);
	}
}
Michael Graff's avatar
Michael Graff committed
97

Michael Graff's avatar
Michael Graff committed
98
99
100
101
102
103
void
send_done(isc_task_t *task, isc_event_t *ev_in)
{
	isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
	dns_dispentry_t *resp = (dns_dispentry_t *)ev_in->arg;

Michael Graff's avatar
Michael Graff committed
104
105
	(void)task;

Michael Graff's avatar
Michael Graff committed
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
	if (ev->result == ISC_R_SUCCESS) {
		printf("Send done (SUCCESS)\n");
		isc_event_free(&ev_in);
		return;
	}

	CHECKRESULT(ev->result, "send_done got event");

	isc_event_free(&ev_in);

	printf("--- removing response (FAILURE)\n");
	dns_dispatch_removeresponse(disp, &resp, NULL);
	isc_app_shutdown();
}


Michael Graff's avatar
Michael Graff committed
122
void
Michael Graff's avatar
Michael Graff committed
123
124
125
126
127
128
start_response(void)
{
	dns_dispentry_t *resp;
	dns_messageid_t id;
	isc_sockaddr_t from;
	dns_message_t *msg;
Michael Graff's avatar
Michael Graff committed
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
	isc_result_t result;
	dns_name_t name;
	unsigned char namebuf[255];
	isc_buffer_t target;
	isc_buffer_t source;
	isc_region_t region;

#define QUESTION "flame.org."

	isc_buffer_init(&source, QUESTION, strlen(QUESTION),
			ISC_BUFFERTYPE_TEXT);
	isc_buffer_add(&source, strlen(QUESTION));
	isc_buffer_setactive(&source, strlen(QUESTION));
	isc_buffer_init(&target, namebuf, sizeof(namebuf),
			ISC_BUFFERTYPE_BINARY);
	dns_name_init(&name, NULL);
	result = dns_name_fromtext(&name, &source, dns_rootname, ISC_FALSE,
				   &target);
	CHECKRESULT(result, "dns_name_fromtext()");

	memset(&from, 0, sizeof(from));
	from.length = sizeof(struct sockaddr_in);
Michael Graff's avatar
Michael Graff committed
151
#ifdef ISC_NET_HAVESALEN
Michael Graff's avatar
Michael Graff committed
152
	from.type.sa.sa_len = sizeof(struct sockaddr_in);
Michael Graff's avatar
Michael Graff committed
153
#endif
Michael Graff's avatar
Michael Graff committed
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
	from.type.sin.sin_port = htons(53);
	from.type.sa.sa_family = AF_INET;
	RUNTIME_CHECK(isc_inet_aton("204.152.184.97",
				    &from.type.sin.sin_addr) == 1);

	msg = NULL;
	result = dns_message_create(mctx, &msg, DNS_MESSAGE_INTENTRENDER);
	CHECKRESULT(result, "dns_message_create()");

	dns_message_addname(msg, &name, DNS_SECTION_QUESTION);

	rdatalist.rdclass = dns_rdataclass_in;
	rdatalist.type = dns_rdatatype_a;
	rdatalist.ttl = 0;
	ISC_LIST_INIT(rdatalist.rdata);

	dns_rdataset_init(&rdataset);
	result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
	CHECKRESULT(result, "dns_rdatalist_tordataset()");

	ISC_LIST_APPEND(name.list, &rdataset, link);

	result = printmessage(msg);
	CHECKRESULT(result, "printmessage()");

	isc_buffer_init(&render, render_buffer, sizeof(render_buffer),
			ISC_BUFFERTYPE_BINARY);
	result = dns_message_renderbegin(msg, &render);
	CHECKRESULT(result, "dns_message_renderbegin()");

	rdataset.attributes |= DNS_RDATASETATTR_QUESTION;

	result = dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0, 0);
	CHECKRESULT(result, "dns_message_rendersection(QUESTION)");

	result = dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0, 0);
	CHECKRESULT(result, "dns_message_rendersection(ANSWER)");

	result = dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0, 0);
	CHECKRESULT(result, "dns_message_rendersection(ADDITIONAL)");

	result = dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0, 0);
	CHECKRESULT(result, "dns_message_rendersection(AUTHORITY)");
Michael Graff's avatar
Michael Graff committed
197
198
199

	printf("--- adding response\n");
	resp = NULL;
Michael Graff's avatar
Michael Graff committed
200
201
202
203
	result = dns_dispatch_addresponse(disp, &from, t2, got_response, NULL,
					  &id, &resp);
	CHECKRESULT(result, "dns_dispatch_addresponse");

Michael Graff's avatar
Michael Graff committed
204
	printf("Assigned MessageID %d\n", id);
Michael Graff's avatar
Michael Graff committed
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219

	msg->opcode = dns_opcode_query;
	msg->rcode = dns_rcode_noerror;
	msg->flags = DNS_MESSAGEFLAG_RD;
	msg->id = id;

	result = dns_message_renderend(msg);
	CHECKRESULT(result, "dns_message_renderend");

	dns_message_destroy(&msg);

	isc_buffer_used(&render, &region);
	result = isc_socket_sendto(dns_dispatch_getsocket(disp), &region,
				   t2, send_done, resp, &from);
	CHECKRESULT(result, "isc_socket_sendto()");
Michael Graff's avatar
Michael Graff committed
220
221
222
223
}

void
got_response(isc_task_t *task, isc_event_t *ev_in)
Michael Graff's avatar
Michael Graff committed
224
225
226
{
	dns_dispatchevent_t *ev = (dns_dispatchevent_t *)ev_in;
	dns_dispentry_t *resp = ev->sender;
Michael Graff's avatar
Michael Graff committed
227
228
229
	dns_message_t *msg;
	isc_result_t result;

Michael Graff's avatar
Michael Graff committed
230
231
	(void)task;

Michael Graff's avatar
Michael Graff committed
232
233
234
235
236
237
	printf("App:  Got response (id %d).  Result: %s\n",
	       ev->id, isc_result_totext(ev->result));

	msg = NULL;
	result = dns_message_create(mctx, &msg, DNS_MESSAGE_INTENTPARSE);
	CHECKRESULT(result, "dns_message_create() failed");
Michael Graff's avatar
Michael Graff committed
238

Michael Graff's avatar
Michael Graff committed
239
240
241
242
243
244
245
246
247
248
249
250
	result = dns_message_parse(msg, &ev->buffer);
	CHECKRESULT(result, "dns_message_parse() failed");

	result = printmessage(msg);
	CHECKRESULT(result, "printmessage() failed");

	dns_message_destroy(&msg);

	printf("--- removing response\n");
	dns_dispatch_removeresponse(disp, &resp, &ev);

	isc_app_shutdown();
Michael Graff's avatar
Michael Graff committed
251
252
253
254
255
256
257
258
}

void
got_request(isc_task_t *task, isc_event_t *ev_in)
{
	dns_dispatchevent_t *ev = (dns_dispatchevent_t *)ev_in;
	dns_dispentry_t *resp = ev->sender;
	static int cnt = 0;
Michael Graff's avatar
Michael Graff committed
259
260
261
	dns_message_t *msg;
	dns_result_t result;

Michael Graff's avatar
Michael Graff committed
262
	printf("App:  Got request.  Result: %s\n",
Michael Graff's avatar
Michael Graff committed
263
264
265
266
267
268
269
270
271
	       isc_result_totext(ev->result));

	if (ev->result != DNS_R_SUCCESS) {
		printf("Got error, terminating application\n");
		dns_dispatch_removerequest(disp, &resp, &ev);
		isc_app_shutdown();
		return;
	}

Michael Graff's avatar
Michael Graff committed
272
273
	hex_dump(&ev->buffer);

Michael Graff's avatar
Michael Graff committed
274
275
276
277
278
279
280
281
282
	msg = NULL;
	result = dns_message_create(mctx, &msg, DNS_MESSAGE_INTENTPARSE);
	CHECKRESULT(result, "dns_message_create() failed");

	result = dns_message_parse(msg, &ev->buffer);
	CHECKRESULT(result, "dns_message_parse() failed");

	result = printmessage(msg);
	CHECKRESULT(result, "printmessage() failed");
Michael Graff's avatar
Michael Graff committed
283

Michael Graff's avatar
Michael Graff committed
284
	dns_message_destroy(&msg);
Michael Graff's avatar
Michael Graff committed
285

Michael Graff's avatar
Michael Graff committed
286
	sleep (1);
Michael Graff's avatar
Michael Graff committed
287
288
	printf("App:  Ready.\n");

Michael Graff's avatar
Michael Graff committed
289
	cnt++;
Michael Graff's avatar
Michael Graff committed
290
291
292
	switch (cnt) {
	case 6:
		printf("--- removing request\n");
Michael Graff's avatar
Michael Graff committed
293
		dns_dispatch_removerequest(disp, &resp, &ev);
Michael Graff's avatar
Michael Graff committed
294
		start_response();
Michael Graff's avatar
Michael Graff committed
295
296
297
298
299
300
		break;
		
	case 3:
		printf("--- removing request\n");
		dns_dispatch_removerequest(disp, &resp, &ev);
		printf("--- adding request\n");
Michael Graff's avatar
Michael Graff committed
301
		RUNTIME_CHECK(dns_dispatch_addrequest(disp, task, got_request,
Michael Graff's avatar
Michael Graff committed
302
303
304
305
306
						      NULL, &resp)
			      == DNS_R_SUCCESS);
		break;

	default:
Michael Graff's avatar
Michael Graff committed
307
		dns_dispatch_freeevent(disp, resp, &ev);
Michael Graff's avatar
Michael Graff committed
308
		break;
Michael Graff's avatar
Michael Graff committed
309
	}
Michael Graff's avatar
Michael Graff committed
310
311
312
313
314
315
316
317
318
319
320
321
}

int
main(int argc, char *argv[])
{
	isc_socket_t *s0;
	isc_sockaddr_t sockaddr;
	dns_dispentry_t *resp;

	(void)argc;
	(void)argv;

Michael Graff's avatar
Michael Graff committed
322
323
	RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);

Michael Graff's avatar
Michael Graff committed
324
325
326
327
328
329
	/*
	 * EVERYTHING needs a memory context.
	 */
	mctx = NULL;
	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);

Michael Graff's avatar
Michael Graff committed
330
331
	dns_result_register();

Michael Graff's avatar
Michael Graff committed
332
333
334
335
	/*
	 * The task manager is independent (other than memory context)
	 */
	manager = NULL;
Michael Graff's avatar
Michael Graff committed
336
	RUNTIME_CHECK(isc_taskmgr_create(mctx, 5, 0, &manager) ==
Michael Graff's avatar
Michael Graff committed
337
338
339
340
		      ISC_R_SUCCESS);

	t0 = NULL;
	RUNTIME_CHECK(isc_task_create(manager, NULL, 0, &t0) == ISC_R_SUCCESS);
Michael Graff's avatar
Michael Graff committed
341
342
343
344
	t1 = NULL;
	RUNTIME_CHECK(isc_task_create(manager, NULL, 0, &t1) == ISC_R_SUCCESS);
	t2 = NULL;
	RUNTIME_CHECK(isc_task_create(manager, NULL, 0, &t2) == ISC_R_SUCCESS);
Michael Graff's avatar
Michael Graff committed
345
346
347
348
349
350
351
352
353
354

	socketmgr = NULL;
	RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS);

	/*
	 * Open up a random socket.  Who cares where.
	 */
	s0 = NULL;
	memset(&sockaddr, 0, sizeof(sockaddr));
	sockaddr.type.sin.sin_family = AF_INET;
Michael Graff's avatar
Michael Graff committed
355
	sockaddr.type.sin.sin_port = htons(5555);
Michael Graff's avatar
Michael Graff committed
356
357
358
359
360
361
362
363
364
	sockaddr.length = sizeof (struct sockaddr_in);
	RUNTIME_CHECK(isc_socket_create(socketmgr, isc_socket_udp, &s0) ==
		      ISC_R_SUCCESS);
	RUNTIME_CHECK(isc_socket_bind(s0, &sockaddr) == ISC_R_SUCCESS);

	/*
	 * Create a dispatch context
	 */
	disp = NULL;
Michael Graff's avatar
Michael Graff committed
365
	RUNTIME_CHECK(dns_dispatch_create(mctx, s0, t0, 512, 6, 1024,
Michael Graff's avatar
Michael Graff committed
366
					 4, &disp) == ISC_R_SUCCESS);
Michael Graff's avatar
Michael Graff committed
367
368

	resp = NULL;
Michael Graff's avatar
Michael Graff committed
369
	RUNTIME_CHECK(dns_dispatch_addrequest(disp, t1, got_request, NULL,
Michael Graff's avatar
Michael Graff committed
370
371
					      &resp) == ISC_R_SUCCESS);

Michael Graff's avatar
Michael Graff committed
372
373
	isc_app_run();

Michael Graff's avatar
Michael Graff committed
374
	isc_socket_detach(&s0);
Michael Graff's avatar
Michael Graff committed
375
376

	dns_dispatch_destroy(&disp);
Michael Graff's avatar
Michael Graff committed
377

Michael Graff's avatar
Michael Graff committed
378
379
380
	fprintf(stderr, "Destroying socket manager\n");
	isc_socketmgr_destroy(&socketmgr);

Michael Graff's avatar
Michael Graff committed
381
382
383
384
385
386
387
	isc_task_shutdown(t0);
	isc_task_detach(&t0);
	isc_task_shutdown(t1);
	isc_task_detach(&t1);
	isc_task_shutdown(t2);
	isc_task_detach(&t2);

Michael Graff's avatar
Michael Graff committed
388
389
390
	fprintf(stderr, "Destroying task manager\n");
	isc_taskmgr_destroy(&manager);

Michael Graff's avatar
Michael Graff committed
391
	isc_mem_stats(mctx, stderr);
Michael Graff's avatar
Michael Graff committed
392
393
	isc_mem_destroy(&mctx);

Michael Graff's avatar
Michael Graff committed
394
395
	isc_app_finish();

Michael Graff's avatar
Michael Graff committed
396
397
	return (0);
}