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