Files
bind9/lib/samples/sample-request.c
T

270 lines
6.2 KiB
C

/*
* 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.
*/
#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 /* ifndef WIN32 */
#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 /* ifdef AI_NUMERICHOST */
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);
}