sample-request.c revision 224090
1249259Sdim/* 2249259Sdim * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") 3249259Sdim * 4249259Sdim * Permission to use, copy, modify, and/or distribute this software for any 5249259Sdim * purpose with or without fee is hereby granted, provided that the above 6249259Sdim * copyright notice and this permission notice appear in all copies. 7249259Sdim * 8249259Sdim * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9249259Sdim * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10249259Sdim * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11249259Sdim * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12249259Sdim * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13249259Sdim * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14249259Sdim * PERFORMANCE OF THIS SOFTWARE. 15249259Sdim */ 16249259Sdim 17263508Sdim/* $Id: sample-request.c,v 1.5 2009-09-29 15:06:07 fdupont Exp $ */ 18263508Sdim 19249259Sdim#include <config.h> 20249259Sdim 21249259Sdim#include <sys/types.h> 22249259Sdim#include <sys/socket.h> 23249259Sdim 24249259Sdim#include <netinet/in.h> 25249259Sdim 26249259Sdim#include <arpa/inet.h> 27249259Sdim 28249259Sdim#include <unistd.h> 29249259Sdim#include <stdio.h> 30249259Sdim#include <stdlib.h> 31249259Sdim#include <string.h> 32249259Sdim#include <netdb.h> 33249259Sdim 34249259Sdim#include <isc/base64.h> 35249259Sdim#include <isc/buffer.h> 36249259Sdim#include <isc/lib.h> 37249259Sdim#include <isc/mem.h> 38249259Sdim#include <isc/sockaddr.h> 39249259Sdim#include <isc/util.h> 40249259Sdim 41249259Sdim#include <dns/client.h> 42249259Sdim#include <dns/fixedname.h> 43263508Sdim#include <dns/keyvalues.h> 44249259Sdim#include <dns/lib.h> 45249259Sdim#include <dns/masterdump.h> 46249259Sdim#include <dns/message.h> 47249259Sdim#include <dns/name.h> 48249259Sdim#include <dns/rdata.h> 49249259Sdim#include <dns/rdataset.h> 50249259Sdim#include <dns/rdatastruct.h> 51249259Sdim#include <dns/rdatatype.h> 52249259Sdim#include <dns/result.h> 53249259Sdim#include <dns/secalg.h> 54249259Sdim 55249259Sdim#include <dst/dst.h> 56249259Sdim 57249259Sdimstatic isc_mem_t *mctx; 58249259Sdimstatic dns_fixedname_t fixedqname; 59249259Sdim 60249259SdimISC_PLATFORM_NORETURN_PRE static void 61249259Sdimusage(void) ISC_PLATFORM_NORETURN_POST; 62249259Sdim 63249259Sdimstatic void 64249259Sdimusage(void) { 65249259Sdim fprintf(stderr, "sample-request [-t RRtype] server_address hostname\n"); 66249259Sdim 67249259Sdim exit(1); 68249259Sdim} 69249259Sdim 70249259Sdimstatic isc_result_t 71249259Sdimmake_querymessage(dns_message_t *message, const char *namestr, 72249259Sdim dns_rdatatype_t rdtype) 73249259Sdim{ 74249259Sdim dns_name_t *qname = NULL, *qname0; 75249259Sdim dns_rdataset_t *qrdataset = NULL; 76249259Sdim isc_result_t result; 77263508Sdim isc_buffer_t b; 78263508Sdim size_t namelen; 79249259Sdim 80249259Sdim /* Construct qname */ 81249259Sdim namelen = strlen(namestr); 82249259Sdim isc_buffer_init(&b, namestr, namelen); 83249259Sdim isc_buffer_add(&b, namelen); 84249259Sdim dns_fixedname_init(&fixedqname); 85249259Sdim qname0 = dns_fixedname_name(&fixedqname); 86249259Sdim result = dns_name_fromtext(qname0, &b, dns_rootname, 0, NULL); 87249259Sdim if (result != ISC_R_SUCCESS) { 88249259Sdim fprintf(stderr, "failed to convert qname: %d\n", result); 89256030Sdim return (result); 90256030Sdim } 91249259Sdim 92249259Sdim /* Construct query message */ 93249259Sdim message->opcode = dns_opcode_query; 94249259Sdim message->rdclass = dns_rdataclass_in; 95249259Sdim 96249259Sdim result = dns_message_gettempname(message, &qname); 97249259Sdim if (result != ISC_R_SUCCESS) 98249259Sdim goto cleanup; 99249259Sdim 100249259Sdim result = dns_message_gettemprdataset(message, &qrdataset); 101249259Sdim if (result != ISC_R_SUCCESS) 102249259Sdim goto cleanup; 103249259Sdim 104249259Sdim dns_name_init(qname, NULL); 105249259Sdim dns_name_clone(qname0, qname); 106249259Sdim dns_rdataset_init(qrdataset); 107249259Sdim dns_rdataset_makequestion(qrdataset, message->rdclass, rdtype); 108249259Sdim ISC_LIST_APPEND(qname->list, qrdataset, link); 109249259Sdim dns_message_addname(message, qname, DNS_SECTION_QUESTION); 110249259Sdim 111249259Sdim return (ISC_R_SUCCESS); 112249259Sdim 113249259Sdim cleanup: 114249259Sdim if (qname != NULL) 115249259Sdim dns_message_puttempname(message, &qname); 116249259Sdim if (qrdataset != NULL) 117249259Sdim dns_message_puttemprdataset(message, &qrdataset); 118249259Sdim if (message != NULL) 119249259Sdim dns_message_destroy(&message); 120249259Sdim return (result); 121249259Sdim} 122249259Sdim 123249259Sdimstatic void 124249259Sdimprint_section(dns_message_t *message, int section, isc_buffer_t *buf) { 125249259Sdim isc_result_t result; 126249259Sdim isc_region_t r; 127249259Sdim 128249259Sdim result = dns_message_sectiontotext(message, section, 129249259Sdim &dns_master_style_full, 0, buf); 130249259Sdim if (result != ISC_R_SUCCESS) 131249259Sdim goto fail; 132249259Sdim 133249259Sdim isc_buffer_usedregion(buf, &r); 134249259Sdim printf("%.*s", (int)r.length, (char *)r.base); 135249259Sdim 136249259Sdim return; 137249259Sdim 138249259Sdim fail: 139249259Sdim fprintf(stderr, "failed to convert a section\n"); 140249259Sdim} 141249259Sdim 142249259Sdimint 143249259Sdimmain(int argc, char *argv[]) { 144249259Sdim int ch, i, gai_error; 145249259Sdim struct addrinfo hints, *res; 146249259Sdim isc_textregion_t tr; 147249259Sdim dns_client_t *client = NULL; 148249259Sdim isc_result_t result; 149249259Sdim isc_sockaddr_t sa; 150249259Sdim dns_message_t *qmessage, *rmessage; 151249259Sdim dns_rdatatype_t type = dns_rdatatype_a; 152249259Sdim isc_buffer_t *outputbuf; 153249259Sdim 154249259Sdim while ((ch = getopt(argc, argv, "t:")) != -1) { 155249259Sdim switch (ch) { 156249259Sdim case 't': 157249259Sdim tr.base = optarg; 158249259Sdim tr.length = strlen(optarg); 159249259Sdim result = dns_rdatatype_fromtext(&type, &tr); 160249259Sdim if (result != ISC_R_SUCCESS) { 161249259Sdim fprintf(stderr, 162249259Sdim "invalid RRtype: %s\n", optarg); 163249259Sdim exit(1); 164263508Sdim } 165249259Sdim break; 166249259Sdim default: 167249259Sdim usage(); 168249259Sdim } 169249259Sdim } 170249259Sdim 171249259Sdim argc -= optind; 172249259Sdim argv += optind; 173249259Sdim if (argc < 2) 174249259Sdim usage(); 175249259Sdim 176249259Sdim isc_lib_register(); 177249259Sdim result = dns_lib_init(); 178249259Sdim if (result != ISC_R_SUCCESS) { 179249259Sdim fprintf(stderr, "dns_lib_init failed: %d\n", result); 180249259Sdim exit(1); 181249259Sdim } 182249259Sdim 183249259Sdim result = dns_client_create(&client, 0); 184249259Sdim if (result != ISC_R_SUCCESS) { 185249259Sdim fprintf(stderr, "dns_client_create failed: %d\n", result); 186249259Sdim exit(1); 187249259Sdim } 188249259Sdim 189249259Sdim /* Prepare message structures */ 190249259Sdim mctx = NULL; 191249259Sdim qmessage = NULL; 192249259Sdim rmessage = NULL; 193249259Sdim 194249259Sdim result = isc_mem_create(0, 0, &mctx); 195249259Sdim if (result != ISC_R_SUCCESS) { 196249259Sdim fprintf(stderr, "failed to create a memory context\n"); 197249259Sdim exit(1); 198249259Sdim } 199249259Sdim result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &qmessage); 200249259Sdim if (result == ISC_R_SUCCESS) { 201249259Sdim result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, 202249259Sdim &rmessage); 203249259Sdim } 204249259Sdim if (result != ISC_R_SUCCESS) { 205249259Sdim fprintf(stderr, "failed to create messages\n"); 206249259Sdim exit(1); 207249259Sdim } 208249259Sdim 209249259Sdim /* Initialize the nameserver address */ 210249259Sdim memset(&hints, 0, sizeof(hints)); 211249259Sdim hints.ai_family = AF_UNSPEC; 212249259Sdim hints.ai_socktype = SOCK_DGRAM; 213249259Sdim hints.ai_protocol = IPPROTO_UDP; 214249259Sdim hints.ai_flags = AI_NUMERICHOST; 215249259Sdim gai_error = getaddrinfo(argv[0], "53", &hints, &res); 216249259Sdim if (gai_error != 0) { 217249259Sdim fprintf(stderr, "getaddrinfo failed: %s\n", 218249259Sdim gai_strerror(gai_error)); 219249259Sdim exit(1); 220249259Sdim } 221249259Sdim INSIST(res->ai_addrlen <= sizeof(sa.type)); 222249259Sdim memcpy(&sa.type, res->ai_addr, res->ai_addrlen); 223249259Sdim freeaddrinfo(res); 224249259Sdim sa.length = res->ai_addrlen; 225249259Sdim ISC_LINK_INIT(&sa, link); 226249259Sdim 227249259Sdim /* Construct qname */ 228249259Sdim result = make_querymessage(qmessage, argv[1], type); 229249259Sdim if (result != ISC_R_SUCCESS) { 230249259Sdim fprintf(stderr, "failed to create a query\n"); 231249259Sdim exit(1); 232249259Sdim } 233249259Sdim 234249259Sdim /* Send request and wait for a response */ 235249259Sdim result = dns_client_request(client, qmessage, rmessage, &sa, 0, 0, 236249259Sdim NULL, 60, 0, 3); 237249259Sdim if (result != ISC_R_SUCCESS) { 238249259Sdim fprintf(stderr, "failed to get a response: %s\n", 239249259Sdim dns_result_totext(result)); 240249259Sdim } 241249259Sdim 242249259Sdim /* Dump the response */ 243249259Sdim outputbuf = NULL; 244249259Sdim result = isc_buffer_allocate(mctx, &outputbuf, 65535); 245249259Sdim if (result != ISC_R_SUCCESS) { 246249259Sdim fprintf(stderr, "failed to allocate a result buffer\n"); 247249259Sdim exit(1); 248249259Sdim } 249249259Sdim for (i = 0; i < DNS_SECTION_MAX; i++) { 250249259Sdim print_section(rmessage, i, outputbuf); 251249259Sdim isc_buffer_clear(outputbuf); 252249259Sdim } 253249259Sdim isc_buffer_free(&outputbuf); 254249259Sdim 255249259Sdim /* Cleanup */ 256249259Sdim dns_message_destroy(&qmessage); 257249259Sdim dns_message_destroy(&rmessage); 258249259Sdim isc_mem_destroy(&mctx); 259249259Sdim dns_client_destroy(&client); 260249259Sdim dns_lib_shutdown(); 261249259Sdim 262249259Sdim exit(0); 263249259Sdim} 264249259Sdim