sample-request.c revision 224090
1249259Sdim/*
2249259Sdim * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
3249259Sdim *
4249259Sdim * Permission to use, copy, modify, and/or distribute this software for any
5249259Sdim * purpose with or without fee is hereby granted, provided that the above
6249259Sdim * copyright notice and this permission notice appear in all copies.
7249259Sdim *
8249259Sdim * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9249259Sdim * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10249259Sdim * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11249259Sdim * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12249259Sdim * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13249259Sdim * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14249259Sdim * PERFORMANCE OF THIS SOFTWARE.
15249259Sdim */
16249259Sdim
17263508Sdim/* $Id: sample-request.c,v 1.5 2009-09-29 15:06:07 fdupont Exp $ */
18263508Sdim
19249259Sdim#include <config.h>
20249259Sdim
21249259Sdim#include <sys/types.h>
22249259Sdim#include <sys/socket.h>
23249259Sdim
24249259Sdim#include <netinet/in.h>
25249259Sdim
26249259Sdim#include <arpa/inet.h>
27249259Sdim
28249259Sdim#include <unistd.h>
29249259Sdim#include <stdio.h>
30249259Sdim#include <stdlib.h>
31249259Sdim#include <string.h>
32249259Sdim#include <netdb.h>
33249259Sdim
34249259Sdim#include <isc/base64.h>
35249259Sdim#include <isc/buffer.h>
36249259Sdim#include <isc/lib.h>
37249259Sdim#include <isc/mem.h>
38249259Sdim#include <isc/sockaddr.h>
39249259Sdim#include <isc/util.h>
40249259Sdim
41249259Sdim#include <dns/client.h>
42249259Sdim#include <dns/fixedname.h>
43263508Sdim#include <dns/keyvalues.h>
44249259Sdim#include <dns/lib.h>
45249259Sdim#include <dns/masterdump.h>
46249259Sdim#include <dns/message.h>
47249259Sdim#include <dns/name.h>
48249259Sdim#include <dns/rdata.h>
49249259Sdim#include <dns/rdataset.h>
50249259Sdim#include <dns/rdatastruct.h>
51249259Sdim#include <dns/rdatatype.h>
52249259Sdim#include <dns/result.h>
53249259Sdim#include <dns/secalg.h>
54249259Sdim
55249259Sdim#include <dst/dst.h>
56249259Sdim
57249259Sdimstatic isc_mem_t *mctx;
58249259Sdimstatic dns_fixedname_t fixedqname;
59249259Sdim
60249259SdimISC_PLATFORM_NORETURN_PRE static void
61249259Sdimusage(void) ISC_PLATFORM_NORETURN_POST;
62249259Sdim
63249259Sdimstatic void
64249259Sdimusage(void) {
65249259Sdim	fprintf(stderr, "sample-request [-t RRtype] server_address hostname\n");
66249259Sdim
67249259Sdim	exit(1);
68249259Sdim}
69249259Sdim
70249259Sdimstatic isc_result_t
71249259Sdimmake_querymessage(dns_message_t *message, const char *namestr,
72249259Sdim		  dns_rdatatype_t rdtype)
73249259Sdim{
74249259Sdim	dns_name_t *qname = NULL, *qname0;
75249259Sdim	dns_rdataset_t *qrdataset = NULL;
76249259Sdim	isc_result_t result;
77263508Sdim	isc_buffer_t b;
78263508Sdim	size_t namelen;
79249259Sdim
80249259Sdim	/* Construct qname */
81249259Sdim	namelen = strlen(namestr);
82249259Sdim	isc_buffer_init(&b, namestr, namelen);
83249259Sdim	isc_buffer_add(&b, namelen);
84249259Sdim	dns_fixedname_init(&fixedqname);
85249259Sdim	qname0 = dns_fixedname_name(&fixedqname);
86249259Sdim	result = dns_name_fromtext(qname0, &b, dns_rootname, 0, NULL);
87249259Sdim	if (result != ISC_R_SUCCESS) {
88249259Sdim		fprintf(stderr, "failed to convert qname: %d\n", result);
89256030Sdim		return (result);
90256030Sdim	}
91249259Sdim
92249259Sdim	/* Construct query message */
93249259Sdim	message->opcode = dns_opcode_query;
94249259Sdim	message->rdclass = dns_rdataclass_in;
95249259Sdim
96249259Sdim	result = dns_message_gettempname(message, &qname);
97249259Sdim	if (result != ISC_R_SUCCESS)
98249259Sdim		goto cleanup;
99249259Sdim
100249259Sdim	result = dns_message_gettemprdataset(message, &qrdataset);
101249259Sdim	if (result != ISC_R_SUCCESS)
102249259Sdim		goto cleanup;
103249259Sdim
104249259Sdim	dns_name_init(qname, NULL);
105249259Sdim	dns_name_clone(qname0, qname);
106249259Sdim	dns_rdataset_init(qrdataset);
107249259Sdim	dns_rdataset_makequestion(qrdataset, message->rdclass, rdtype);
108249259Sdim	ISC_LIST_APPEND(qname->list, qrdataset, link);
109249259Sdim	dns_message_addname(message, qname, DNS_SECTION_QUESTION);
110249259Sdim
111249259Sdim	return (ISC_R_SUCCESS);
112249259Sdim
113249259Sdim cleanup:
114249259Sdim	if (qname != NULL)
115249259Sdim		dns_message_puttempname(message, &qname);
116249259Sdim	if (qrdataset != NULL)
117249259Sdim		dns_message_puttemprdataset(message, &qrdataset);
118249259Sdim	if (message != NULL)
119249259Sdim		dns_message_destroy(&message);
120249259Sdim	return (result);
121249259Sdim}
122249259Sdim
123249259Sdimstatic void
124249259Sdimprint_section(dns_message_t *message, int section, isc_buffer_t *buf) {
125249259Sdim	isc_result_t result;
126249259Sdim	isc_region_t r;
127249259Sdim
128249259Sdim	result = dns_message_sectiontotext(message, section,
129249259Sdim					   &dns_master_style_full, 0, buf);
130249259Sdim	if (result != ISC_R_SUCCESS)
131249259Sdim		goto fail;
132249259Sdim
133249259Sdim	isc_buffer_usedregion(buf, &r);
134249259Sdim	printf("%.*s", (int)r.length, (char *)r.base);
135249259Sdim
136249259Sdim	return;
137249259Sdim
138249259Sdim fail:
139249259Sdim	fprintf(stderr, "failed to convert a section\n");
140249259Sdim}
141249259Sdim
142249259Sdimint
143249259Sdimmain(int argc, char *argv[]) {
144249259Sdim	int ch, i, gai_error;
145249259Sdim	struct addrinfo hints, *res;
146249259Sdim	isc_textregion_t tr;
147249259Sdim	dns_client_t *client = NULL;
148249259Sdim	isc_result_t result;
149249259Sdim	isc_sockaddr_t sa;
150249259Sdim	dns_message_t *qmessage, *rmessage;
151249259Sdim	dns_rdatatype_t type = dns_rdatatype_a;
152249259Sdim	isc_buffer_t *outputbuf;
153249259Sdim
154249259Sdim	while ((ch = getopt(argc, argv, "t:")) != -1) {
155249259Sdim		switch (ch) {
156249259Sdim		case 't':
157249259Sdim			tr.base = optarg;
158249259Sdim			tr.length = strlen(optarg);
159249259Sdim			result = dns_rdatatype_fromtext(&type, &tr);
160249259Sdim			if (result != ISC_R_SUCCESS) {
161249259Sdim				fprintf(stderr,
162249259Sdim					"invalid RRtype: %s\n", optarg);
163249259Sdim				exit(1);
164263508Sdim			}
165249259Sdim			break;
166249259Sdim		default:
167249259Sdim			usage();
168249259Sdim		}
169249259Sdim	}
170249259Sdim
171249259Sdim	argc -= optind;
172249259Sdim	argv += optind;
173249259Sdim	if (argc < 2)
174249259Sdim		usage();
175249259Sdim
176249259Sdim	isc_lib_register();
177249259Sdim	result = dns_lib_init();
178249259Sdim	if (result != ISC_R_SUCCESS) {
179249259Sdim		fprintf(stderr, "dns_lib_init failed: %d\n", result);
180249259Sdim		exit(1);
181249259Sdim	}
182249259Sdim
183249259Sdim	result = dns_client_create(&client, 0);
184249259Sdim	if (result != ISC_R_SUCCESS) {
185249259Sdim		fprintf(stderr, "dns_client_create failed: %d\n", result);
186249259Sdim		exit(1);
187249259Sdim	}
188249259Sdim
189249259Sdim	/* Prepare message structures */
190249259Sdim	mctx = NULL;
191249259Sdim	qmessage = NULL;
192249259Sdim	rmessage = NULL;
193249259Sdim
194249259Sdim	result = isc_mem_create(0, 0, &mctx);
195249259Sdim	if (result != ISC_R_SUCCESS) {
196249259Sdim		fprintf(stderr, "failed to create a memory context\n");
197249259Sdim		exit(1);
198249259Sdim	}
199249259Sdim	result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &qmessage);
200249259Sdim	if (result == ISC_R_SUCCESS) {
201249259Sdim		result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
202249259Sdim					    &rmessage);
203249259Sdim	}
204249259Sdim	if (result != ISC_R_SUCCESS) {
205249259Sdim		fprintf(stderr, "failed to create messages\n");
206249259Sdim		exit(1);
207249259Sdim	}
208249259Sdim
209249259Sdim	/* Initialize the nameserver address */
210249259Sdim	memset(&hints, 0, sizeof(hints));
211249259Sdim	hints.ai_family = AF_UNSPEC;
212249259Sdim	hints.ai_socktype = SOCK_DGRAM;
213249259Sdim	hints.ai_protocol = IPPROTO_UDP;
214249259Sdim	hints.ai_flags = AI_NUMERICHOST;
215249259Sdim	gai_error = getaddrinfo(argv[0], "53", &hints, &res);
216249259Sdim	if (gai_error != 0) {
217249259Sdim		fprintf(stderr, "getaddrinfo failed: %s\n",
218249259Sdim			gai_strerror(gai_error));
219249259Sdim		exit(1);
220249259Sdim	}
221249259Sdim	INSIST(res->ai_addrlen <= sizeof(sa.type));
222249259Sdim	memcpy(&sa.type, res->ai_addr, res->ai_addrlen);
223249259Sdim	freeaddrinfo(res);
224249259Sdim	sa.length = res->ai_addrlen;
225249259Sdim	ISC_LINK_INIT(&sa, link);
226249259Sdim
227249259Sdim	/* Construct qname */
228249259Sdim	result = make_querymessage(qmessage, argv[1], type);
229249259Sdim	if (result != ISC_R_SUCCESS) {
230249259Sdim		fprintf(stderr, "failed to create a query\n");
231249259Sdim		exit(1);
232249259Sdim	}
233249259Sdim
234249259Sdim	/* Send request and wait for a response */
235249259Sdim	result = dns_client_request(client, qmessage, rmessage, &sa, 0, 0,
236249259Sdim				    NULL, 60, 0, 3);
237249259Sdim	if (result != ISC_R_SUCCESS) {
238249259Sdim		fprintf(stderr, "failed to get a response: %s\n",
239249259Sdim			dns_result_totext(result));
240249259Sdim	}
241249259Sdim
242249259Sdim	/* Dump the response */
243249259Sdim	outputbuf = NULL;
244249259Sdim	result = isc_buffer_allocate(mctx, &outputbuf, 65535);
245249259Sdim	if (result != ISC_R_SUCCESS) {
246249259Sdim		fprintf(stderr, "failed to allocate a result buffer\n");
247249259Sdim		exit(1);
248249259Sdim	}
249249259Sdim	for (i = 0; i < DNS_SECTION_MAX; i++) {
250249259Sdim		print_section(rmessage, i, outputbuf);
251249259Sdim		isc_buffer_clear(outputbuf);
252249259Sdim	}
253249259Sdim	isc_buffer_free(&outputbuf);
254249259Sdim
255249259Sdim	/* Cleanup */
256249259Sdim	dns_message_destroy(&qmessage);
257249259Sdim	dns_message_destroy(&rmessage);
258249259Sdim	isc_mem_destroy(&mctx);
259249259Sdim	dns_client_destroy(&client);
260249259Sdim	dns_lib_shutdown();
261249259Sdim
262249259Sdim	exit(0);
263249259Sdim}
264249259Sdim