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