sdig.c 10.2 KB
Newer Older
Bob Halley's avatar
Bob Halley 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
25
/*
 * Copyright (C) 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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <netdb.h>		/* XXXRTH */
26
extern int h_errno;
Bob Halley's avatar
Bob Halley committed
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

#include <isc/types.h>
#include <isc/app.h>
#include <isc/assertions.h>
#include <isc/error.h>
#include <isc/mem.h>
#include <isc/net.h>
#include <isc/result.h>
#include <isc/sockaddr.h>
#include <isc/socket.h>
#include <isc/task.h>

#include <dns/types.h>
#include <dns/message.h>
#include <dns/name.h>
#include <dns/fixedname.h>
Bob Halley's avatar
Bob Halley committed
43
44
#include <dns/rdata.h>
#include <dns/rdatalist.h>
Bob Halley's avatar
Bob Halley committed
45
46
47
48
49
50
51
#include <dns/rdataset.h>
#include <dns/rdataclass.h>
#include <dns/rdatatype.h>
#include <dns/result.h>

#include "printmsg.h"

Bob Halley's avatar
Bob Halley committed
52
53
#define SDIG_BUFFER_SIZE 2048

Bob Halley's avatar
Bob Halley committed
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
static dns_message_t *message = NULL;
static isc_boolean_t have_ipv6 = ISC_FALSE;

static void
fatal(char *format, ...) {
	va_list args;

	va_start(args, format);	
	vfprintf(stderr, format, args);
	va_end(args);
	fprintf(stderr, "\n");
	exit(1);
}

static inline void
check_result(isc_result_t result, char *msg) {
	if (result != ISC_R_SUCCESS)
		fatal("%s: %s", msg, isc_result_totext(result));
}

static void
usage() {
	fprintf(stderr,
		"usage: sdig [@server] [-p port] [+vc] name [type] [class]\n");
	exit(1);
}

static void
add_type(dns_message_t *message, dns_name_t *name, dns_rdataclass_t rdclass,
	 dns_rdatatype_t rdtype)
{
	dns_rdataset_t *rdataset;
	isc_result_t result;

	rdataset = NULL;
	result = dns_message_gettemprdataset(message, &rdataset);
	check_result(result, "dns_message_gettemprdataset()");
	dns_rdataset_init(rdataset);
	dns_rdataset_makequestion(rdataset, rdclass, rdtype);
	ISC_LIST_APPEND(name->list, rdataset, link);
}

Bob Halley's avatar
Bob Halley committed
96
static void
Bob Halley's avatar
EDNS0    
Bob Halley committed
97
add_opt(dns_message_t *message, isc_uint16_t udpsize) {
Bob Halley's avatar
Bob Halley committed
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
	dns_rdataset_t *rdataset;
	dns_rdatalist_t *rdatalist;
	dns_rdata_t *rdata;
	isc_result_t result;

	rdataset = NULL;
	result = dns_message_gettemprdataset(message, &rdataset);
	check_result(result, "dns_message_gettemprdataset()");
	dns_rdataset_init(rdataset);
	rdatalist = NULL;
	result = dns_message_gettemprdatalist(message, &rdatalist);
	check_result(result, "dns_message_gettemprdatalist()");
	rdata = NULL;
	result = dns_message_gettemprdata(message, &rdata);
	check_result(result, "dns_message_gettemprdata()");

	rdatalist->type = dns_rdatatype_opt;
	rdatalist->covers = 0;

	/*
	 * Set Maximum UDP buffer size.
	 */
	rdatalist->rdclass = udpsize;

	/*
	 * Set EXTENDED-RCODE, VERSION, and Z to 0.
	 */
	rdatalist->ttl = 0;

	/*
	 * No ENDS options.
	 */
	rdata->data = NULL;
	rdata->length = 0;

	ISC_LIST_INIT(rdatalist->rdata);
	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
	dns_rdatalist_tordataset(rdatalist, rdataset);
Bob Halley's avatar
EDNS0    
Bob Halley committed
136
137
138

	result = dns_message_setopt(message, rdataset);
	check_result(result, "dns_message_setopt()");
Bob Halley's avatar
Bob Halley committed
139
140
}

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
static void
hex_dump(isc_buffer_t *b)
{
	unsigned int len;
	isc_region_t r;

	isc_buffer_remaining(b, &r);

	for (len = 0 ; len < r.length ; len++) {
		printf("%02x ", r.base[len]);
		if (len != 0 && len % 16 == 0)
			printf("\n");
	}
	if (len % 16 != 0)
		printf("\n");
}

