1224090Sdougb/* 2262706Serwin * Copyright (C) 2009, 2012-2014 Internet Systems Consortium, Inc. ("ISC") 3224090Sdougb * 4224090Sdougb * Permission to use, copy, modify, and/or distribute this software for any 5224090Sdougb * purpose with or without fee is hereby granted, provided that the above 6224090Sdougb * copyright notice and this permission notice appear in all copies. 7224090Sdougb * 8224090Sdougb * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9224090Sdougb * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10224090Sdougb * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11224090Sdougb * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12224090Sdougb * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13224090Sdougb * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14224090Sdougb * PERFORMANCE OF THIS SOFTWARE. 15224090Sdougb */ 16224090Sdougb 17234010Sdougb/* $Id: sample-request.c,v 1.5 2009/09/29 15:06:07 fdupont Exp $ */ 18224090Sdougb 19224090Sdougb#include <config.h> 20224090Sdougb 21224090Sdougb#include <sys/types.h> 22224090Sdougb#include <sys/socket.h> 23224090Sdougb 24224090Sdougb#include <netinet/in.h> 25224090Sdougb 26224090Sdougb#include <arpa/inet.h> 27224090Sdougb 28224090Sdougb#include <unistd.h> 29224090Sdougb#include <stdio.h> 30224090Sdougb#include <stdlib.h> 31224090Sdougb#include <string.h> 32224090Sdougb#include <netdb.h> 33224090Sdougb 34224090Sdougb#include <isc/base64.h> 35224090Sdougb#include <isc/buffer.h> 36224090Sdougb#include <isc/lib.h> 37224090Sdougb#include <isc/mem.h> 38224090Sdougb#include <isc/sockaddr.h> 39224090Sdougb#include <isc/util.h> 40224090Sdougb 41224090Sdougb#include <dns/client.h> 42224090Sdougb#include <dns/fixedname.h> 43224090Sdougb#include <dns/keyvalues.h> 44224090Sdougb#include <dns/lib.h> 45224090Sdougb#include <dns/masterdump.h> 46224090Sdougb#include <dns/message.h> 47224090Sdougb#include <dns/name.h> 48224090Sdougb#include <dns/rdata.h> 49224090Sdougb#include <dns/rdataset.h> 50224090Sdougb#include <dns/rdatastruct.h> 51224090Sdougb#include <dns/rdatatype.h> 52224090Sdougb#include <dns/result.h> 53224090Sdougb#include <dns/secalg.h> 54224090Sdougb 55224090Sdougb#include <dst/dst.h> 56224090Sdougb 57224090Sdougbstatic isc_mem_t *mctx; 58224090Sdougbstatic dns_fixedname_t fixedqname; 59224090Sdougb 60224090SdougbISC_PLATFORM_NORETURN_PRE static void 61224090Sdougbusage(void) ISC_PLATFORM_NORETURN_POST; 62224090Sdougb 63224090Sdougbstatic void 64224090Sdougbusage(void) { 65224090Sdougb fprintf(stderr, "sample-request [-t RRtype] server_address hostname\n"); 66224090Sdougb 67224090Sdougb exit(1); 68224090Sdougb} 69224090Sdougb 70224090Sdougbstatic isc_result_t 71224090Sdougbmake_querymessage(dns_message_t *message, const char *namestr, 72224090Sdougb dns_rdatatype_t rdtype) 73224090Sdougb{ 74224090Sdougb dns_name_t *qname = NULL, *qname0; 75224090Sdougb dns_rdataset_t *qrdataset = NULL; 76224090Sdougb isc_result_t result; 77224090Sdougb isc_buffer_t b; 78224090Sdougb size_t namelen; 79224090Sdougb 80254402Serwin REQUIRE(message != NULL); 81254402Serwin REQUIRE(namestr != NULL); 82254402Serwin 83224090Sdougb /* Construct qname */ 84224090Sdougb namelen = strlen(namestr); 85254402Serwin isc_buffer_constinit(&b, namestr, namelen); 86224090Sdougb isc_buffer_add(&b, namelen); 87224090Sdougb dns_fixedname_init(&fixedqname); 88224090Sdougb qname0 = dns_fixedname_name(&fixedqname); 89224090Sdougb result = dns_name_fromtext(qname0, &b, dns_rootname, 0, NULL); 90224090Sdougb if (result != ISC_R_SUCCESS) { 91224090Sdougb fprintf(stderr, "failed to convert qname: %d\n", result); 92224090Sdougb return (result); 93224090Sdougb } 94224090Sdougb 95224090Sdougb /* Construct query message */ 96224090Sdougb message->opcode = dns_opcode_query; 97224090Sdougb message->rdclass = dns_rdataclass_in; 98224090Sdougb 99224090Sdougb result = dns_message_gettempname(message, &qname); 100224090Sdougb if (result != ISC_R_SUCCESS) 101224090Sdougb goto cleanup; 102224090Sdougb 103224090Sdougb result = dns_message_gettemprdataset(message, &qrdataset); 104224090Sdougb if (result != ISC_R_SUCCESS) 105224090Sdougb goto cleanup; 106224090Sdougb 107224090Sdougb dns_name_init(qname, NULL); 108224090Sdougb dns_name_clone(qname0, qname); 109224090Sdougb dns_rdataset_init(qrdataset); 110224090Sdougb dns_rdataset_makequestion(qrdataset, message->rdclass, rdtype); 111224090Sdougb ISC_LIST_APPEND(qname->list, qrdataset, link); 112224090Sdougb dns_message_addname(message, qname, DNS_SECTION_QUESTION); 113224090Sdougb 114224090Sdougb return (ISC_R_SUCCESS); 115224090Sdougb 116224090Sdougb cleanup: 117224090Sdougb if (qname != NULL) 118224090Sdougb dns_message_puttempname(message, &qname); 119224090Sdougb if (qrdataset != NULL) 120224090Sdougb dns_message_puttemprdataset(message, &qrdataset); 121254402Serwin dns_message_destroy(&message); 122224090Sdougb return (result); 123224090Sdougb} 124224090Sdougb 125224090Sdougbstatic void 126224090Sdougbprint_section(dns_message_t *message, int section, isc_buffer_t *buf) { 127224090Sdougb isc_result_t result; 128224090Sdougb isc_region_t r; 129224090Sdougb 130224090Sdougb result = dns_message_sectiontotext(message, section, 131224090Sdougb &dns_master_style_full, 0, buf); 132224090Sdougb if (result != ISC_R_SUCCESS) 133224090Sdougb goto fail; 134224090Sdougb 135224090Sdougb isc_buffer_usedregion(buf, &r); 136224090Sdougb printf("%.*s", (int)r.length, (char *)r.base); 137224090Sdougb 138224090Sdougb return; 139224090Sdougb 140224090Sdougb fail: 141224090Sdougb fprintf(stderr, "failed to convert a section\n"); 142224090Sdougb} 143224090Sdougb 144224090Sdougbint 145224090Sdougbmain(int argc, char *argv[]) { 146224090Sdougb int ch, i, gai_error; 147224090Sdougb struct addrinfo hints, *res; 148224090Sdougb isc_textregion_t tr; 149224090Sdougb dns_client_t *client = NULL; 150224090Sdougb isc_result_t result; 151224090Sdougb isc_sockaddr_t sa; 152224090Sdougb dns_message_t *qmessage, *rmessage; 153224090Sdougb dns_rdatatype_t type = dns_rdatatype_a; 154224090Sdougb isc_buffer_t *outputbuf; 155224090Sdougb 156224090Sdougb while ((ch = getopt(argc, argv, "t:")) != -1) { 157224090Sdougb switch (ch) { 158224090Sdougb case 't': 159224090Sdougb tr.base = optarg; 160224090Sdougb tr.length = strlen(optarg); 161224090Sdougb result = dns_rdatatype_fromtext(&type, &tr); 162224090Sdougb if (result != ISC_R_SUCCESS) { 163224090Sdougb fprintf(stderr, 164224090Sdougb "invalid RRtype: %s\n", optarg); 165224090Sdougb exit(1); 166224090Sdougb } 167224090Sdougb break; 168224090Sdougb default: 169224090Sdougb usage(); 170224090Sdougb } 171224090Sdougb } 172224090Sdougb 173224090Sdougb argc -= optind; 174224090Sdougb argv += optind; 175224090Sdougb if (argc < 2) 176224090Sdougb usage(); 177224090Sdougb 178224090Sdougb isc_lib_register(); 179224090Sdougb result = dns_lib_init(); 180224090Sdougb if (result != ISC_R_SUCCESS) { 181224090Sdougb fprintf(stderr, "dns_lib_init failed: %d\n", result); 182224090Sdougb exit(1); 183224090Sdougb } 184224090Sdougb 185224090Sdougb result = dns_client_create(&client, 0); 186224090Sdougb if (result != ISC_R_SUCCESS) { 187224090Sdougb fprintf(stderr, "dns_client_create failed: %d\n", result); 188224090Sdougb exit(1); 189224090Sdougb } 190224090Sdougb 191224090Sdougb /* Prepare message structures */ 192224090Sdougb mctx = NULL; 193224090Sdougb qmessage = NULL; 194224090Sdougb rmessage = NULL; 195224090Sdougb 196224090Sdougb result = isc_mem_create(0, 0, &mctx); 197224090Sdougb if (result != ISC_R_SUCCESS) { 198224090Sdougb fprintf(stderr, "failed to create a memory context\n"); 199224090Sdougb exit(1); 200224090Sdougb } 201224090Sdougb result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &qmessage); 202224090Sdougb if (result == ISC_R_SUCCESS) { 203224090Sdougb result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, 204224090Sdougb &rmessage); 205224090Sdougb } 206224090Sdougb if (result != ISC_R_SUCCESS) { 207224090Sdougb fprintf(stderr, "failed to create messages\n"); 208224090Sdougb exit(1); 209224090Sdougb } 210224090Sdougb 211224090Sdougb /* Initialize the nameserver address */ 212224090Sdougb memset(&hints, 0, sizeof(hints)); 213224090Sdougb hints.ai_family = AF_UNSPEC; 214224090Sdougb hints.ai_socktype = SOCK_DGRAM; 215224090Sdougb hints.ai_protocol = IPPROTO_UDP; 216224090Sdougb hints.ai_flags = AI_NUMERICHOST; 217224090Sdougb gai_error = getaddrinfo(argv[0], "53", &hints, &res); 218224090Sdougb if (gai_error != 0) { 219224090Sdougb fprintf(stderr, "getaddrinfo failed: %s\n", 220224090Sdougb gai_strerror(gai_error)); 221224090Sdougb exit(1); 222224090Sdougb } 223224090Sdougb INSIST(res->ai_addrlen <= sizeof(sa.type)); 224262706Serwin memmove(&sa.type, res->ai_addr, res->ai_addrlen); 225224090Sdougb freeaddrinfo(res); 226224090Sdougb sa.length = res->ai_addrlen; 227224090Sdougb ISC_LINK_INIT(&sa, link); 228224090Sdougb 229224090Sdougb /* Construct qname */ 230224090Sdougb result = make_querymessage(qmessage, argv[1], type); 231224090Sdougb if (result != ISC_R_SUCCESS) { 232224090Sdougb fprintf(stderr, "failed to create a query\n"); 233224090Sdougb exit(1); 234224090Sdougb } 235224090Sdougb 236224090Sdougb /* Send request and wait for a response */ 237224090Sdougb result = dns_client_request(client, qmessage, rmessage, &sa, 0, 0, 238224090Sdougb NULL, 60, 0, 3); 239224090Sdougb if (result != ISC_R_SUCCESS) { 240224090Sdougb fprintf(stderr, "failed to get a response: %s\n", 241224090Sdougb dns_result_totext(result)); 242224090Sdougb } 243224090Sdougb 244224090Sdougb /* Dump the response */ 245224090Sdougb outputbuf = NULL; 246224090Sdougb result = isc_buffer_allocate(mctx, &outputbuf, 65535); 247224090Sdougb if (result != ISC_R_SUCCESS) { 248224090Sdougb fprintf(stderr, "failed to allocate a result buffer\n"); 249224090Sdougb exit(1); 250224090Sdougb } 251224090Sdougb for (i = 0; i < DNS_SECTION_MAX; i++) { 252224090Sdougb print_section(rmessage, i, outputbuf); 253224090Sdougb isc_buffer_clear(outputbuf); 254224090Sdougb } 255224090Sdougb isc_buffer_free(&outputbuf); 256224090Sdougb 257224090Sdougb /* Cleanup */ 258224090Sdougb dns_message_destroy(&qmessage); 259224090Sdougb dns_message_destroy(&rmessage); 260224090Sdougb isc_mem_destroy(&mctx); 261224090Sdougb dns_client_destroy(&client); 262224090Sdougb dns_lib_shutdown(); 263224090Sdougb 264254402Serwin return (0); 265224090Sdougb} 266