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: sig0_test.c,v 1.19 2009/09/02 23:48:01 tbox Exp $ */
19
20#include <config.h>
21
22#include <stddef.h>
23#include <stdlib.h>
24#include <string.h>
25
26#include <isc/app.h>
27#include <isc/boolean.h>
28#include <isc/assertions.h>
29#include <isc/commandline.h>
30#include <isc/entropy.h>
31#include <isc/error.h>
32#include <isc/log.h>
33#include <isc/mem.h>
34#include <isc/mutex.h>
35#include <isc/net.h>
36#include <isc/task.h>
37#include <isc/timer.h>
38#include <isc/socket.h>
39#include <isc/util.h>
40
41#include <dns/dnssec.h>
42#include <dns/events.h>
43#include <dns/fixedname.h>
44#include <dns/keyvalues.h>
45#include <dns/masterdump.h>
46#include <dns/message.h>
47#include <dns/name.h>
48#include <dns/rdataset.h>
49#include <dns/resolver.h>
50#include <dns/result.h>
51#include <dns/types.h>
52
53#include <dst/result.h>
54#include <dst/dst.h>
55
56#define CHECK(str, x) { \
57	if ((x) != ISC_R_SUCCESS) { \
58		printf("%s: %s\n", (str), isc_result_totext(x)); \
59		exit(-1); \
60	} \
61}
62
63isc_mutex_t lock;
64dst_key_t *key;
65isc_mem_t *mctx;
66unsigned char qdata[1024], rdata[1024];
67isc_buffer_t qbuffer, rbuffer;
68isc_taskmgr_t *taskmgr;
69isc_entropy_t *ent = NULL;
70isc_task_t *task1;
71isc_log_t *lctx = NULL;
72isc_logconfig_t *logconfig = NULL;
73isc_socket_t *s;
74isc_sockaddr_t address;
75char output[10 * 1024];
76isc_buffer_t outbuf;
77static const dns_master_style_t *style = &dns_master_style_debug;
78
79static void
80senddone(isc_task_t *task, isc_event_t *event) {
81	isc_socketevent_t *sevent = (isc_socketevent_t *)event;
82
83	REQUIRE(sevent != NULL);
84	REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE);
85	REQUIRE(task == task1);
86
87	printf("senddone\n");
88
89	isc_event_free(&event);
90}
91
92static void
93recvdone(isc_task_t *task, isc_event_t *event) {
94	isc_socketevent_t *sevent = (isc_socketevent_t *)event;
95	isc_buffer_t source;
96	isc_result_t result;
97	dns_message_t *response;
98
99	REQUIRE(sevent != NULL);
100	REQUIRE(sevent->ev_type == ISC_SOCKEVENT_RECVDONE);
101	REQUIRE(task == task1);
102
103	printf("recvdone\n");
104	if (sevent->result != ISC_R_SUCCESS) {
105		printf("failed\n");
106		exit(-1);
107	}
108
109	isc_buffer_init(&source, sevent->region.base, sevent->region.length);
110	isc_buffer_add(&source, sevent->n);
111
112	response = NULL;
113	result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
114	CHECK("dns_message_create", result);
115	result = dns_message_parse(response, &source, 0);
116	CHECK("dns_message_parse", result);
117
118	isc_buffer_init(&outbuf, output, sizeof(output));
119	result = dns_message_totext(response, style, 0, &outbuf);
120	CHECK("dns_message_totext", result);
121	printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
122	       (char *)isc_buffer_base(&outbuf));
123
124	dns_message_destroy(&response);
125	isc_event_free(&event);
126
127	isc_app_shutdown();
128}
129
130static void
131buildquery(void) {
132	isc_result_t result;
133	dns_rdataset_t *question = NULL;
134	dns_name_t *qname = NULL;
135	isc_region_t r, inr;
136	dns_message_t *query;
137	char nametext[] = "host.example";
138	isc_buffer_t namesrc, namedst;
139	unsigned char namedata[256];
140	isc_sockaddr_t sa;
141	dns_compress_t cctx;
142
143	query = NULL;
144	result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
145	CHECK("dns_message_create", result);
146	result = dns_message_setsig0key(query, key);
147	CHECK("dns_message_setsig0key", result);
148
149	result = dns_message_gettemprdataset(query, &question);
150	CHECK("dns_message_gettemprdataset", result);
151	dns_rdataset_init(question);
152	dns_rdataset_makequestion(question, dns_rdataclass_in,
153				  dns_rdatatype_a);
154	result = dns_message_gettempname(query, &qname);
155	CHECK("dns_message_gettempname", result);
156	isc_buffer_init(&namesrc, nametext, strlen(nametext));
157	isc_buffer_add(&namesrc, strlen(nametext));
158	isc_buffer_init(&namedst, namedata, sizeof(namedata));
159	dns_name_init(qname, NULL);
160	result = dns_name_fromtext(qname, &namesrc, dns_rootname, 0, &namedst);
161	CHECK("dns_name_fromtext", result);
162	ISC_LIST_APPEND(qname->list, question, link);
163	dns_message_addname(query, qname, DNS_SECTION_QUESTION);
164
165	isc_buffer_init(&qbuffer, qdata, sizeof(qdata));
166
167	result = dns_compress_init(&cctx, -1, mctx);
168	CHECK("dns_compress_init", result);
169	result = dns_message_renderbegin(query, &cctx, &qbuffer);
170	CHECK("dns_message_renderbegin", result);
171	result = dns_message_rendersection(query, DNS_SECTION_QUESTION, 0);
172	CHECK("dns_message_rendersection(question)", result);
173	result = dns_message_rendersection(query, DNS_SECTION_ANSWER, 0);
174	CHECK("dns_message_rendersection(answer)", result);
175	result = dns_message_rendersection(query, DNS_SECTION_AUTHORITY, 0);
176	CHECK("dns_message_rendersection(auth)", result);
177	result = dns_message_rendersection(query, DNS_SECTION_ADDITIONAL, 0);
178	CHECK("dns_message_rendersection(add)", result);
179	result = dns_message_renderend(query);
180	CHECK("dns_message_renderend", result);
181	dns_compress_invalidate(&cctx);
182
183	isc_buffer_init(&outbuf, output, sizeof(output));
184	result = dns_message_totext(query, style, 0, &outbuf);
185	CHECK("dns_message_totext", result);
186	printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
187	       (char *)isc_buffer_base(&outbuf));
188
189	isc_buffer_usedregion(&qbuffer, &r);
190	isc_sockaddr_any(&sa);
191	result = isc_socket_bind(s, &sa, 0);
192	CHECK("isc_socket_bind", result);
193	result = isc_socket_sendto(s, &r, task1, senddone, NULL, &address,
194				   NULL);
195	CHECK("isc_socket_sendto", result);
196
197	inr.base = rdata;
198	inr.length = sizeof(rdata);
199	result = isc_socket_recv(s, &inr, 1, task1, recvdone, NULL);
200	CHECK("isc_socket_recv", result);
201	dns_message_destroy(&query);
202}
203
204int
205main(int argc, char *argv[]) {
206	isc_boolean_t verbose = ISC_FALSE;
207	isc_socketmgr_t *socketmgr;
208	isc_timermgr_t *timermgr;
209	struct in_addr inaddr;
210	dns_fixedname_t fname;
211	dns_name_t *name;
212	isc_buffer_t b;
213	int ch;
214	isc_result_t result;
215	in_port_t port = 53;
216
217	RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);
218
219	RUNTIME_CHECK(isc_mutex_init(&lock) == ISC_R_SUCCESS);
220
221	mctx = NULL;
222	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
223
224	while ((ch = isc_commandline_parse(argc, argv, "vp:")) != -1) {
225		switch (ch) {
226		case 'v':
227			verbose = ISC_TRUE;
228			break;
229		case 'p':
230			port = (unsigned int)atoi(isc_commandline_argument);
231			break;
232		}
233	}
234
235	RUNTIME_CHECK(isc_entropy_create(mctx, &ent) == ISC_R_SUCCESS);
236	RUNTIME_CHECK(dst_lib_init(mctx, ent, 0) == ISC_R_SUCCESS);
237
238	dns_result_register();
239	dst_result_register();
240
241	taskmgr = NULL;
242	RUNTIME_CHECK(isc_taskmgr_create(mctx, 2, 0, &taskmgr) ==
243		      ISC_R_SUCCESS);
244	task1 = NULL;
245	RUNTIME_CHECK(isc_task_create(taskmgr, 0, &task1) == ISC_R_SUCCESS);
246
247	timermgr = NULL;
248	RUNTIME_CHECK(isc_timermgr_create(mctx, &timermgr) == ISC_R_SUCCESS);
249	socketmgr = NULL;
250	RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS);
251
252	RUNTIME_CHECK(isc_log_create(mctx, &lctx, &logconfig) == ISC_R_SUCCESS);
253
254	s = NULL;
255	RUNTIME_CHECK(isc_socket_create(socketmgr, PF_INET,
256					isc_sockettype_udp, &s) ==
257		      ISC_R_SUCCESS);
258
259	inaddr.s_addr = htonl(INADDR_LOOPBACK);
260	isc_sockaddr_fromin(&address, &inaddr, port);
261
262	dns_fixedname_init(&fname);
263	name = dns_fixedname_name(&fname);
264	isc_buffer_init(&b, "child.example.", strlen("child.example."));
265	isc_buffer_add(&b, strlen("child.example."));
266	result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
267	CHECK("dns_name_fromtext", result);
268
269	key = NULL;
270	result = dst_key_fromfile(name, 4017, DNS_KEYALG_DSA,
271				  DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
272				  NULL, mctx, &key);
273	CHECK("dst_key_fromfile", result);
274
275	buildquery();
276
277	(void)isc_app_run();
278
279	isc_task_shutdown(task1);
280	isc_task_detach(&task1);
281	isc_taskmgr_destroy(&taskmgr);
282
283	isc_socket_detach(&s);
284	isc_socketmgr_destroy(&socketmgr);
285	isc_timermgr_destroy(&timermgr);
286
287	dst_key_free(&key);
288
289	dst_lib_destroy();
290
291	isc_entropy_detach(&ent);
292
293	isc_log_destroy(&lctx);
294
295	if (verbose)
296		isc_mem_stats(mctx, stdout);
297	isc_mem_destroy(&mctx);
298
299	DESTROYLOCK(&lock);
300
301	isc_app_finish();
302
303	return (0);
304}
305