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