diff options
Diffstat (limited to '')
-rw-r--r-- | lib/samples/sample-request.c | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/lib/samples/sample-request.c b/lib/samples/sample-request.c new file mode 100644 index 0000000..e60a6df --- /dev/null +++ b/lib/samples/sample-request.c @@ -0,0 +1,265 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + + +#include <config.h> + +#ifndef WIN32 +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> + +#include <arpa/inet.h> + +#include <netdb.h> +#include <unistd.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/base64.h> +#include <isc/buffer.h> +#include <isc/commandline.h> +#include <isc/lib.h> +#include <isc/mem.h> +#include <isc/print.h> +#include <isc/sockaddr.h> +#include <isc/util.h> + +#include <dns/client.h> +#include <dns/fixedname.h> +#include <dns/keyvalues.h> +#include <dns/lib.h> +#include <dns/masterdump.h> +#include <dns/message.h> +#include <dns/name.h> +#include <dns/rdata.h> +#include <dns/rdataset.h> +#include <dns/rdatastruct.h> +#include <dns/rdatatype.h> +#include <dns/result.h> +#include <dns/secalg.h> + +#include <dst/dst.h> + +static isc_mem_t *mctx; +static dns_fixedname_t fixedqname; + +ISC_PLATFORM_NORETURN_PRE static void +usage(void) ISC_PLATFORM_NORETURN_POST; + +static void +usage(void) { + fprintf(stderr, "sample-request [-t RRtype] server_address hostname\n"); + + exit(1); +} + +static isc_result_t +make_querymessage(dns_message_t *message, const char *namestr, + dns_rdatatype_t rdtype) +{ + dns_name_t *qname = NULL, *qname0; + dns_rdataset_t *qrdataset = NULL; + isc_result_t result; + isc_buffer_t b; + unsigned int namelen; + + REQUIRE(message != NULL); + REQUIRE(namestr != NULL); + + /* Construct qname */ + namelen = strlen(namestr); + isc_buffer_constinit(&b, namestr, namelen); + isc_buffer_add(&b, namelen); + qname0 = dns_fixedname_initname(&fixedqname); + result = dns_name_fromtext(qname0, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to convert qname: %u\n", result); + return (result); + } + + /* Construct query message */ + message->opcode = dns_opcode_query; + message->rdclass = dns_rdataclass_in; + + result = dns_message_gettempname(message, &qname); + if (result != ISC_R_SUCCESS) + goto cleanup; + + result = dns_message_gettemprdataset(message, &qrdataset); + if (result != ISC_R_SUCCESS) + goto cleanup; + + dns_name_init(qname, NULL); + dns_name_clone(qname0, qname); + dns_rdataset_makequestion(qrdataset, message->rdclass, rdtype); + ISC_LIST_APPEND(qname->list, qrdataset, link); + dns_message_addname(message, qname, DNS_SECTION_QUESTION); + + return (ISC_R_SUCCESS); + + cleanup: + if (qname != NULL) + dns_message_puttempname(message, &qname); + if (qrdataset != NULL) + dns_message_puttemprdataset(message, &qrdataset); + dns_message_destroy(&message); + return (result); +} + +static void +print_section(dns_message_t *message, int section, isc_buffer_t *buf) { + isc_result_t result; + isc_region_t r; + + result = dns_message_sectiontotext(message, section, + &dns_master_style_full, 0, buf); + if (result != ISC_R_SUCCESS) + goto fail; + + isc_buffer_usedregion(buf, &r); + printf("%.*s", (int)r.length, (char *)r.base); + + return; + + fail: + fprintf(stderr, "failed to convert a section\n"); +} + +int +main(int argc, char *argv[]) { + int ch, i, gaierror; + struct addrinfo hints, *res; + isc_textregion_t tr; + dns_client_t *client = NULL; + isc_result_t result; + isc_sockaddr_t sa; + dns_message_t *qmessage, *rmessage; + dns_rdatatype_t type = dns_rdatatype_a; + isc_buffer_t *outputbuf; + + while ((ch = isc_commandline_parse(argc, argv, "t:")) != -1) { + switch (ch) { + case 't': + tr.base = isc_commandline_argument; + tr.length = strlen(isc_commandline_argument); + result = dns_rdatatype_fromtext(&type, &tr); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, + "invalid RRtype: %s\n", + isc_commandline_argument); + exit(1); + } + break; + default: + usage(); + } + } + + argc -= isc_commandline_index; + argv += isc_commandline_index; + if (argc < 2) + usage(); + + isc_lib_register(); + result = dns_lib_init(); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_lib_init failed: %u\n", result); + exit(1); + } + + result = dns_client_create(&client, 0); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "dns_client_create failed: %u\n", result); + exit(1); + } + + /* Prepare message structures */ + mctx = NULL; + qmessage = NULL; + rmessage = NULL; + + result = isc_mem_create(0, 0, &mctx); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to create a memory context\n"); + exit(1); + } + result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &qmessage); + if (result == ISC_R_SUCCESS) { + result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, + &rmessage); + } + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to create messages\n"); + exit(1); + } + + /* Initialize the nameserver address */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; +#ifdef AI_NUMERICHOST + hints.ai_flags = AI_NUMERICHOST; +#endif + gaierror = getaddrinfo(argv[0], "53", &hints, &res); + if (gaierror != 0) { + fprintf(stderr, "getaddrinfo failed: %s\n", + gai_strerror(gaierror)); + exit(1); + } + INSIST(res->ai_addrlen <= sizeof(sa.type)); + memmove(&sa.type, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + sa.length = (unsigned int)res->ai_addrlen; + ISC_LINK_INIT(&sa, link); + + /* Construct qname */ + result = make_querymessage(qmessage, argv[1], type); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to create a query\n"); + exit(1); + } + + /* Send request and wait for a response */ + result = dns_client_request(client, qmessage, rmessage, &sa, 0, 0, + NULL, 60, 0, 3); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to get a response: %s\n", + dns_result_totext(result)); + } + + /* Dump the response */ + outputbuf = NULL; + result = isc_buffer_allocate(mctx, &outputbuf, 65535); + if (result != ISC_R_SUCCESS) { + fprintf(stderr, "failed to allocate a result buffer\n"); + exit(1); + } + for (i = 0; i < DNS_SECTION_MAX; i++) { + print_section(rmessage, i, outputbuf); + isc_buffer_clear(outputbuf); + } + isc_buffer_free(&outputbuf); + + /* Cleanup */ + dns_message_destroy(&qmessage); + dns_message_destroy(&rmessage); + isc_mem_destroy(&mctx); + dns_client_destroy(&client); + dns_lib_shutdown(); + + return (0); +} |