1/* 2 * Copyright (C) 2009 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 /* Construct qname */ 81 namelen = strlen(namestr); 82 isc_buffer_init(&b, namestr, namelen); 83 isc_buffer_add(&b, namelen); 84 dns_fixedname_init(&fixedqname); 85 qname0 = dns_fixedname_name(&fixedqname); 86 result = dns_name_fromtext(qname0, &b, dns_rootname, 0, NULL); 87 if (result != ISC_R_SUCCESS) { 88 fprintf(stderr, "failed to convert qname: %d\n", result); 89 return (result); 90 } 91 92 /* Construct query message */ 93 message->opcode = dns_opcode_query; 94 message->rdclass = dns_rdataclass_in; 95 96 result = dns_message_gettempname(message, &qname); 97 if (result != ISC_R_SUCCESS) 98 goto cleanup; 99 100 result = dns_message_gettemprdataset(message, &qrdataset); 101 if (result != ISC_R_SUCCESS) 102 goto cleanup; 103 104 dns_name_init(qname, NULL); 105 dns_name_clone(qname0, qname); 106 dns_rdataset_init(qrdataset); 107 dns_rdataset_makequestion(qrdataset, message->rdclass, rdtype); 108 ISC_LIST_APPEND(qname->list, qrdataset, link); 109 dns_message_addname(message, qname, DNS_SECTION_QUESTION); 110 111 return (ISC_R_SUCCESS); 112 113 cleanup: 114 if (qname != NULL) 115 dns_message_puttempname(message, &qname); 116 if (qrdataset != NULL) 117 dns_message_puttemprdataset(message, &qrdataset); 118 if (message != NULL) 119 dns_message_destroy(&message); 120 return (result); 121} 122 123static void 124print_section(dns_message_t *message, int section, isc_buffer_t *buf) { 125 isc_result_t result; 126 isc_region_t r; 127 128 result = dns_message_sectiontotext(message, section, 129 &dns_master_style_full, 0, buf); 130 if (result != ISC_R_SUCCESS) 131 goto fail; 132 133 isc_buffer_usedregion(buf, &r); 134 printf("%.*s", (int)r.length, (char *)r.base); 135 136 return; 137 138 fail: 139 fprintf(stderr, "failed to convert a section\n"); 140} 141 142int 143main(int argc, char *argv[]) { 144 int ch, i, gai_error; 145 struct addrinfo hints, *res; 146 isc_textregion_t tr; 147 dns_client_t *client = NULL; 148 isc_result_t result; 149 isc_sockaddr_t sa; 150 dns_message_t *qmessage, *rmessage; 151 dns_rdatatype_t type = dns_rdatatype_a; 152 isc_buffer_t *outputbuf; 153 154 while ((ch = getopt(argc, argv, "t:")) != -1) { 155 switch (ch) { 156 case 't': 157 tr.base = optarg; 158 tr.length = strlen(optarg); 159 result = dns_rdatatype_fromtext(&type, &tr); 160 if (result != ISC_R_SUCCESS) { 161 fprintf(stderr, 162 "invalid RRtype: %s\n", optarg); 163 exit(1); 164 } 165 break; 166 default: 167 usage(); 168 } 169 } 170 171 argc -= optind; 172 argv += optind; 173 if (argc < 2) 174 usage(); 175 176 isc_lib_register(); 177 result = dns_lib_init(); 178 if (result != ISC_R_SUCCESS) { 179 fprintf(stderr, "dns_lib_init failed: %d\n", result); 180 exit(1); 181 } 182 183 result = dns_client_create(&client, 0); 184 if (result != ISC_R_SUCCESS) { 185 fprintf(stderr, "dns_client_create failed: %d\n", result); 186 exit(1); 187 } 188 189 /* Prepare message structures */ 190 mctx = NULL; 191 qmessage = NULL; 192 rmessage = NULL; 193 194 result = isc_mem_create(0, 0, &mctx); 195 if (result != ISC_R_SUCCESS) { 196 fprintf(stderr, "failed to create a memory context\n"); 197 exit(1); 198 } 199 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &qmessage); 200 if (result == ISC_R_SUCCESS) { 201 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, 202 &rmessage); 203 } 204 if (result != ISC_R_SUCCESS) { 205 fprintf(stderr, "failed to create messages\n"); 206 exit(1); 207 } 208 209 /* Initialize the nameserver address */ 210 memset(&hints, 0, sizeof(hints)); 211 hints.ai_family = AF_UNSPEC; 212 hints.ai_socktype = SOCK_DGRAM; 213 hints.ai_protocol = IPPROTO_UDP; 214 hints.ai_flags = AI_NUMERICHOST; 215 gai_error = getaddrinfo(argv[0], "53", &hints, &res); 216 if (gai_error != 0) { 217 fprintf(stderr, "getaddrinfo failed: %s\n", 218 gai_strerror(gai_error)); 219 exit(1); 220 } 221 INSIST(res->ai_addrlen <= sizeof(sa.type)); 222 memcpy(&sa.type, res->ai_addr, res->ai_addrlen); 223 freeaddrinfo(res); 224 sa.length = res->ai_addrlen; 225 ISC_LINK_INIT(&sa, link); 226 227 /* Construct qname */ 228 result = make_querymessage(qmessage, argv[1], type); 229 if (result != ISC_R_SUCCESS) { 230 fprintf(stderr, "failed to create a query\n"); 231 exit(1); 232 } 233 234 /* Send request and wait for a response */ 235 result = dns_client_request(client, qmessage, rmessage, &sa, 0, 0, 236 NULL, 60, 0, 3); 237 if (result != ISC_R_SUCCESS) { 238 fprintf(stderr, "failed to get a response: %s\n", 239 dns_result_totext(result)); 240 } 241 242 /* Dump the response */ 243 outputbuf = NULL; 244 result = isc_buffer_allocate(mctx, &outputbuf, 65535); 245 if (result != ISC_R_SUCCESS) { 246 fprintf(stderr, "failed to allocate a result buffer\n"); 247 exit(1); 248 } 249 for (i = 0; i < DNS_SECTION_MAX; i++) { 250 print_section(rmessage, i, outputbuf); 251 isc_buffer_clear(outputbuf); 252 } 253 isc_buffer_free(&outputbuf); 254 255 /* Cleanup */ 256 dns_message_destroy(&qmessage); 257 dns_message_destroy(&rmessage); 258 isc_mem_destroy(&mctx); 259 dns_client_destroy(&client); 260 dns_lib_shutdown(); 261 262 exit(0); 263} 264