Bob Halley's avatar
Bob Halley committed
158
static void
159
get_address(char *hostname, in_port_t port, isc_sockaddr_t *sockaddr) {
Bob Halley's avatar
Bob Halley committed
160
161
162
163
164
165
	struct in_addr in4;
	struct in6_addr in6;
	struct hostent *he;

	if (have_ipv6 && inet_pton(AF_INET6, hostname, &in6) == 1)
		isc_sockaddr_fromin6(sockaddr, &in6, port);
Bob Halley's avatar
Bob Halley committed
166
	else if (inet_pton(AF_INET, hostname, &in4) == 1)
Bob Halley's avatar
Bob Halley committed
167
		isc_sockaddr_fromin(sockaddr, &in4, port);
Bob Halley's avatar
Bob Halley committed
168
	else {
Bob Halley's avatar
Bob Halley committed
169
170
171
172
173
174
175
176
177
178
179
180
181
182
		he = gethostbyname(hostname);
		if (he == NULL)
			fatal("gethostbyname() failed, h_errno = %d",
			      h_errno);
		INSIST(he->h_addrtype == AF_INET);
		isc_sockaddr_fromin(sockaddr,
				    (struct in_addr *)(he->h_addr_list[0]),
				    port);
	}
}

static void
recv_done(isc_task_t *task, isc_event_t *event) {
	isc_socketevent_t *sevent;
183
	isc_buffer_t *b;
Bob Halley's avatar
Bob Halley committed
184
185
186
187
188
189
190
	isc_result_t result;

	REQUIRE(event->type == ISC_SOCKEVENT_RECVDONE);
	sevent = (isc_socketevent_t *)event;

	(void)task;

191
192
193
	/*
	 * There will be one buffer (since that is what we put on the list)
	 */
Bob Halley's avatar
Bob Halley committed
194
	if (sevent->result == ISC_R_SUCCESS) {
195
196
		b = ISC_LIST_HEAD(sevent->bufferlist);
		ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
Bob Halley's avatar
Bob Halley committed
197
		dns_message_reset(message, DNS_MESSAGE_INTENTPARSE);
198
		result = dns_message_parse(message, b, ISC_FALSE);
199
		if (result != ISC_R_SUCCESS)
200
			hex_dump(b);
Bob Halley's avatar
Bob Halley committed
201
202
203
		check_result(result, "dns_message_parse()");
		result = printmessage(message);
		check_result(result, "printmessage()");
204
		printf("; Received %u bytes.\n", b->used);
Bob Halley's avatar
Bob Halley committed
205
	} else if (sevent->result != ISC_R_CANCELED)
Bob Halley's avatar
Bob Halley committed
206
		fatal("recv_done(): %s", isc_result_totext(sevent->result));
Bob Halley's avatar
Bob Halley committed
207
208
209
210
211
212
213
214
215
216
217
218
219
220
	
	isc_event_free(&event);
	isc_app_shutdown();
}

static void
send_done(isc_task_t *task, isc_event_t *event) {
	(void)task;
	isc_event_free(&event);
}

