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
usage(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
make_querymessage(dns_message_t * message,const char * namestr,dns_rdatatype_t rdtype)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
print_section(dns_message_t * message,int section,isc_buffer_t * buf)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
main(int argc,char * argv[])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