diff --git a/bin/dig/Makefile b/bin/dig/Makefile new file mode 100644 index 0000000000..b1a2734e25 --- /dev/null +++ b/bin/dig/Makefile @@ -0,0 +1,262 @@ +# Generated automatically from Makefile.in by configure. +# Copyright (C) 1998, 1999, 2000 Internet Software Consortium. +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +# CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +# PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +# SOFTWARE. + +srcdir = . +top_srcdir = ../.. + + +# Copyright (C) 1999, 2000 Internet Software Consortium. +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +# CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +# PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +# SOFTWARE. + +# Search for machine-generated header files in the build tree, +# and for normal headers in the source tree (${top_srcdir}). +# We only need to look in OS-specific subdirectories for the +# latter case, because there are no machine-generated OS-specific +# headers. + +ISC_INCLUDES = -I/export/home/mws/bind9/lib/isc/include \ + -I${top_srcdir}/lib/isc \ + -I${top_srcdir}/lib/isc/include \ + -I${top_srcdir}/lib/isc/unix/include \ + -I${top_srcdir}/lib/isc/pthreads/include + +DNS_INCLUDES = -I/export/home/mws/bind9/lib/dns/include \ + -I${top_srcdir}/lib/dns/include \ + -I${top_srcdir}/lib/dns/sec/dst/include + +OMAPI_INCLUDES = -I/export/home/mws/bind9/lib/omapi/include \ + -I${top_srcdir}/lib/omapi/include + +LWRES_INCLUDES = -I/export/home/mws/bind9/lib/lwres/include \ + -I${top_srcdir}/lib/lwres/include + +TEST_INCLUDES = \ + -I${top_srcdir}/lib/tests/include + +CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} ${LWRES_INCLUDES} \ + ${OMAPI_INCLUDES} -I./unix/include -I./include + +CDEFINES = +CWARNINGS = + +DNSLIBS = ../../lib/dns/libdns.a +ISCLIBS = ../../lib/isc/libisc.a +OMAPILIBS = ../../lib/omapi/libomapi.a +LWRESLIBS = ../../lib/lwres/liblwres.a + +DNSDEPLIBS = ../../lib/dns/libdns.a +ISCDEPLIBS = ../../lib/isc/libisc.a +OMAPIDEPLIBS = ../../lib/omapi/libomapi.a +LWRESDEPLIBS = ../../lib/lwres/liblwres.a + +LIBS = -lnsl -lsocket -lpthread -lthread + +SUBDIRS = db dst master mem names rbt sockaddr tasks timers + +# Alphabetically +TARGETS = dig + +# Alphabetically +SRCS = dig.c\ + printmsg.c + + + +# Copyright (C) 1998, 1999, 2000 Internet Software Consortium. +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +# CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +# PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +# SOFTWARE. + +### +### Common Makefile rules for BIND 9. +### + +### +### Paths +### +### Note: paths that vary by Makefile MUST NOT be listed +### here, or they won't get expanded correctly. + +prefix = /usr/local +exec_prefix = ${prefix} +bindir = ${exec_prefix}/bin +sbindir = ${exec_prefix}/sbin +includedir = ${prefix}/include +libdir = ${exec_prefix}/lib +sysconfdir = /etc +localstatedir = /var + +DESTDIR = + + + +top_builddir = /export/home/mws/bind9 + +### +### All +### +### Makefile may define: +### TARGETS + +all: subdirs ${TARGETS} + +### +### Subdirectories +### +### Makefile may define: +### SUBDIRS + +ALL_SUBDIRS = ${SUBDIRS} nulldir + +# +# We use a single-colon rule so that additional dependencies of +# subdirectories can be specified after the inclusion of this file. +# The "depend" target is treated the same way. +# +subdirs: + @for i in ${ALL_SUBDIRS}; do \ + if [ "$$i" != "nulldir" -a -d $$i ]; then \ + echo "making all in `pwd`/$$i"; \ + (cd $$i; ${MAKE} ${MAKEDEFS} all); \ + fi \ + done + +install clean distclean:: + @for i in ${ALL_SUBDIRS}; do \ + if [ "$$i" != "nulldir" -a -d $$i ]; then \ + echo "making $@ in `pwd`/$$i"; \ + (cd $$i; ${MAKE} ${MAKEDEFS} $@); \ + fi \ + done + +### +### C Programs +### +### Makefile must define +### CC +### Makefile may define +### CFLAGS +### CINCLUDES +### CDEFINES +### CWARNINGS + +CC = gcc +CFLAGS = -g -O2 +STD_CINCLUDES = +STD_CDEFINES = +STD_CWARNINGS = -W -Wall -Wmissing-prototypes + +.SUFFIXES: +.SUFFIXES: .c .o + +ALWAYS_INCLUDES = -I${top_builddir} +ALWAYS_DEFINES = -D_REENTRANT +ALWAYS_WARNINGS = + +ALL_CPPFLAGS = \ + ${ALWAYS_INCLUDES} ${CINCLUDES} ${STD_CINCLUDES} \ + ${ALWAYS_DEFINES} ${CDEFINES} ${STD_CDEFINES} + +ALL_CFLAGS = ${CFLAGS} \ + ${ALL_CPPFLAGS} \ + ${ALWAYS_WARNINGS} ${STD_CWARNINGS} ${CWARNINGS} + +.c.o: + ${LIBTOOL} ${CC} ${ALL_CFLAGS} -c $< + +SHELL = /bin/sh +LIBTOOL = + +MKDEP = ${SHELL} ${top_builddir}/make/mkdep + +clean distclean:: + rm -f *.o *.lo *.la core *.core + rm -rf .libs + +distclean:: + rm -f Makefile + +depend: + @for i in ${ALL_SUBDIRS}; do \ + if [ "$$i" != "nulldir" -a -d $$i ]; then \ + echo "making depend in `pwd`/$$i"; \ + (cd $$i; ${MAKE} ${MAKEDEFS} $@); \ + fi \ + done + @if [ X"${SRCS}" != X -a X"${PSRCS}" != X ] ; then \ + echo ${MKDEP} ${ALL_CPPFLAGS} ${SRCS}; \ + ${MKDEP} ${ALL_CPPFLAGS} ${SRCS}; \ + echo ${MKDEP} -ap ${ALL_CPPFLAGS} ${PSRCS}; \ + ${MKDEP} -ap ${ALL_CPPFLAGS} ${PSRCS}; \ + elif [ X"${SRCS}" != X ] ; then \ + echo ${MKDEP} ${ALL_CPPFLAGS} ${SRCS}; \ + ${MKDEP} ${ALL_CPPFLAGS} ${SRCS}; \ + elif [ X"${PSRCS}" != X ] ; then \ + echo ${MKDEP} ${ALL_CPPFLAGS} ${PSRCS}; \ + ${MKDEP} -p ${ALL_CPPFLAGS} ${PSRCS}; \ + fi + +FORCE: + +### +### Libraries +### + +AR = /usr/ccs/bin/ar +ARFLAGS = cruv +RANLIB = ranlib + +### +### Installation +### + +INSTALL = /export/home/mws/bind9/install-sh -c +INSTALL_PROGRAM = ${INSTALL} +INSTALL_DATA = ${INSTALL} -m 644 + +all: ${TARGETS} + +dig: dig.o printmsg.o ${ISCDEPLIBS} ${DNSDEPLIBS} + ${LIBTOOL} ${CC} ${CFLAGS} -o $@ dig.o printmsg.o\ + ${DNSLIBS} ${ISCLIBS} ${LIBS} +distclean:: + rm -f headerdep_test.sh + +clean distclean:: + rm -f ${TARGETS} ${XTARGETS} + rm -f t_journal diff --git a/bin/dig/dig.c b/bin/dig/dig.c new file mode 100644 index 0000000000..92f69f9e9d --- /dev/null +++ b/bin/dig/dig.c @@ -0,0 +1,749 @@ +/* + * Copyright (C) 1999, 2000 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include + +extern int h_errno; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#undef DEBUG +#undef MEMDEBUG + +ISC_LIST(dig_lookup_t) lookup_list; +ISC_LIST(dig_server_t) server_list; + +isc_boolean_t tcp_mode=ISC_FALSE, + recurse=ISC_TRUE, + have_ipv6=ISC_FALSE; +in_port_t port; +unsigned int timeout; +isc_mem_t *mctx=NULL; +isc_taskmgr_t *taskmgr=NULL; +isc_task_t *task=NULL; +isc_timermgr_t *timermgr=NULL; +isc_socketmgr_t *socketmgr=NULL; +dns_messageid_t id; +dns_name_t rootorg; +char *rootspace[BUFSIZE]; +isc_buffer_t rootbuf; +int sendcount=0; + +static void +fatal(char *format, ...) { + va_list args; + + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); +#ifdef NEVER + free_lists(); +#endif + exit(1); +} + +static inline void +check_result(isc_result_t result, char *msg) { + if (result != ISC_R_SUCCESS) + fatal("%s: %s", msg, isc_result_totext(result)); +} + +static isc_boolean_t +isclass(char *text) { + /* Tests if a field is a class, without needing isc libs + initialized. This list will have to be manually kept in + sync with what the libs support. */ + static const char *classlist[] = {"in", "hs", "any"}; + static const int numclasses = 3; + int i; + + for (i=0;i 0; argc--, argv++) { + if ((strncmp(argv[0],"@",1) == 0) + && (!is_batchfile)) { + srv=isc_mem_allocate(mctx, sizeof(struct dig_server)); + if (srv == NULL) + fatal ("Memory allocation failure."); + strncpy(srv->servername,&argv[0][1],MXNAME-1); + ISC_LIST_APPEND(server_list, srv, link); + } else if ((strcmp(argv[0],"+vc") == 0) + && (!is_batchfile)) { + tcp_mode = ISC_TRUE; + } else if (strcmp(argv[0],"+norecurs") == 0) { + recurse = ISC_FALSE; + } else if (strcmp(argv[0],"-f") == 0) { + batchname=argv[1]; + argv++; + argc--; + } else { + if (have_host) { + ENSURE ( lookup != NULL ); + if (isclass(argv[0])) { + strncpy (lookup->rctext,argv[0], + MXRD); + continue; + } else if (istype(argv[0])) { + strncpy (lookup->rttext,argv[0], + MXRD); + continue; + } + } + lookup = isc_mem_allocate (mctx, + sizeof(struct dig_lookup)); + if (lookup == NULL) + fatal ("Memory allocation failure."); + lookup->pending = ISC_FALSE; + strncpy (lookup->textname,argv[0], MXNAME-1); + lookup->rttext[0]=0; + lookup->rctext[0]=0; + lookup->namespace[0]=0; + lookup->sendspace[0]=0; + lookup->sendmsg=NULL; + lookup->name=NULL; + lookup->timer = NULL; + ISC_LIST_INIT(lookup->q); + ISC_LIST_APPEND(lookup_list, lookup, link); + have_host = ISC_TRUE; + } + } + if (batchname != NULL) { + fp = fopen (batchname, "r"); + if (fp == NULL) { + perror (batchname); + fatal ("Couldn't open specified batch file."); + } + while (fgets (batchline, MXNAME, fp) != 0) { + bargc = sscanf ("%s %s %s %s %s %s %s", + bargv[1], bargv[2], bargv[3], + bargv[4], bargv[5], bargv[6], + bargv[7]); + bargc++; + strcpy (bargv[0], "dig"); + parse_args(ISC_TRUE, bargc, (char**)bargv); + } + } + if (lookup_list.head == NULL) { + lookup = isc_mem_allocate (mctx, + sizeof(struct dig_lookup)); + if (lookup == NULL) + fatal ("Memory allocation failure."); + lookup->pending = ISC_FALSE; + lookup->rctext[0]=0; + lookup->namespace[0]=0; + lookup->sendspace[0]=0; + lookup->sendmsg=NULL; + lookup->name=NULL; + lookup->timer = NULL; + ISC_LIST_INIT(lookup->q); + strcpy (lookup->textname,"."); + strcpy (lookup->rttext, "NS"); + lookup->rctext[0]=0; + ISC_LIST_APPEND(lookup_list, lookup, link); + } +} + +static void +setup_system() { + char rcinput[MXNAME]; + FILE *fp; + char *ptr; + dig_server_t *srv; + + port = 53; + timeout = 5; + id = getpid()<<8; + + if (server_list.head == NULL) { + fp = fopen (RESOLVCONF, "r"); + if (fp != NULL) { + while (fgets(rcinput, MXNAME, fp) != 0) { + ptr = strtok (rcinput, " \t"); + if (ptr != NULL) { + if (strcasecmp(ptr,"nameserver") + == 0) { + ptr = strtok (NULL, " \t"); + if (ptr != NULL) { + srv=isc_mem_allocate (mctx, sizeof(struct dig_server)); + if (srv == NULL) + fatal ("Memory allocation failure."); + strncpy(srv->servername, ptr,MXNAME-1); + ISC_LIST_APPEND(server_list, srv, link); + } + } + } + } + fclose (fp); + } + } + if (server_list.head == NULL) { + srv = isc_mem_allocate(mctx, sizeof(dig_server_t)); + if (srv == NULL) + fatal ("Memory allocation failure"); + strcpy (srv->servername, "127.0.0.1"); + ISC_LIST_APPEND(server_list, srv, link); + } +} + +static void +setup_libs() { + isc_result_t result; + isc_buffer_t b; + + result = isc_app_start(); + check_result (result, "isc_app_start"); + + result = isc_net_probeipv4(); + check_result (result, "isc_net_probeipv4"); + + result = isc_net_probeipv6(); + if (result == ISC_R_SUCCESS) + have_ipv6=ISC_TRUE; + + result = isc_mem_create (0, 0, &mctx); + check_result (result, "isc_mem_create"); + + result = isc_taskmgr_create (mctx, 1, 0, &taskmgr); + check_result (result, "isc_taskmgr_create"); + + result = isc_task_create (taskmgr, 0, &task); + check_result (result, "isc_task_create"); + + result = isc_timermgr_create (mctx, &timermgr); + check_result (result, "isc_timermgr_create"); + + result = isc_socketmgr_create (mctx, &socketmgr); + check_result (result, "isc_socketmgr_create"); + + isc_buffer_init (&b, ".", 1, ISC_BUFFERTYPE_TEXT); + isc_buffer_add (&b, 1); + dns_name_init (&rootorg, NULL); + isc_buffer_init (&rootbuf, rootspace, BUFSIZE, + ISC_BUFFERTYPE_BINARY); + result = dns_name_fromtext (&rootorg, &b, NULL, + ISC_FALSE, &rootbuf); + check_result (result, "dns_name_fromtext"); + + + +} + +static void +add_type(dns_message_t *message, dns_name_t *name, dns_rdataclass_t rdclass, + dns_rdatatype_t rdtype) +{ + dns_rdataset_t *rdataset; + isc_result_t result; + + rdataset = NULL; + result = dns_message_gettemprdataset(message, &rdataset); + check_result(result, "dns_message_gettemprdataset()"); + dns_rdataset_init(rdataset); + dns_rdataset_makequestion(rdataset, rdclass, rdtype); + ISC_LIST_APPEND(name->list, rdataset, link); +} + +static void +setup_lookup(dig_lookup_t *lookup) { + isc_result_t result; + int len; + dns_rdatatype_t rdtype; + dns_rdataclass_t rdclass; + dig_server_t *serv; + dig_query_t *query; + isc_textregion_t r; + isc_buffer_t b; + +#ifdef DEBUG + printf ("Setting up for looking up %s\n",lookup->textname); +#endif + len=strlen(lookup->textname); + isc_buffer_init (&b, lookup->textname, len, + ISC_BUFFERTYPE_TEXT); + isc_buffer_add (&b, len); + + result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, + &lookup->sendmsg); + check_result (result, "dns_message_create"); + + + result = dns_message_gettempname(lookup->sendmsg, &lookup->name); + check_result (result,"dns_message_gettempname"); + dns_name_init (lookup->name, NULL); + + isc_buffer_init (&lookup->namebuf, lookup->namespace, BUFSIZE, + ISC_BUFFERTYPE_BINARY); + + result = dns_name_fromtext (lookup->name, &b, &rootorg, + ISC_FALSE, &lookup->namebuf); + check_result (result, "dns_name_fromtext"); + + if (lookup->rctext[0] == 0) + strcpy (lookup->rctext, "IN"); + if (lookup->rttext[0] == 0) + strcpy (lookup->rttext, "A"); + + lookup->sendmsg->id = id++; + lookup->sendmsg->opcode = dns_opcode_query; + if (recurse) + lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD; + + dns_message_addname(lookup->sendmsg, lookup->name, + DNS_SECTION_QUESTION); + + + r.base=lookup->rttext; + r.length=strlen(lookup->rttext); + result = dns_rdatatype_fromtext(&rdtype, &r); + check_result (result, "dns_rdatatype_fromtext"); + r.base=lookup->rctext; + r.length=strlen(lookup->rctext); + result = dns_rdataclass_fromtext(&rdclass, &r); + check_result (result, "dns_rdataclass_fromtext"); + add_type(lookup->sendmsg, lookup->name, rdclass, rdtype); + + isc_buffer_init (&lookup->sendbuf, lookup->sendspace, COMMSIZE, + ISC_BUFFERTYPE_BINARY); + result = dns_message_renderbegin(lookup->sendmsg, &lookup->sendbuf); + check_result (result, "dns_message_renderbegin"); + result = dns_message_rendersection(lookup->sendmsg, + DNS_SECTION_QUESTION,0); + check_result (result, "dns_message_rendersection"); + result = dns_message_renderend(lookup->sendmsg); + check_result (result, "dns_message_renderend"); + + lookup->pending = ISC_FALSE; + + for (serv = ISC_LIST_HEAD(server_list); + serv != NULL; + serv = ISC_LIST_NEXT(serv, link)) { + query = isc_mem_allocate(mctx, sizeof(dig_query_t)); + if (query == NULL) + fatal ("Memory allocation failure."); + query->lookup = lookup; + query->working = ISC_FALSE; + query->waiting_connect = ISC_FALSE; + query->first_pass = ISC_TRUE; + query->first_soa_rcvd = ISC_FALSE; + query->servname = serv->servername; + ISC_LIST_INIT (query->sendlist); + ISC_LIST_INIT (query->recvlist); + ISC_LIST_INIT (query->lengthlist); + query->sock = NULL; + + isc_buffer_init (&query->recvbuf, query->recvspace, + COMMSIZE, ISC_BUFFERTYPE_BINARY); + isc_buffer_init (&query->lengthbuf, query->lengthspace, + 2, ISC_BUFFERTYPE_BINARY); + + ISC_LIST_ENQUEUE (query->recvlist, &query->recvbuf, link); + ISC_LIST_ENQUEUE (query->sendlist, &lookup->sendbuf, link); + ISC_LIST_ENQUEUE (query->lengthlist, &query->lengthbuf, link); + ISC_LIST_ENQUEUE (lookup->q, query, link); + } +} + +static void +send_done (isc_task_t *task, isc_event_t *event) { + UNUSED (task); + isc_event_free (&event); +} + +static void +cancel_lookup (dig_lookup_t *lookup) { + dig_query_t *query; + + if (!lookup->pending) + return; + lookup->pending = ISC_FALSE; + for (query = ISC_LIST_HEAD(lookup->q); + query != NULL; + query = ISC_LIST_NEXT(query, link)) { + if (query->working) { + isc_socket_cancel (query->sock, task, + ISC_SOCKCANCEL_ALL); + } + } +} + +static void +do_lookup_udp (dig_lookup_t *lookup); + +static void +check_next_lookup (dig_lookup_t *lookup) { + dig_lookup_t *next; + dig_query_t *query; + isc_boolean_t still_working=ISC_FALSE; + + for (query = ISC_LIST_HEAD(lookup->q); + query != NULL; + query = ISC_LIST_NEXT(query, link)) { + if (query->working) { + still_working=ISC_TRUE; + } + } + if (still_working) + return; + + next = ISC_LIST_NEXT (lookup, link); + if (next == NULL) { +#ifdef DEBUG + puts ("Shutting Down."); +#endif + isc_app_shutdown(); + return; + } + + setup_lookup(next); +#ifdef NEVER + if (tcp_mode) + do_lookup_tcp(next); + else +#endif + do_lookup_udp(next); + +} + +static void +recv_timeout (isc_task_t *task, isc_event_t *event) { + dig_lookup_t *lookup; + dig_query_t *q=NULL; + isc_result_t result; + isc_buffer_t *b; + isc_region_t r; + + lookup=event->ev_arg; + + REQUIRE (event->ev_type == ISC_TIMEREVENT_IDLE); + + result = isc_buffer_allocate(mctx, &b, 256, ISC_BUFFERTYPE_TEXT); + check_result (result, "isc_buffer_allocate"); + for (q = ISC_LIST_HEAD(lookup->q); + q != NULL; + q = ISC_LIST_NEXT(q, link)) { + isc_buffer_clear (b); + result = isc_sockaddr_totext(&q->sockaddr, b); + check_result (result, "isc_sockaddr_totext"); + isc_buffer_used(b, &r); + printf (";; Connection to server %.*s for %s failed: Connection timed out.\n", + (int)r.length, r.base, q->lookup->textname); + isc_socket_cancel(q->sock, task, ISC_SOCKCANCEL_ALL); + } + isc_buffer_free (&b); + lookup->pending = ISC_FALSE; +} + +static void +recv_done (isc_task_t *task, isc_event_t *event) { + isc_socketevent_t *sevent=NULL; + dig_query_t *query=NULL; + isc_buffer_t *b=NULL; + dns_message_t *msg=NULL; + isc_result_t result; + isc_buffer_t ab; + char abspace[MXNAME]; + isc_region_t r; + + UNUSED (task); + + sendcount--; +#ifdef DEBUG + printf ("In recv_done, counter down to %d\n",sendcount); +#endif + REQUIRE (event->ev_type == ISC_SOCKEVENT_RECVDONE); + sevent = (isc_socketevent_t *)event; + query = event->ev_arg; + + if (!query->lookup->pending) { +#ifdef DEBUG + puts ("No longer pending..."); +#endif + query->working = ISC_FALSE; + query->waiting_connect = ISC_FALSE; + check_next_lookup(query->lookup); + isc_event_free (&event); + return; + } + + if (sevent->result == ISC_R_SUCCESS) { + b = ISC_LIST_HEAD(sevent->bufferlist); + ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link); + result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, + &msg); + check_result (result, "dns_message_create"); + result = dns_message_parse(msg, b, ISC_TRUE); +#ifdef NEVER + if (result != ISC_R_SUCCESS) + hex_dump (b); +#endif + check_result (result, "dns_message_parse"); + cancel_lookup (query->lookup); + printmessage(msg); + query->working = ISC_FALSE; + query->waiting_connect = ISC_FALSE; + check_next_lookup(query->lookup); + /* XXXMWS Will need a more complex pending check once + TCP mode comes in and we need to deal with + XFR transfers. */ + query->lookup->pending = ISC_FALSE; + if (!query->lookup->pending) { + isc_buffer_init (&ab, abspace, MXNAME, + ISC_BUFFERTYPE_TEXT); + check_result (result,"isc_buffer_init"); + result = isc_sockaddr_totext (&sevent->address, &ab); + check_result (result, "isc_sockaddr_totext"); + isc_buffer_used (&ab, &r); + printf ("; Received %u bytes from %s\n", + b->used, r.base); + } + dns_message_destroy (&msg); + isc_event_free (&event); + return; + } + /* In truth, we should never get into the CANCELED routine, since + the cancel_lookup() routine clears the pending flag. */ + if (sevent->result == ISC_R_CANCELED) { + query->working = ISC_FALSE; + query->waiting_connect = ISC_FALSE; + check_next_lookup(query->lookup); + isc_event_free (&event); + return; + } + fatal ("recv_done got result %s",isc_result_totext(sevent->result)); +} + +static void +get_address(char *hostname, in_port_t port, isc_sockaddr_t *sockaddr) { + struct in_addr in4; + struct in6_addr in6; + struct hostent *he; + + if (have_ipv6 && inet_pton(AF_INET6, hostname, &in6) == 1) + isc_sockaddr_fromin6(sockaddr, &in6, port); + else if (inet_pton(AF_INET, hostname, &in4) == 1) + isc_sockaddr_fromin(sockaddr, &in4, port); + else { + he = gethostbyname(hostname); + if (he == NULL) + fatal("gethostbyname() failed, h_errno = %d", + h_errno); + INSIST(he->h_addrtype == AF_INET); + isc_sockaddr_fromin(sockaddr, + (struct in_addr *)(he->h_addr_list[0]), + port); + } +} + +static void +do_lookup_udp (dig_lookup_t *lookup) { + dig_query_t *query; + isc_result_t result; + +#ifdef DEBUG + puts ("Starting a UDP lookup."); +#endif + lookup->pending = ISC_TRUE; + isc_interval_set (&lookup->interval, timeout, 0); + result = isc_timer_create (timermgr, isc_timertype_once, + NULL, &lookup->interval, task, + recv_timeout, lookup, + &lookup->timer); + check_result (result, "isc_timer_create"); + + for (query = ISC_LIST_HEAD(lookup->q); + query != NULL; + query = ISC_LIST_NEXT(query, link)) { + query->working = ISC_TRUE; + query->waiting_connect = ISC_FALSE; + get_address(query->servname, port, &query->sockaddr); + + result = isc_socket_create (socketmgr, + isc_sockaddr_pf(&query->sockaddr), + isc_sockettype_udp, + &query->sock) ; + check_result (result, "isc_socket_create"); + result = isc_socket_recvv (query->sock, &query->recvlist, + 1, task, recv_done, query); + check_result (result, "isc_socket_recvv"); + sendcount++; +#ifdef DEBUG + printf ("Sent count number %d\n",sendcount); +#endif + result = isc_socket_sendtov(query->sock, &query->sendlist, + task, send_done, query, + &query->sockaddr, NULL); + check_result (result, "isc_socket_sendtov"); + } +} + +static void +free_lists() { + void *ptr; + dig_lookup_t *l; + dig_query_t *q; + dig_server_t *s; + + l = ISC_LIST_HEAD(lookup_list); + while (l != NULL) { + INSIST (!l->pending); + q = ISC_LIST_HEAD(l->q); + while (q != NULL) { + INSIST (!q->working); + if (q->sock != NULL) + isc_socket_detach (&q->sock); + if (ISC_LINK_LINKED (&q->recvbuf, link)) + ISC_LIST_DEQUEUE (q->recvlist, + &q->recvbuf, link); + if (ISC_LINK_LINKED (&q->lengthbuf, link)) + ISC_LIST_DEQUEUE (q->lengthlist, + &q->lengthbuf, link); + isc_buffer_invalidate (&q->recvbuf); + isc_buffer_invalidate (&q->lengthbuf); + ptr = q; + q = ISC_LIST_NEXT(q, link); + isc_mem_free (mctx, ptr); + } + if (l->sendmsg != NULL) + dns_message_destroy (&l->sendmsg); + if (l->timer != NULL) + isc_timer_detach (&l->timer); + ptr = l; + l = ISC_LIST_NEXT(l, link); + isc_mem_free (mctx, ptr); + } + s = ISC_LIST_HEAD(server_list); + while (s != NULL) { + ptr = s; + s = ISC_LIST_NEXT(s, link); + isc_mem_free (mctx, ptr); + } + dns_name_invalidate (&rootorg); + if (socketmgr != NULL) + isc_socketmgr_destroy (&socketmgr); + if (timermgr != NULL) + isc_timermgr_destroy (&timermgr); + if (task != NULL) + isc_task_detach (&task); + if (taskmgr != NULL) + isc_taskmgr_destroy (&taskmgr); +} + +int +main (int argc, char **argv) { + dig_lookup_t *lookup = NULL; + + ISC_LIST_INIT(lookup_list); + ISC_LIST_INIT(server_list); + + setup_libs(); + parse_args(ISC_FALSE, argc, argv); + setup_system(); + lookup = ISC_LIST_HEAD(lookup_list); + setup_lookup(lookup); +#ifdef TCP_WORKING + if (tcp_mode) + do_lookup_tcp(lookup); + else +#endif + do_lookup_udp(lookup); + isc_app_run(); + free_lists(); +#ifdef MEMDEBUG + isc_mem_stats(mctx, stderr); +#endif + isc_app_finish(); + return (0); +} diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h new file mode 100644 index 0000000000..a53ba647b5 --- /dev/null +++ b/bin/dig/include/dig/dig.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 1999, 2000 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef DIG_H +#define DIG_H + +#define SDIG_BUFFER_SIZE 2048 +#include +#include +#include +#include +#include +#include +#include +#include + +#define MXSERV 4 +#define MXNAME 256 +#define MXRD 32 +#define BUFSIZE 512 +#define COMMSIZE 2048 +#define RESOLVCONF "/etc/resolv.conf" + +ISC_LANG_BEGINDECLS + +typedef struct dig_lookup dig_lookup_t; +typedef struct dig_query dig_query_t; +typedef struct dig_server dig_server_t; + +struct dig_lookup { + isc_boolean_t pending; /* Pending a successful answer */ + char textname[MXNAME]; /* Name we're going to be looking up */ + char rttext[MXRD]; /* rdata type text */ + char rctext[MXRD]; /* rdata class text */ + char namespace[BUFSIZE]; + isc_buffer_t namebuf; + isc_buffer_t sendbuf; + char sendspace[COMMSIZE]; + dns_name_t *name; + isc_timer_t *timer; + isc_interval_t interval; + dns_message_t *sendmsg; + ISC_LINK(dig_lookup_t) link; + ISC_LIST(dig_query_t) q; +}; + +struct dig_query { + dig_lookup_t *lookup; + isc_boolean_t working, + waiting_connect, + first_pass, + first_soa_rcvd; + char *servname; + isc_bufferlist_t sendlist, + recvlist, + lengthlist; + isc_buffer_t recvbuf, + lengthbuf; + char recvspace[COMMSIZE], + lengthspace[4]; + isc_socket_t *sock; + ISC_LINK(dig_query_t) link; + isc_sockaddr_t sockaddr; +}; + +struct dig_server { + char servername[MXNAME]; + ISC_LINK(dig_server_t) link; +}; + +ISC_LANG_ENDDECLS + +#endif diff --git a/bin/dig/include/dig/printmsg.h b/bin/dig/include/dig/printmsg.h new file mode 100644 index 0000000000..47513fc273 --- /dev/null +++ b/bin/dig/include/dig/printmsg.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 1998, 1999, 2000 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef TEST_PRINTMSG_H +#define TEST_PRINTMSG_H + +#include + +isc_result_t printmessage(dns_message_t *message); + +#endif /* TEST_PRINTMSG_H */ diff --git a/bin/dig/printmsg.c b/bin/dig/printmsg.c new file mode 100644 index 0000000000..bb387e78fb --- /dev/null +++ b/bin/dig/printmsg.c @@ -0,0 +1,264 @@ +/* + * Copyright (C) 1998, 1999, 2000 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static char *opcodetext[] = { + "QUERY", + "IQUERY", + "STATUS", + "RESERVED3", + "NOTIFY", + "UPDATE", + "RESERVED6", + "RESERVED7", + "RESERVED8", + "RESERVED9", + "RESERVED10", + "RESERVED11", + "RESERVED12", + "RESERVED13", + "RESERVED14", + "RESERVED15" +}; + +static char *rcodetext[] = { + "NOERROR", + "FORMERR", + "SERVFAIL", + "NXDOMAIN", + "NOTIMPL", + "REFUSED", + "YXDOMAIN", + "YXRRSET", + "NXRRSET", + "NOTAUTH", + "NOTZONE", + "RESERVED11", + "RESERVED12", + "RESERVED13", + "RESERVED14", + "RESERVED15", + "BADVERS" +}; + +static isc_result_t +printsection(dns_message_t *msg, dns_section_t sectionid, char *section_name) +{ + dns_name_t *name, *print_name; + dns_rdataset_t *rdataset; + isc_buffer_t target; + isc_result_t result; + isc_region_t r; + dns_name_t empty_name; + char t[4096]; + isc_boolean_t first; + isc_boolean_t no_rdata; + + if (sectionid == DNS_SECTION_QUESTION) + no_rdata = ISC_TRUE; + else + no_rdata = ISC_FALSE; + + printf(";; %s SECTION:\n", section_name); + + dns_name_init(&empty_name, NULL); + + result = dns_message_firstname(msg, sectionid); + if (result == ISC_R_NOMORE) + return (ISC_R_SUCCESS); + else if (result != ISC_R_SUCCESS) + return (result); + + for (;;) { + name = NULL; + dns_message_currentname(msg, sectionid, &name); + + isc_buffer_init(&target, t, sizeof t, ISC_BUFFERTYPE_TEXT); + first = ISC_TRUE; + print_name = name; + + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + result = dns_rdataset_totext(rdataset, + print_name, + ISC_FALSE, + no_rdata, + &target); + if (result != ISC_R_SUCCESS) + return (result); +#ifdef USEINITALWS + if (first) { + print_name = &empty_name; + first = ISC_FALSE; + } +#endif + } + isc_buffer_used(&target, &r); + printf("%.*s", (int)r.length, (char *)r.base); + + result = dns_message_nextname(msg, sectionid); + if (result == ISC_R_NOMORE) + break; + else if (result != ISC_R_SUCCESS) + return (result); + } + + return (ISC_R_SUCCESS); +} + +static isc_result_t +printrdata(dns_message_t *msg, dns_rdataset_t *rdataset, dns_name_t *owner, + char *set_name) +{ + isc_buffer_t target; + isc_result_t result; + isc_region_t r; + char t[4096]; + + UNUSED(msg); + printf(";; %s SECTION:\n", set_name); + + isc_buffer_init(&target, t, sizeof t, ISC_BUFFERTYPE_TEXT); + + result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_FALSE, + &target); + if (result != ISC_R_SUCCESS) + return (result); + isc_buffer_used(&target, &r); + printf("%.*s", (int)r.length, (char *)r.base); + + return (ISC_R_SUCCESS); +} + +isc_result_t +printmessage(dns_message_t *msg) { + isc_boolean_t did_flag = ISC_FALSE; + isc_result_t result; + dns_rdataset_t *opt, *tsig; + dns_name_t *tsigname; + + result = ISC_R_SUCCESS; + + printf(";; ->>HEADER<<- opcode: %s, status: %s, id: %u\n", + opcodetext[msg->opcode], rcodetext[msg->rcode], msg->id); + + printf(";; flags: "); + if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) { + printf("qr"); + did_flag = ISC_TRUE; + } + if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) { + printf("%saa", did_flag ? " " : ""); + did_flag = ISC_TRUE; + } + if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) { + printf("%stc", did_flag ? " " : ""); + did_flag = ISC_TRUE; + } + if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) { + printf("%srd", did_flag ? " " : ""); + did_flag = ISC_TRUE; + } + if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) { + printf("%sra", did_flag ? " " : ""); + did_flag = ISC_TRUE; + } + if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) { + printf("%sad", did_flag ? " " : ""); + did_flag = ISC_TRUE; + } + if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) { + printf("%scd", did_flag ? " " : ""); + did_flag = ISC_TRUE; + } + printf("; QUERY: %u, ANSWER: %u, AUTHORITY: %u, ADDITIONAL: %u\n", + msg->counts[DNS_SECTION_QUESTION], + msg->counts[DNS_SECTION_ANSWER], + msg->counts[DNS_SECTION_AUTHORITY], + msg->counts[DNS_SECTION_ADDITIONAL]); + opt = dns_message_getopt(msg); + if (opt != NULL) + printf(";; EDNS: version: %u, udp=%u\n", + (unsigned int)((opt->ttl & 0x00ff0000) >> 16), + (unsigned int)opt->rdclass); + + tsigname = NULL; + tsig = dns_message_gettsig(msg, &tsigname); + if (tsig != NULL) + printf(";; PSEUDOSECTIONS: TSIG\n"); + if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION])) { + printf("\n"); + result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION"); + if (result != ISC_R_SUCCESS) + return (result); + } + if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) { + printf("\n"); + result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER"); + if (result != ISC_R_SUCCESS) + return (result); + } + if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY])) { + printf("\n"); + result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY"); + if (result != ISC_R_SUCCESS) + return (result); + } + if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL])) { + printf("\n"); + result = printsection(msg, DNS_SECTION_ADDITIONAL, + "ADDITIONAL"); + if (result != ISC_R_SUCCESS) + return (result); + } + if (tsig != NULL) { + printf("\n"); + result = printrdata(msg, tsig, tsigname, + "PSEUDOSECTION TSIG"); + if (result != ISC_R_SUCCESS) + return (result); + } + printf("\n"); + + return (result); +}