int
main(int argc, char *argv[]) {
	char *server;
221
	in_port_t port;
Bob Halley's avatar
Bob Halley committed
222
	isc_boolean_t vc, have_name, have_type, edns0;
Bob Halley's avatar
Bob Halley committed
223
	dns_name_t *name;
224
225
	static unsigned char *namedata[512];
	isc_buffer_t namebuffer;
Bob Halley's avatar
Bob Halley committed
226
227
228
229
	dns_rdatatype_t rdtype;
	dns_rdataclass_t rdclass, nclass;
	size_t len;
	isc_buffer_t b, b2;
230
	isc_bufferlist_t bufferlist;
Bob Halley's avatar
Bob Halley committed
231
232
233
234
235
236
237
	isc_result_t result;
	isc_textregion_t tr;
	isc_mem_t *mctx;
	isc_taskmgr_t *taskmgr;
	isc_task_t *task;
	isc_socketmgr_t *socketmgr;
	isc_socket_t *sock;
238
239
	static unsigned char *data[SDIG_BUFFER_SIZE];
	static unsigned char *data2[SDIG_BUFFER_SIZE];
Bob Halley's avatar
Bob Halley committed
240
241
	isc_sockaddr_t sockaddr;
	int i;
242
	unsigned int bufsize = SDIG_BUFFER_SIZE;
Bob Halley's avatar
Bob Halley committed
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276

	/*
	 * Initialize.
	 */

	result = isc_app_start();
	check_result(result, "isc_app_start()");

	dns_result_register();

	RUNTIME_CHECK(isc_net_probeipv4() == ISC_R_SUCCESS);
	if (isc_net_probeipv6() == ISC_R_SUCCESS)
		have_ipv6 = ISC_TRUE;

	mctx = NULL;
	result = isc_mem_create(0, 0, &mctx);
	check_result(result, "isc_mem_create()");
	taskmgr = NULL;
	result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
	check_result(result, "isc_taskmgr_create()");
	task = NULL;
	result = isc_task_create(taskmgr, NULL, 0, &task);
	check_result(result, "isc_task_create()");
	socketmgr = NULL;
	result = isc_socketmgr_create(mctx, &socketmgr);
	check_result(result, "isc_socketmgr_create()");
	sock = NULL;

	server = "localhost";
	port = 5544;
	vc = ISC_FALSE;
	have_name = ISC_FALSE;
	have_type = ISC_FALSE;
	rdclass = dns_rdataclass_in;
Bob Halley's avatar
Bob Halley committed
277
	edns0 = ISC_FALSE;
Bob Halley's avatar
Bob Halley committed
278
279
280
281

	message = NULL;
	result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message);
	check_result(result, "dns_message_create()");
282
283
284
285
286
287
288
	name = NULL;
	result = dns_message_gettempname(message, &name);
	check_result(result, "dns_message_gettempname()");
	dns_name_init(name, NULL);

	isc_buffer_init(&namebuffer, namedata, sizeof(namedata),
			ISC_BUFFERTYPE_BINARY);
