1 /*	$NetBSD: sample-request.c,v 1.1.1.5 2015/07/08 15:38:07 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2009, 2012-2015  Internet Systems Consortium, Inc. ("ISC")
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /* Id: sample-request.c,v 1.5 2009/09/29 15:06:07 fdupont Exp  */
20 
21 #include <config.h>
22 
23 #ifndef WIN32
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 
27 #include <netinet/in.h>
28 
29 #include <arpa/inet.h>
30 
31 #include <netdb.h>
32 #include <unistd.h>
33 #endif
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 
39 #include <isc/base64.h>
40 #include <isc/buffer.h>
41 #include <isc/commandline.h>
42 #include <isc/lib.h>
43 #include <isc/mem.h>
44 #include <isc/sockaddr.h>
45 #include <isc/util.h>
46 
47 #include <dns/client.h>
48 #include <dns/fixedname.h>
49 #include <dns/keyvalues.h>
50 #include <dns/lib.h>
51 #include <dns/masterdump.h>
52 #include <dns/message.h>
53 #include <dns/name.h>
54 #include <dns/rdata.h>
55 #include <dns/rdataset.h>
56 #include <dns/rdatastruct.h>
57 #include <dns/rdatatype.h>
58 #include <dns/result.h>
59 #include <dns/secalg.h>
60 
61 #include <dst/dst.h>
62 
63 static isc_mem_t *mctx;
64 static dns_fixedname_t fixedqname;
65 
66 ISC_PLATFORM_NORETURN_PRE static void
67 usage(void) ISC_PLATFORM_NORETURN_POST;
68 
69 static void
70 usage(void) {
71 	fprintf(stderr, "sample-request [-t RRtype] server_address hostname\n");
72 
73 	exit(1);
74 }
75 
76 static isc_result_t
77 make_querymessage(dns_message_t *message, const char *namestr,
78 		  dns_rdatatype_t rdtype)
79 {
80 	dns_name_t *qname = NULL, *qname0;
81 	dns_rdataset_t *qrdataset = NULL;
82 	isc_result_t result;
83 	isc_buffer_t b;
84 	unsigned int namelen;
85 
86 	REQUIRE(message != NULL);
87 	REQUIRE(namestr != NULL);
88 
89 	/* Construct qname */
90 	namelen = strlen(namestr);
91 	isc_buffer_constinit(&b, namestr, namelen);
92 	isc_buffer_add(&b, namelen);
93 	dns_fixedname_init(&fixedqname);
94 	qname0 = dns_fixedname_name(&fixedqname);
95 	result = dns_name_fromtext(qname0, &b, dns_rootname, 0, NULL);
96 	if (result != ISC_R_SUCCESS) {
97 		fprintf(stderr, "failed to convert qname: %d\n", result);
98 		return (result);
99 	}
100 
101 	/* Construct query message */
102 	message->opcode = dns_opcode_query;
103 	message->rdclass = dns_rdataclass_in;
104 
105 	result = dns_message_gettempname(message, &qname);
106 	if (result != ISC_R_SUCCESS)
107 		goto cleanup;
108 
109 	result = dns_message_gettemprdataset(message, &qrdataset);
110 	if (result != ISC_R_SUCCESS)
111 		goto cleanup;
112 
113 	dns_name_init(qname, NULL);
114 	dns_name_clone(qname0, qname);
115 	dns_rdataset_makequestion(qrdataset, message->rdclass, rdtype);
116 	ISC_LIST_APPEND(qname->list, qrdataset, link);
117 	dns_message_addname(message, qname, DNS_SECTION_QUESTION);
118 
119 	return (ISC_R_SUCCESS);
120 
121  cleanup:
122 	if (qname != NULL)
123 		dns_message_puttempname(message, &qname);
124 	if (qrdataset != NULL)
125 		dns_message_puttemprdataset(message, &qrdataset);
126 	dns_message_destroy(&message);
127 	return (result);
128 }
129 
130 static void
131 print_section(dns_message_t *message, int section, isc_buffer_t *buf) {
132 	isc_result_t result;
133 	isc_region_t r;
134 
135 	result = dns_message_sectiontotext(message, section,
136 					   &dns_master_style_full, 0, buf);
137 	if (result != ISC_R_SUCCESS)
138 		goto fail;
139 
140 	isc_buffer_usedregion(buf, &r);
141 	printf("%.*s", (int)r.length, (char *)r.base);
142 
143 	return;
144 
145  fail:
146 	fprintf(stderr, "failed to convert a section\n");
147 }
148 
149 int
150 main(int argc, char *argv[]) {
151 	int ch, i, gai_error;
152 	struct addrinfo hints, *res;
153 	isc_textregion_t tr;
154 	dns_client_t *client = NULL;
155 	isc_result_t result;
156 	isc_sockaddr_t sa;
157 	dns_message_t *qmessage, *rmessage;
158 	dns_rdatatype_t type = dns_rdatatype_a;
159 	isc_buffer_t *outputbuf;
160 
161 	while ((ch = isc_commandline_parse(argc, argv, "t:")) != -1) {
162 		switch (ch) {
163 		case 't':
164 			tr.base = isc_commandline_argument;
165 			tr.length = strlen(isc_commandline_argument);
166 			result = dns_rdatatype_fromtext(&type, &tr);
167 			if (result != ISC_R_SUCCESS) {
168 				fprintf(stderr,
169 					"invalid RRtype: %s\n",
170 					isc_commandline_argument);
171 				exit(1);
172 			}
173 			break;
174 		default:
175 			usage();
176 		}
177 	}
178 
179 	argc -= isc_commandline_index;
180 	argv += isc_commandline_index;
181 	if (argc < 2)
182 		usage();
183 
184 	isc_lib_register();
185 	result = dns_lib_init();
186 	if (result != ISC_R_SUCCESS) {
187 		fprintf(stderr, "dns_lib_init failed: %d\n", result);
188 		exit(1);
189 	}
190 
191 	result = dns_client_create(&client, 0);
192 	if (result != ISC_R_SUCCESS) {
193 		fprintf(stderr, "dns_client_create failed: %d\n", result);
194 		exit(1);
195 	}
196 
197 	/* Prepare message structures */
198 	mctx = NULL;
199 	qmessage = NULL;
200 	rmessage = NULL;
201 
202 	result = isc_mem_create(0, 0, &mctx);
203 	if (result != ISC_R_SUCCESS) {
204 		fprintf(stderr, "failed to create a memory context\n");
205 		exit(1);
206 	}
207 	result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &qmessage);
208 	if (result == ISC_R_SUCCESS) {
209 		result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
210 					    &rmessage);
211 	}
212 	if (result != ISC_R_SUCCESS) {
213 		fprintf(stderr, "failed to create messages\n");
214 		exit(1);
215 	}
216 
217 	/* Initialize the nameserver address */
218 	memset(&hints, 0, sizeof(hints));
219 	hints.ai_family = AF_UNSPEC;
220 	hints.ai_socktype = SOCK_DGRAM;
221 	hints.ai_protocol = IPPROTO_UDP;
222 #ifdef AI_NUMERICHOST
223 	hints.ai_flags = AI_NUMERICHOST;
224 #endif
225 	gai_error = getaddrinfo(argv[0], "53", &hints, &res);
226 	if (gai_error != 0) {
227 		fprintf(stderr, "getaddrinfo failed: %s\n",
228 			gai_strerror(gai_error));
229 		exit(1);
230 	}
231 	INSIST(res->ai_addrlen <= sizeof(sa.type));
232 	memmove(&sa.type, res->ai_addr, res->ai_addrlen);
233 	freeaddrinfo(res);
234 	sa.length = (unsigned int)res->ai_addrlen;
235 	ISC_LINK_INIT(&sa, link);
236 
237 	/* Construct qname */
238 	result = make_querymessage(qmessage, argv[1], type);
239 	if (result != ISC_R_SUCCESS) {
240 		fprintf(stderr, "failed to create a query\n");
241 		exit(1);
242 	}
243 
244 	/* Send request and wait for a response */
245 	result = dns_client_request(client, qmessage, rmessage, &sa, 0, 0,
246 				    NULL, 60, 0, 3);
247 	if (result != ISC_R_SUCCESS) {
248 		fprintf(stderr, "failed to get a response: %s\n",
249 			dns_result_totext(result));
250 	}
251 
252 	/* Dump the response */
253 	outputbuf = NULL;
254 	result = isc_buffer_allocate(mctx, &outputbuf, 65535);
255 	if (result != ISC_R_SUCCESS) {
256 		fprintf(stderr, "failed to allocate a result buffer\n");
257 		exit(1);
258 	}
259 	for (i = 0; i < DNS_SECTION_MAX; i++) {
260 		print_section(rmessage, i, outputbuf);
261 		isc_buffer_clear(outputbuf);
262 	}
263 	isc_buffer_free(&outputbuf);
264 
265 	/* Cleanup */
266 	dns_message_destroy(&qmessage);
267 	dns_message_destroy(&rmessage);
268 	isc_mem_destroy(&mctx);
269 	dns_client_destroy(&client);
270 	dns_lib_shutdown();
271 
272 	return (0);
273 }
274