Bob Halley's avatar
Bob Halley committed
289
290
291
292
293
294
295
296
297
298
299
300
301

	printf("\n; <<>> sdig <<>>");
	for (i = 1; i < argc; i++) {
		printf(" %s", argv[i]);
	}
	printf("\n");
	for (argc--, argv++; argc > 0; argc--, argv++) {
		if (strncmp(argv[0], "@", 1) == 0) {
			server = &argv[0][1];
		} else if (strcmp(argv[0], "-p") == 0) {
			if (argc < 2)
				usage();
			port = atoi(argv[1]);
Bob Halley's avatar
Bob Halley committed
302
303
			argv++;
			argc--;
Bob Halley's avatar
Bob Halley committed
304
305
		} else if (strcmp(argv[0], "+vc") == 0) {
			fatal("TCP transport not yet implemented");
Bob Halley's avatar
Bob Halley committed
306
		} else if (strcmp(argv[0], "+edns0") == 0) {
Bob Halley's avatar
EDNS0    
Bob Halley committed
307
			edns0 = ISC_TRUE;
308
309
310
311
		} else if (strncmp(argv[0], "+bufsize=", 9) == 0) {
			bufsize = atoi(&argv[0][9]);
			if (bufsize > SDIG_BUFFER_SIZE)
				bufsize = SDIG_BUFFER_SIZE;
Bob Halley's avatar
Bob Halley committed
312
313
314
315
316
317
318
319
320
321
322
		} else {
			len = strlen(argv[0]);
			tr.base = argv[0];
			tr.length = len;
			if (!have_name) {
				isc_buffer_init(&b, argv[0], len,
						ISC_BUFFERTYPE_TEXT);
				isc_buffer_add(&b, len);
				result = dns_name_fromtext(name, &b,
							   dns_rootname,
							   ISC_FALSE,
323
							   &namebuffer);
Bob Halley's avatar
Bob Halley committed
324
325
326
327
328
329
330
331
332
				check_result(result, "dns_name_fromtext()");
				have_name = ISC_TRUE;
			} else {
				if (dns_rdatatype_fromtext(&rdtype, &tr) ==
				    ISC_R_SUCCESS) {
					add_type(message, name, rdclass,
						 rdtype);
					have_type = ISC_TRUE;
				} else {
Bob Halley's avatar
Bob Halley committed
333
334
					if (dns_rdataclass_fromtext(&nclass,
								    &tr) !=
Bob Halley's avatar
Bob Halley committed
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
					    ISC_R_SUCCESS)
						fatal("unknown class "
						      "or type %s", argv[0]);
					rdclass = nclass;
				}
			}
		}
	}
	if (!have_name)
		usage();
	if (!have_type)
		add_type(message, name, dns_rdataclass_in, dns_rdatatype_a);

	message->id = 1;
	message->opcode = dns_opcode_query;
	message->flags |= DNS_MESSAGEFLAG_RD;
	dns_message_addname(message, name, DNS_SECTION_QUESTION);

	isc_buffer_init(&b, data, sizeof data, ISC_BUFFERTYPE_BINARY);
	result = dns_message_renderbegin(message, &b);
	check_result(result, "dns_message_renderbegin()");
Bob Halley's avatar
EDNS0    
Bob Halley committed
356
	if (edns0)
357
		add_opt(message, (isc_uint16_t)bufsize);
Bob Halley's avatar
Bob Halley committed
358
359
360
361
362
363
	result = dns_message_rendersection(message, DNS_SECTION_QUESTION,
					   0, 0);
	check_result(result, "dns_message_rendersection()");
	result = dns_message_renderend(message);
	check_result(result, "dns_message_renderend()");

Bob Halley's avatar
Bob Halley committed
364
365
	(void)printmessage(message);

Bob Halley's avatar
Bob Halley committed
366
367
	get_address(server, port, &sockaddr);

368
369
370
371
	result = isc_socket_create(socketmgr, isc_sockaddr_pf(&sockaddr),
				   isc_sockettype_udp, &sock);
	check_result(result, "isc_socket_create()");

Bob Halley's avatar
Bob Halley committed
372
	ISC_LIST_INIT(bufferlist);
Bob Halley's avatar
Bob Halley committed
373
	isc_buffer_init(&b2, data2, sizeof data2, ISC_BUFFERTYPE_BINARY);
374
375
376
377
378
379
380
	ISC_LIST_ENQUEUE(bufferlist, &b2, link);
	result = isc_socket_recvv(sock, &bufferlist, 1, task, recv_done, NULL);
	check_result(result, "isc_socket_recvv()");
	ISC_LIST_ENQUEUE(bufferlist, &b, link);
	result = isc_socket_sendtov(sock, &bufferlist, task, send_done, NULL,
				    &sockaddr);
	check_result(result, "isc_socket_sendtov()");
Bob Halley's avatar
Bob Halley committed
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395

	isc_app_run();

	dns_message_destroy(&message);
	isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL);
	isc_task_detach(&task);
	isc_socket_detach(&sock);
	isc_taskmgr_destroy(&taskmgr);
	isc_socketmgr_destroy(&socketmgr);
	isc_mem_destroy(&mctx);

	isc_app_finish();
	
	return (0);
}