2 * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: dighost.c,v 1.336.22.4 2011-03-11 06:46:58 marka Exp $ */
22 * Notice to programmers: Do not use this code as an example of how to
23 * use the ISC library to perform DNS lookups. Dig and Host both operate
24 * on the request level, since they allow fine-tuning of output and are
25 * intended as debugging tools. As a result, they perform many of the
26 * functions which could be better handled using the dns_resolver
27 * functions in most applications.
41 #include <idn/result.h>
43 #include <idn/resconf.h>
47 #include <dns/byaddr.h>
49 #include <dns/dnssec.h>
52 #include <isc/random.h>
55 #include <dns/fixedname.h>
57 #include <dns/message.h>
59 #include <dns/rdata.h>
60 #include <dns/rdataclass.h>
61 #include <dns/rdatalist.h>
62 #include <dns/rdataset.h>
63 #include <dns/rdatastruct.h>
64 #include <dns/rdatatype.h>
65 #include <dns/result.h>
71 #include <isc/base64.h>
72 #include <isc/entropy.h>
76 #include <isc/netaddr.h>
78 #include <isc/netdb.h>
80 #include <isc/parseint.h>
81 #include <isc/print.h>
82 #include <isc/random.h>
83 #include <isc/result.h>
84 #include <isc/string.h>
86 #include <isc/timer.h>
87 #include <isc/types.h>
90 #include <isccfg/namedconf.h>
92 #include <lwres/lwres.h>
93 #include <lwres/net.h>
95 #include <bind9/getaddresses.h>
99 #if ! defined(NS_INADDRSZ)
100 #define NS_INADDRSZ 4
103 #if ! defined(NS_IN6ADDRSZ)
104 #define NS_IN6ADDRSZ 16
107 static lwres_context_t *lwctx = NULL;
108 static lwres_conf_t *lwconf;
110 dig_lookuplist_t lookup_list;
111 dig_serverlist_t server_list;
112 dig_searchlistlist_t search_list;
115 check_ra = ISC_FALSE,
116 have_ipv4 = ISC_FALSE,
117 have_ipv6 = ISC_FALSE,
118 specified_source = ISC_FALSE,
119 free_now = ISC_FALSE,
120 cancel_now = ISC_FALSE,
121 usesearch = ISC_FALSE,
122 showsearch = ISC_FALSE,
124 is_dst_up = ISC_FALSE;
126 unsigned int timeout = 0;
127 unsigned int extrabytes;
128 isc_mem_t *mctx = NULL;
129 isc_log_t *lctx = NULL;
130 isc_taskmgr_t *taskmgr = NULL;
131 isc_task_t *global_task = NULL;
132 isc_timermgr_t *timermgr = NULL;
133 isc_socketmgr_t *socketmgr = NULL;
134 isc_sockaddr_t bind_address;
135 isc_sockaddr_t bind_any;
141 int lookup_counter = 0;
144 static void initialize_idn(void);
145 static isc_result_t output_filter(isc_buffer_t *buffer,
146 unsigned int used_org,
147 isc_boolean_t absolute);
148 static idn_result_t append_textname(char *name, const char *origin,
150 static void idn_check_result(idn_result_t r, const char *msg);
159 *\li 0 Everything went well, including things like NXDOMAIN
161 *\li 7 Got too many RR's or Names
162 *\li 8 Couldn't open batch file
163 *\li 9 No reply from server
164 *\li 10 Internal error
168 char keynametext[MXNAME];
169 char keyfile[MXNAME] = "";
170 char keysecret[MXNAME] = "";
171 dns_name_t *hmacname = NULL;
172 unsigned int digestbits = 0;
173 isc_buffer_t *namebuf = NULL;
174 dns_tsigkey_t *key = NULL;
175 isc_boolean_t validated = ISC_TRUE;
176 isc_entropy_t *entp = NULL;
177 isc_mempool_t *commctx = NULL;
178 isc_boolean_t debugging = ISC_FALSE;
179 isc_boolean_t memdebugging = ISC_FALSE;
180 char *progname = NULL;
181 isc_mutex_t lookup_lock;
182 dig_lookup_t *current_lookup = NULL;
186 isc_result_t get_trusted_key(isc_mem_t *mctx);
187 dns_rdataset_t * sigchase_scanname(dns_rdatatype_t type,
188 dns_rdatatype_t covers,
189 isc_boolean_t *lookedup,
190 dns_name_t *rdata_name);
191 dns_rdataset_t * chase_scanname_section(dns_message_t *msg,
193 dns_rdatatype_t type,
194 dns_rdatatype_t covers,
196 isc_result_t advanced_rrsearch(dns_rdataset_t **rdataset,
198 dns_rdatatype_t type,
199 dns_rdatatype_t covers,
200 isc_boolean_t *lookedup);
201 isc_result_t sigchase_verify_sig_key(dns_name_t *name,
202 dns_rdataset_t *rdataset,
203 dst_key_t* dnsseckey,
204 dns_rdataset_t *sigrdataset,
206 isc_result_t sigchase_verify_sig(dns_name_t *name,
207 dns_rdataset_t *rdataset,
208 dns_rdataset_t *keyrdataset,
209 dns_rdataset_t *sigrdataset,
211 isc_result_t sigchase_verify_ds(dns_name_t *name,
212 dns_rdataset_t *keyrdataset,
213 dns_rdataset_t *dsrdataset,
215 void sigchase(dns_message_t *msg);
216 void print_rdata(dns_rdata_t *rdata, isc_mem_t *mctx);
217 void print_rdataset(dns_name_t *name,
218 dns_rdataset_t *rdataset, isc_mem_t *mctx);
219 void dup_name(dns_name_t *source, dns_name_t* target,
221 void free_name(dns_name_t *name, isc_mem_t *mctx);
222 void dump_database(void);
223 void dump_database_section(dns_message_t *msg, int section);
224 dns_rdataset_t * search_type(dns_name_t *name, dns_rdatatype_t type,
225 dns_rdatatype_t covers);
226 isc_result_t contains_trusted_key(dns_name_t *name,
227 dns_rdataset_t *rdataset,
228 dns_rdataset_t *sigrdataset,
230 void print_type(dns_rdatatype_t type);
231 isc_result_t prove_nx_domain(dns_message_t * msg,
233 dns_name_t * rdata_name,
234 dns_rdataset_t ** rdataset,
235 dns_rdataset_t ** sigrdataset);
236 isc_result_t prove_nx_type(dns_message_t * msg, dns_name_t *name,
237 dns_rdataset_t *nsec,
238 dns_rdataclass_t class,
239 dns_rdatatype_t type,
240 dns_name_t * rdata_name,
241 dns_rdataset_t ** rdataset,
242 dns_rdataset_t ** sigrdataset);
243 isc_result_t prove_nx(dns_message_t * msg, dns_name_t * name,
244 dns_rdataclass_t class,
245 dns_rdatatype_t type,
246 dns_name_t * rdata_name,
247 dns_rdataset_t ** rdataset,
248 dns_rdataset_t ** sigrdataset);
249 static void nameFromString(const char *str, dns_name_t *p_ret);
250 int inf_name(dns_name_t * name1, dns_name_t * name2);
251 isc_result_t opentmpkey(isc_mem_t *mctx, const char *file,
252 char **tempp, FILE **fp);
253 isc_result_t removetmpkey(isc_mem_t *mctx, const char *file);
254 void clean_trustedkey(void);
255 void insert_trustedkey(dst_key_t **key);
257 isc_result_t getneededrr(dns_message_t *msg);
258 void sigchase_bottom_up(dns_message_t *msg);
259 void sigchase_bu(dns_message_t *msg);
262 isc_result_t initialization(dns_name_t *name);
263 isc_result_t prepare_lookup(dns_name_t *name);
264 isc_result_t grandfather_pb_test(dns_name_t * zone_name,
265 dns_rdataset_t *sigrdataset);
266 isc_result_t child_of_zone(dns_name_t *name,
267 dns_name_t *zone_name,
268 dns_name_t *child_name);
269 void sigchase_td(dns_message_t *msg);
271 char trustedkey[MXNAME] = "";
273 dns_rdataset_t *chase_rdataset = NULL;
274 dns_rdataset_t *chase_sigrdataset = NULL;
275 dns_rdataset_t *chase_dsrdataset = NULL;
276 dns_rdataset_t *chase_sigdsrdataset = NULL;
277 dns_rdataset_t *chase_keyrdataset = NULL;
278 dns_rdataset_t *chase_sigkeyrdataset = NULL;
279 dns_rdataset_t *chase_nsrdataset = NULL;
281 dns_name_t chase_name; /* the query name */
284 * the current name is the parent name when we follow delegation
286 dns_name_t chase_current_name;
288 * the child name is used for delegation (NS DS responses in AUTHORITY section)
290 dns_name_t chase_authority_name;
293 dns_name_t chase_signame;
297 isc_boolean_t chase_siglookedup = ISC_FALSE;
298 isc_boolean_t chase_keylookedup = ISC_FALSE;
299 isc_boolean_t chase_sigkeylookedup = ISC_FALSE;
300 isc_boolean_t chase_dslookedup = ISC_FALSE;
301 isc_boolean_t chase_sigdslookedup = ISC_FALSE;
303 isc_boolean_t chase_nslookedup = ISC_FALSE;
304 isc_boolean_t chase_lookedup = ISC_FALSE;
307 isc_boolean_t delegation_follow = ISC_FALSE;
308 isc_boolean_t grandfather_pb = ISC_FALSE;
309 isc_boolean_t have_response = ISC_FALSE;
310 isc_boolean_t have_delegation_ns = ISC_FALSE;
311 dns_message_t * error_message = NULL;
314 isc_boolean_t dsvalidating = ISC_FALSE;
315 isc_boolean_t chase_name_dup = ISC_FALSE;
317 ISC_LIST(dig_message_t) chase_message_list;
318 ISC_LIST(dig_message_t) chase_message_list2;
321 #define MAX_TRUSTED_KEY 5
322 typedef struct struct_trusted_key_list {
323 dst_key_t * key[MAX_TRUSTED_KEY];
327 struct_tk_list tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0};
331 #define DIG_MAX_ADDRESSES 20
334 * Apply and clear locks at the event level in global task.
335 * Can I get rid of these using shutdown events? XXX
337 #define LOCK_LOOKUP {\
338 debug("lock_lookup %s:%d", __FILE__, __LINE__);\
339 check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\
342 #define UNLOCK_LOOKUP {\
343 debug("unlock_lookup %s:%d", __FILE__, __LINE__);\
344 check_result(isc_mutex_unlock((&lookup_lock)),\
345 "isc_mutex_unlock");\
349 cancel_lookup(dig_lookup_t *lookup);
352 recv_done(isc_task_t *task, isc_event_t *event);
355 send_udp(dig_query_t *query);
358 connect_timeout(isc_task_t *task, isc_event_t *event);
361 launch_next_query(dig_query_t *query, isc_boolean_t include_question);
365 mem_alloc(void *arg, size_t size) {
366 return (isc_mem_get(arg, size));
370 mem_free(void *arg, void *mem, size_t size) {
371 isc_mem_put(arg, mem, size);
375 next_token(char **stringp, const char *delim) {
379 res = strsep(stringp, delim);
382 } while (*res == '\0');
387 count_dots(char *string) {
401 hex_dump(isc_buffer_t *b) {
405 isc_buffer_usedregion(b, &r);
407 printf("%d bytes\n", r.length);
408 for (len = 0; len < r.length; len++) {
409 printf("%02x ", r.base[len]);
410 if (len % 16 == 15) {
412 for (i = len - 15; i <= len; i++) {
413 if (r.base[i] >= '!' && r.base[i] <= '}')
422 for (i = len; (i % 16) != 0; i++)
425 for (i = ((len>>4)<<4); i < len; i++) {
426 if (r.base[i] >= '!' && r.base[i] <= '}')
436 * Append 'len' bytes of 'text' at '*p', failing with
437 * ISC_R_NOSPACE if that would advance p past 'end'.
440 append(const char *text, int len, char **p, char *end) {
442 return (ISC_R_NOSPACE);
443 memcpy(*p, text, len);
445 return (ISC_R_SUCCESS);
449 reverse_octets(const char *in, char **p, char *end) {
450 char *dot = strchr(in, '.');
454 result = reverse_octets(dot + 1, p, end);
455 if (result != ISC_R_SUCCESS)
457 result = append(".", 1, p, end);
458 if (result != ISC_R_SUCCESS)
464 return (append(in, len, p, end));
468 get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int,
469 isc_boolean_t strict)
475 addr.family = AF_INET6;
476 r = inet_pton(AF_INET6, value, &addr.type.in6);
478 /* This is a valid IPv6 address. */
479 dns_fixedname_t fname;
481 unsigned int options = 0;
484 options |= DNS_BYADDROPT_IPV6INT;
485 dns_fixedname_init(&fname);
486 name = dns_fixedname_name(&fname);
487 result = dns_byaddr_createptrname2(&addr, options, name);
488 if (result != ISC_R_SUCCESS)
490 dns_name_format(name, reverse, len);
491 return (ISC_R_SUCCESS);
494 * Not a valid IPv6 address. Assume IPv4.
495 * If 'strict' is not set, construct the
496 * in-addr.arpa name by blindly reversing
497 * octets whether or not they look like integers,
498 * so that this can be used for RFC2317 names
502 char *end = reverse + len;
503 if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1)
504 return (DNS_R_BADDOTTEDQUAD);
505 result = reverse_octets(value, &p, end);
506 if (result != ISC_R_SUCCESS)
508 /* Append .in-addr.arpa. and a terminating NUL. */
509 result = append(".in-addr.arpa.", 15, &p, end);
510 if (result != ISC_R_SUCCESS)
512 return (ISC_R_SUCCESS);
517 fatal(const char *format, ...) {
521 fprintf(stderr, "%s: ", progname);
522 va_start(args, format);
523 vfprintf(stderr, format, args);
525 fprintf(stderr, "\n");
529 exitcode = fatalexit;
534 debug(const char *format, ...) {
539 va_start(args, format);
540 vfprintf(stderr, format, args);
542 fprintf(stderr, "\n");
547 check_result(isc_result_t result, const char *msg) {
548 if (result != ISC_R_SUCCESS) {
549 fatal("%s: %s", msg, isc_result_totext(result));
554 * Create a server structure, which is part of the lookup structure.
555 * This is little more than a linked list of servers to query in hopes
556 * of finding the answer the user is looking for
559 make_server(const char *servname, const char *userarg) {
562 REQUIRE(servname != NULL);
564 debug("make_server(%s)", servname);
565 srv = isc_mem_allocate(mctx, sizeof(struct dig_server));
567 fatal("memory allocation failure in %s:%d",
569 strlcpy(srv->servername, servname, MXNAME);
570 strlcpy(srv->userarg, userarg, MXNAME);
571 ISC_LINK_INIT(srv, link);
576 addr2af(int lwresaddrtype)
580 switch (lwresaddrtype) {
581 case LWRES_ADDRTYPE_V4:
585 case LWRES_ADDRTYPE_V6:
594 * Create a copy of the server list from the lwres configuration structure.
595 * The dest list must have already had ISC_LIST_INIT applied.
598 copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) {
599 dig_server_t *newsrv;
600 char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
604 debug("copy_server_list()");
605 for (i = 0; i < confdata->nsnext; i++) {
606 af = addr2af(confdata->nameservers[i].family);
608 if (af == AF_INET && !have_ipv4)
610 if (af == AF_INET6 && !have_ipv6)
613 lwres_net_ntop(af, confdata->nameservers[i].address,
615 newsrv = make_server(tmp, tmp);
616 ISC_LINK_INIT(newsrv, link);
617 ISC_LIST_ENQUEUE(*dest, newsrv, link);
622 flush_server_list(void) {
623 dig_server_t *s, *ps;
625 debug("flush_server_list()");
626 s = ISC_LIST_HEAD(server_list);
629 s = ISC_LIST_NEXT(s, link);
630 ISC_LIST_DEQUEUE(server_list, ps, link);
631 isc_mem_free(mctx, ps);
636 set_nameserver(char *opt) {
638 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
639 isc_netaddr_t netaddr;
642 char tmp[ISC_NETADDR_FORMATSIZE];
647 result = bind9_getaddresses(opt, 0, sockaddrs,
648 DIG_MAX_ADDRESSES, &count);
649 if (result != ISC_R_SUCCESS)
650 fatal("couldn't get address for '%s': %s",
651 opt, isc_result_totext(result));
655 for (i = 0; i < count; i++) {
656 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
657 isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
658 srv = make_server(tmp, opt);
660 fatal("memory allocation failure");
661 ISC_LIST_APPEND(server_list, srv, link);
666 add_nameserver(lwres_conf_t *confdata, const char *addr, int af) {
668 int i = confdata->nsnext;
670 if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS)
671 return (ISC_R_FAILURE);
675 confdata->nameservers[i].family = LWRES_ADDRTYPE_V4;
676 confdata->nameservers[i].length = NS_INADDRSZ;
679 confdata->nameservers[i].family = LWRES_ADDRTYPE_V6;
680 confdata->nameservers[i].length = NS_IN6ADDRSZ;
683 return (ISC_R_FAILURE);
686 if (lwres_net_pton(af, addr, &confdata->nameservers[i].address) == 1) {
688 return (ISC_R_SUCCESS);
690 return (ISC_R_FAILURE);
694 * Produce a cloned server list. The dest list must have already had
695 * ISC_LIST_INIT applied.
698 clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
699 dig_server_t *srv, *newsrv;
701 debug("clone_server_list()");
702 srv = ISC_LIST_HEAD(src);
703 while (srv != NULL) {
704 newsrv = make_server(srv->servername, srv->userarg);
705 ISC_LINK_INIT(newsrv, link);
706 ISC_LIST_ENQUEUE(*dest, newsrv, link);
707 srv = ISC_LIST_NEXT(srv, link);
712 * Create an empty lookup structure, which holds all the information needed
713 * to get an answer to a user's question. This structure contains two
714 * linked lists: the server list (servers to query) and the query list
715 * (outstanding queries which have been made to the listed servers).
718 make_empty_lookup(void) {
719 dig_lookup_t *looknew;
721 debug("make_empty_lookup()");
725 looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
727 fatal("memory allocation failure in %s:%d",
729 looknew->pending = ISC_TRUE;
730 looknew->textname[0] = 0;
731 looknew->cmdline[0] = 0;
732 looknew->rdtype = dns_rdatatype_a;
733 looknew->qrdtype = dns_rdatatype_a;
734 looknew->rdclass = dns_rdataclass_in;
735 looknew->rdtypeset = ISC_FALSE;
736 looknew->rdclassset = ISC_FALSE;
737 looknew->sendspace = NULL;
738 looknew->sendmsg = NULL;
739 looknew->name = NULL;
740 looknew->oname = NULL;
741 looknew->timer = NULL;
742 looknew->xfr_q = NULL;
743 looknew->current_query = NULL;
744 looknew->doing_xfr = ISC_FALSE;
745 looknew->ixfr_serial = ISC_FALSE;
746 looknew->trace = ISC_FALSE;
747 looknew->trace_root = ISC_FALSE;
748 looknew->identify = ISC_FALSE;
749 looknew->identify_previous_line = ISC_FALSE;
750 looknew->ignore = ISC_FALSE;
751 looknew->servfail_stops = ISC_TRUE;
752 looknew->besteffort = ISC_TRUE;
753 looknew->dnssec = ISC_FALSE;
754 looknew->nsid = ISC_FALSE;
756 looknew->sigchase = ISC_FALSE;
758 looknew->do_topdown = ISC_FALSE;
759 looknew->trace_root_sigchase = ISC_FALSE;
760 looknew->rdtype_sigchaseset = ISC_FALSE;
761 looknew->rdtype_sigchase = dns_rdatatype_any;
762 looknew->qrdtype_sigchase = dns_rdatatype_any;
763 looknew->rdclass_sigchase = dns_rdataclass_in;
764 looknew->rdclass_sigchaseset = ISC_FALSE;
767 looknew->udpsize = 0;
769 looknew->recurse = ISC_TRUE;
770 looknew->aaonly = ISC_FALSE;
771 looknew->adflag = ISC_FALSE;
772 looknew->cdflag = ISC_FALSE;
773 looknew->ns_search_only = ISC_FALSE;
774 looknew->origin = NULL;
775 looknew->tsigctx = NULL;
776 looknew->querysig = NULL;
777 looknew->retries = tries;
778 looknew->nsfound = 0;
779 looknew->tcp_mode = ISC_FALSE;
780 looknew->ip6_int = ISC_FALSE;
781 looknew->comments = ISC_TRUE;
782 looknew->stats = ISC_TRUE;
783 looknew->section_question = ISC_TRUE;
784 looknew->section_answer = ISC_TRUE;
785 looknew->section_authority = ISC_TRUE;
786 looknew->section_additional = ISC_TRUE;
787 looknew->new_search = ISC_FALSE;
788 looknew->done_as_is = ISC_FALSE;
789 looknew->need_search = ISC_FALSE;
790 ISC_LINK_INIT(looknew, link);
791 ISC_LIST_INIT(looknew->q);
792 ISC_LIST_INIT(looknew->my_server_list);
797 * Clone a lookup, perhaps copying the server list. This does not clone
798 * the query list, since it will be regenerated by the setup_lookup()
799 * function, nor does it queue up the new lookup for processing.
800 * Caution: If you don't clone the servers, you MUST clone the server
801 * list separately from somewhere else, or construct it by hand.
804 clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
805 dig_lookup_t *looknew;
807 debug("clone_lookup()");
811 looknew = make_empty_lookup();
812 INSIST(looknew != NULL);
813 strncpy(looknew->textname, lookold->textname, MXNAME);
815 strncpy(looknew->textnamesigchase, lookold->textnamesigchase, MXNAME);
817 strncpy(looknew->cmdline, lookold->cmdline, MXNAME);
818 looknew->textname[MXNAME-1] = 0;
819 looknew->rdtype = lookold->rdtype;
820 looknew->qrdtype = lookold->qrdtype;
821 looknew->rdclass = lookold->rdclass;
822 looknew->rdtypeset = lookold->rdtypeset;
823 looknew->rdclassset = lookold->rdclassset;
824 looknew->doing_xfr = lookold->doing_xfr;
825 looknew->ixfr_serial = lookold->ixfr_serial;
826 looknew->trace = lookold->trace;
827 looknew->trace_root = lookold->trace_root;
828 looknew->identify = lookold->identify;
829 looknew->identify_previous_line = lookold->identify_previous_line;
830 looknew->ignore = lookold->ignore;
831 looknew->servfail_stops = lookold->servfail_stops;
832 looknew->besteffort = lookold->besteffort;
833 looknew->dnssec = lookold->dnssec;
834 looknew->nsid = lookold->nsid;
836 looknew->sigchase = lookold->sigchase;
838 looknew->do_topdown = lookold->do_topdown;
839 looknew->trace_root_sigchase = lookold->trace_root_sigchase;
840 looknew->rdtype_sigchaseset = lookold->rdtype_sigchaseset;
841 looknew->rdtype_sigchase = lookold->rdtype_sigchase;
842 looknew->qrdtype_sigchase = lookold->qrdtype_sigchase;
843 looknew->rdclass_sigchase = lookold->rdclass_sigchase;
844 looknew->rdclass_sigchaseset = lookold->rdclass_sigchaseset;
847 looknew->udpsize = lookold->udpsize;
848 looknew->edns = lookold->edns;
849 looknew->recurse = lookold->recurse;
850 looknew->aaonly = lookold->aaonly;
851 looknew->adflag = lookold->adflag;
852 looknew->cdflag = lookold->cdflag;
853 looknew->ns_search_only = lookold->ns_search_only;
854 looknew->tcp_mode = lookold->tcp_mode;
855 looknew->comments = lookold->comments;
856 looknew->stats = lookold->stats;
857 looknew->section_question = lookold->section_question;
858 looknew->section_answer = lookold->section_answer;
859 looknew->section_authority = lookold->section_authority;
860 looknew->section_additional = lookold->section_additional;
861 looknew->retries = lookold->retries;
862 looknew->tsigctx = NULL;
863 looknew->need_search = lookold->need_search;
864 looknew->done_as_is = lookold->done_as_is;
867 clone_server_list(lookold->my_server_list,
868 &looknew->my_server_list);
873 * Requeue a lookup for further processing, perhaps copying the server
874 * list. The new lookup structure is returned to the caller, and is
875 * queued for processing. If servers are not cloned in the requeue, they
876 * must be added before allowing the current event to complete, since the
877 * completion of the event may result in the next entry on the lookup
881 requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
882 dig_lookup_t *looknew;
884 debug("requeue_lookup()");
887 if (lookup_counter > LOOKUP_LIMIT)
888 fatal("too many lookups");
890 looknew = clone_lookup(lookold, servers);
891 INSIST(looknew != NULL);
893 debug("before insertion, init@%p -> %p, new@%p -> %p",
894 lookold, lookold->link.next, looknew, looknew->link.next);
895 ISC_LIST_PREPEND(lookup_list, looknew, link);
896 debug("after insertion, init -> %p, new = %p, new -> %p",
897 lookold, looknew, looknew->link.next);
903 setup_text_key(void) {
906 isc_buffer_t secretbuf;
908 unsigned char *secretstore;
910 debug("setup_text_key()");
911 result = isc_buffer_allocate(mctx, &namebuf, MXNAME);
912 check_result(result, "isc_buffer_allocate");
913 dns_name_init(&keyname, NULL);
914 check_result(result, "dns_name_init");
915 isc_buffer_putstr(namebuf, keynametext);
916 secretsize = strlen(keysecret) * 3 / 4;
917 secretstore = isc_mem_allocate(mctx, secretsize);
918 if (secretstore == NULL)
919 fatal("memory allocation failure in %s:%d",
921 isc_buffer_init(&secretbuf, secretstore, secretsize);
922 result = isc_base64_decodestring(keysecret, &secretbuf);
923 if (result != ISC_R_SUCCESS)
926 secretsize = isc_buffer_usedlength(&secretbuf);
928 result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf);
929 if (result != ISC_R_SUCCESS)
932 result = dns_tsigkey_create(&keyname, hmacname, secretstore,
933 secretsize, ISC_FALSE, NULL, 0, 0, mctx,
936 if (result != ISC_R_SUCCESS)
937 printf(";; Couldn't create key %s: %s\n",
938 keynametext, isc_result_totext(result));
940 dst_key_setbits(key->key, digestbits);
942 isc_mem_free(mctx, secretstore);
943 dns_name_invalidate(&keyname);
944 isc_buffer_free(&namebuf);
948 parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max,
951 isc_result_t result = isc_parse_uint32(&n, value, 10);
952 if (result == ISC_R_SUCCESS && n > max)
953 result = ISC_R_RANGE;
954 if (result != ISC_R_SUCCESS) {
955 printf("invalid %s '%s': %s\n", desc,
956 value, isc_result_totext(result));
960 return (ISC_R_SUCCESS);
964 parse_bits(char *arg, const char *desc, isc_uint32_t max) {
968 result = parse_uint(&tmp, arg, max, desc);
969 if (result != ISC_R_SUCCESS)
970 fatal("couldn't parse digest bits");
971 tmp = (tmp + 7) & ~0x7U;
977 * Parse HMAC algorithm specification
980 parse_hmac(const char *hmac) {
984 REQUIRE(hmac != NULL);
987 if (len >= (int) sizeof(buf))
988 fatal("unknown key type '%.*s'", len, hmac);
989 strncpy(buf, hmac, sizeof(buf));
993 if (strcasecmp(buf, "hmac-md5") == 0) {
994 hmacname = DNS_TSIG_HMACMD5_NAME;
995 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
996 hmacname = DNS_TSIG_HMACMD5_NAME;
997 digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128);
998 } else if (strcasecmp(buf, "hmac-sha1") == 0) {
999 hmacname = DNS_TSIG_HMACSHA1_NAME;
1001 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
1002 hmacname = DNS_TSIG_HMACSHA1_NAME;
1003 digestbits = parse_bits(&buf[10], "digest-bits [0..160]", 160);
1004 } else if (strcasecmp(buf, "hmac-sha224") == 0) {
1005 hmacname = DNS_TSIG_HMACSHA224_NAME;
1006 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
1007 hmacname = DNS_TSIG_HMACSHA224_NAME;
1008 digestbits = parse_bits(&buf[12], "digest-bits [0..224]", 224);
1009 } else if (strcasecmp(buf, "hmac-sha256") == 0) {
1010 hmacname = DNS_TSIG_HMACSHA256_NAME;
1011 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
1012 hmacname = DNS_TSIG_HMACSHA256_NAME;
1013 digestbits = parse_bits(&buf[12], "digest-bits [0..256]", 256);
1014 } else if (strcasecmp(buf, "hmac-sha384") == 0) {
1015 hmacname = DNS_TSIG_HMACSHA384_NAME;
1016 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
1017 hmacname = DNS_TSIG_HMACSHA384_NAME;
1018 digestbits = parse_bits(&buf[12], "digest-bits [0..384]", 384);
1019 } else if (strcasecmp(buf, "hmac-sha512") == 0) {
1020 hmacname = DNS_TSIG_HMACSHA512_NAME;
1021 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
1022 hmacname = DNS_TSIG_HMACSHA512_NAME;
1023 digestbits = parse_bits(&buf[12], "digest-bits [0..512]", 512);
1025 fprintf(stderr, ";; Warning, ignoring "
1026 "invalid TSIG algorithm %s\n", buf);
1031 * Get a key from a named.conf format keyfile
1034 read_confkey(void) {
1035 isc_log_t *lctx = NULL;
1036 cfg_parser_t *pctx = NULL;
1037 cfg_obj_t *file = NULL;
1038 const cfg_obj_t *key = NULL;
1039 const cfg_obj_t *secretobj = NULL;
1040 const cfg_obj_t *algorithmobj = NULL;
1041 const char *keyname;
1042 const char *secretstr;
1043 const char *algorithm;
1044 isc_result_t result;
1046 if (! isc_file_exists(keyfile))
1047 return (ISC_R_FILENOTFOUND);
1049 result = cfg_parser_create(mctx, lctx, &pctx);
1050 if (result != ISC_R_SUCCESS)
1053 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
1055 if (result != ISC_R_SUCCESS)
1058 result = cfg_map_get(file, "key", &key);
1059 if (result != ISC_R_SUCCESS)
1062 (void) cfg_map_get(key, "secret", &secretobj);
1063 (void) cfg_map_get(key, "algorithm", &algorithmobj);
1064 if (secretobj == NULL || algorithmobj == NULL)
1065 fatal("key must have algorithm and secret");
1067 keyname = cfg_obj_asstring(cfg_map_getname(key));
1068 secretstr = cfg_obj_asstring(secretobj);
1069 algorithm = cfg_obj_asstring(algorithmobj);
1071 strncpy(keynametext, keyname, sizeof(keynametext));
1072 strncpy(keysecret, secretstr, sizeof(keysecret));
1073 parse_hmac(algorithm);
1079 cfg_obj_destroy(pctx, &file);
1080 cfg_parser_destroy(&pctx);
1087 setup_file_key(void) {
1088 isc_result_t result;
1089 dst_key_t *dstkey = NULL;
1091 debug("setup_file_key()");
1093 /* Try reading the key from a K* pair */
1094 result = dst_key_fromnamedfile(keyfile, NULL,
1095 DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
1098 /* If that didn't work, try reading it as a session.key keyfile */
1099 if (result != ISC_R_SUCCESS) {
1100 result = read_confkey();
1101 if (result == ISC_R_SUCCESS)
1105 if (result != ISC_R_SUCCESS) {
1106 fprintf(stderr, "Couldn't read key from %s: %s\n",
1107 keyfile, isc_result_totext(result));
1111 switch (dst_key_alg(dstkey)) {
1112 case DST_ALG_HMACMD5:
1113 hmacname = DNS_TSIG_HMACMD5_NAME;
1115 case DST_ALG_HMACSHA1:
1116 hmacname = DNS_TSIG_HMACSHA1_NAME;
1118 case DST_ALG_HMACSHA224:
1119 hmacname = DNS_TSIG_HMACSHA224_NAME;
1121 case DST_ALG_HMACSHA256:
1122 hmacname = DNS_TSIG_HMACSHA256_NAME;
1124 case DST_ALG_HMACSHA384:
1125 hmacname = DNS_TSIG_HMACSHA384_NAME;
1127 case DST_ALG_HMACSHA512:
1128 hmacname = DNS_TSIG_HMACSHA512_NAME;
1131 printf(";; Couldn't create key %s: bad algorithm\n",
1135 result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmacname,
1136 dstkey, ISC_FALSE, NULL, 0, 0,
1138 if (result != ISC_R_SUCCESS) {
1139 printf(";; Couldn't create key %s: %s\n",
1140 keynametext, isc_result_totext(result));
1145 dst_key_free(&dstkey);
1148 static dig_searchlist_t *
1149 make_searchlist_entry(char *domain) {
1150 dig_searchlist_t *search;
1151 search = isc_mem_allocate(mctx, sizeof(*search));
1153 fatal("memory allocation failure in %s:%d",
1154 __FILE__, __LINE__);
1155 strncpy(search->origin, domain, MXNAME);
1156 search->origin[MXNAME-1] = 0;
1157 ISC_LINK_INIT(search, link);
1162 clear_searchlist(void) {
1163 dig_searchlist_t *search;
1164 while ((search = ISC_LIST_HEAD(search_list)) != NULL) {
1165 ISC_LIST_UNLINK(search_list, search, link);
1166 isc_mem_free(mctx, search);
1171 create_search_list(lwres_conf_t *confdata) {
1173 dig_searchlist_t *search;
1175 debug("create_search_list()");
1178 for (i = 0; i < confdata->searchnxt; i++) {
1179 search = make_searchlist_entry(confdata->search[i]);
1180 ISC_LIST_APPEND(search_list, search, link);
1185 * Setup the system as a whole, reading key information and resolv.conf
1189 setup_system(void) {
1190 dig_searchlist_t *domain = NULL;
1191 lwres_result_t lwresult;
1192 unsigned int lwresflags;
1194 debug("setup_system()");
1196 lwresflags = LWRES_CONTEXT_SERVERMODE;
1198 lwresflags |= LWRES_CONTEXT_USEIPV4;
1200 lwresflags |= LWRES_CONTEXT_USEIPV6;
1202 lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free,
1204 if (lwresult != LWRES_R_SUCCESS)
1205 fatal("lwres_context_create failed");
1207 lwresult = lwres_conf_parse(lwctx, RESOLV_CONF);
1208 if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND)
1209 fatal("parse of %s failed", RESOLV_CONF);
1211 lwconf = lwres_conf_get(lwctx);
1213 /* Make the search list */
1214 if (lwconf->searchnxt > 0)
1215 create_search_list(lwconf);
1216 else { /* No search list. Use the domain name if any */
1217 if (lwconf->domainname != NULL) {
1218 domain = make_searchlist_entry(lwconf->domainname);
1219 ISC_LIST_APPEND(search_list, domain, link);
1225 ndots = lwconf->ndots;
1226 debug("ndots is %d.", ndots);
1229 /* If user doesn't specify server use nameservers from resolv.conf. */
1230 if (ISC_LIST_EMPTY(server_list))
1231 copy_server_list(lwconf, &server_list);
1233 /* If we don't find a nameserver fall back to localhost */
1234 if (ISC_LIST_EMPTY(server_list)) {
1236 lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET);
1237 if (lwresult != ISC_R_SUCCESS)
1238 fatal("add_nameserver failed");
1241 lwresult = add_nameserver(lwconf, "::1", AF_INET6);
1242 if (lwresult != ISC_R_SUCCESS)
1243 fatal("add_nameserver failed");
1246 copy_server_list(lwconf, &server_list);
1253 if (keyfile[0] != 0)
1255 else if (keysecret[0] != 0)
1258 /* Setup the list of messages for +sigchase */
1259 ISC_LIST_INIT(chase_message_list);
1260 ISC_LIST_INIT(chase_message_list2);
1261 dns_name_init(&chase_name, NULL);
1263 dns_name_init(&chase_current_name, NULL);
1264 dns_name_init(&chase_authority_name, NULL);
1267 dns_name_init(&chase_signame, NULL);
1275 * Override the search list derived from resolv.conf by 'domain'.
1278 set_search_domain(char *domain) {
1279 dig_searchlist_t *search;
1282 search = make_searchlist_entry(domain);
1283 ISC_LIST_APPEND(search_list, search, link);
1287 * Setup the ISC and DNS libraries for use by the system.
1291 isc_result_t result;
1292 isc_logconfig_t *logconfig = NULL;
1294 debug("setup_libs()");
1296 result = isc_net_probeipv4();
1297 if (result == ISC_R_SUCCESS)
1298 have_ipv4 = ISC_TRUE;
1300 result = isc_net_probeipv6();
1301 if (result == ISC_R_SUCCESS)
1302 have_ipv6 = ISC_TRUE;
1303 if (!have_ipv6 && !have_ipv4)
1304 fatal("can't find either v4 or v6 networking");
1306 result = isc_mem_create(0, 0, &mctx);
1307 check_result(result, "isc_mem_create");
1309 result = isc_log_create(mctx, &lctx, &logconfig);
1310 check_result(result, "isc_log_create");
1312 isc_log_setcontext(lctx);
1314 dns_log_setcontext(lctx);
1316 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
1317 check_result(result, "isc_log_usechannel");
1319 isc_log_setdebuglevel(lctx, 0);
1321 result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
1322 check_result(result, "isc_taskmgr_create");
1324 result = isc_task_create(taskmgr, 0, &global_task);
1325 check_result(result, "isc_task_create");
1327 result = isc_timermgr_create(mctx, &timermgr);
1328 check_result(result, "isc_timermgr_create");
1330 result = isc_socketmgr_create(mctx, &socketmgr);
1331 check_result(result, "isc_socketmgr_create");
1333 result = isc_entropy_create(mctx, &entp);
1334 check_result(result, "isc_entropy_create");
1336 result = dst_lib_init(mctx, entp, 0);
1337 check_result(result, "dst_lib_init");
1338 is_dst_up = ISC_TRUE;
1340 result = isc_mempool_create(mctx, COMMSIZE, &commctx);
1341 check_result(result, "isc_mempool_create");
1342 isc_mempool_setname(commctx, "COMMPOOL");
1344 * 6 and 2 set as reasonable parameters for 3 or 4 nameserver
1347 isc_mempool_setfreemax(commctx, 6);
1348 isc_mempool_setfillcount(commctx, 2);
1350 result = isc_mutex_init(&lookup_lock);
1351 check_result(result, "isc_mutex_init");
1353 dns_result_register();
1357 * Add EDNS0 option record to a message. Currently, the only supported
1358 * options are UDP buffer size, the DO bit, and NSID request.
1361 add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns,
1362 isc_boolean_t dnssec, isc_boolean_t nsid)
1364 dns_rdataset_t *rdataset = NULL;
1365 dns_rdatalist_t *rdatalist = NULL;
1366 dns_rdata_t *rdata = NULL;
1367 isc_result_t result;
1370 result = dns_message_gettemprdataset(msg, &rdataset);
1371 check_result(result, "dns_message_gettemprdataset");
1372 dns_rdataset_init(rdataset);
1373 result = dns_message_gettemprdatalist(msg, &rdatalist);
1374 check_result(result, "dns_message_gettemprdatalist");
1375 result = dns_message_gettemprdata(msg, &rdata);
1376 check_result(result, "dns_message_gettemprdata");
1378 debug("setting udp size of %d", udpsize);
1379 rdatalist->type = dns_rdatatype_opt;
1380 rdatalist->covers = 0;
1381 rdatalist->rdclass = udpsize;
1382 rdatalist->ttl = edns << 16;
1384 rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
1386 isc_buffer_t *b = NULL;
1388 result = isc_buffer_allocate(mctx, &b, 4);
1389 check_result(result, "isc_buffer_allocate");
1390 isc_buffer_putuint16(b, DNS_OPT_NSID);
1391 isc_buffer_putuint16(b, 0);
1392 rdata->data = isc_buffer_base(b);
1393 rdata->length = isc_buffer_usedlength(b);
1394 dns_message_takebuffer(msg, &b);
1399 ISC_LIST_INIT(rdatalist->rdata);
1400 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1401 dns_rdatalist_tordataset(rdatalist, rdataset);
1402 result = dns_message_setopt(msg, rdataset);
1403 check_result(result, "dns_message_setopt");
1407 * Add a question section to a message, asking for the specified name,
1411 add_question(dns_message_t *message, dns_name_t *name,
1412 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype)
1414 dns_rdataset_t *rdataset;
1415 isc_result_t result;
1417 debug("add_question()");
1419 result = dns_message_gettemprdataset(message, &rdataset);
1420 check_result(result, "dns_message_gettemprdataset()");
1421 dns_rdataset_init(rdataset);
1422 dns_rdataset_makequestion(rdataset, rdclass, rdtype);
1423 ISC_LIST_APPEND(name->list, rdataset, link);
1427 * Check if we're done with all the queued lookups, which is true iff
1428 * all sockets, sends, and recvs are accounted for (counters == 0),
1429 * and the lookup list is empty.
1430 * If we are done, pass control back out to dighost_shutdown() (which is
1431 * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
1432 * a whole or reseed the lookup list.
1435 check_if_done(void) {
1436 debug("check_if_done()");
1437 debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
1438 if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
1440 INSIST(sockcount == 0);
1441 INSIST(recvcount == 0);
1442 debug("shutting down");
1448 * Clear out a query when we're done with it. WARNING: This routine
1449 * WILL invalidate the query pointer.
1452 clear_query(dig_query_t *query) {
1453 dig_lookup_t *lookup;
1455 REQUIRE(query != NULL);
1457 debug("clear_query(%p)", query);
1459 lookup = query->lookup;
1461 if (lookup->current_query == query)
1462 lookup->current_query = NULL;
1464 ISC_LIST_UNLINK(lookup->q, query, link);
1465 if (ISC_LINK_LINKED(&query->recvbuf, link))
1466 ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf,
1468 if (ISC_LINK_LINKED(&query->lengthbuf, link))
1469 ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf,
1471 INSIST(query->recvspace != NULL);
1472 if (query->sock != NULL) {
1473 isc_socket_detach(&query->sock);
1475 debug("sockcount=%d", sockcount);
1477 isc_mempool_put(commctx, query->recvspace);
1478 isc_buffer_invalidate(&query->recvbuf);
1479 isc_buffer_invalidate(&query->lengthbuf);
1480 if (query->waiting_senddone)
1481 query->pending_free = ISC_TRUE;
1483 isc_mem_free(mctx, query);
1487 * Try and clear out a lookup if we're done with it. Return ISC_TRUE if
1488 * the lookup was successfully cleared. If ISC_TRUE is returned, the
1489 * lookup pointer has been invalidated.
1491 static isc_boolean_t
1492 try_clear_lookup(dig_lookup_t *lookup) {
1495 REQUIRE(lookup != NULL);
1497 debug("try_clear_lookup(%p)", lookup);
1499 if (ISC_LIST_HEAD(lookup->q) != NULL) {
1501 q = ISC_LIST_HEAD(lookup->q);
1503 debug("query to %s still pending", q->servname);
1504 q = ISC_LIST_NEXT(q, link);
1511 * At this point, we know there are no queries on the lookup,
1512 * so can make it go away also.
1514 destroy_lookup(lookup);
1519 destroy_lookup(dig_lookup_t *lookup) {
1524 s = ISC_LIST_HEAD(lookup->my_server_list);
1526 debug("freeing server %p belonging to %p", s, lookup);
1528 s = ISC_LIST_NEXT(s, link);
1529 ISC_LIST_DEQUEUE(lookup->my_server_list,
1530 (dig_server_t *)ptr, link);
1531 isc_mem_free(mctx, ptr);
1533 if (lookup->sendmsg != NULL)
1534 dns_message_destroy(&lookup->sendmsg);
1535 if (lookup->querysig != NULL) {
1536 debug("freeing buffer %p", lookup->querysig);
1537 isc_buffer_free(&lookup->querysig);
1539 if (lookup->timer != NULL)
1540 isc_timer_detach(&lookup->timer);
1541 if (lookup->sendspace != NULL)
1542 isc_mempool_put(commctx, lookup->sendspace);
1544 if (lookup->tsigctx != NULL)
1545 dst_context_destroy(&lookup->tsigctx);
1547 isc_mem_free(mctx, lookup);
1551 * If we can, start the next lookup in the queue running.
1552 * This assumes that the lookup on the head of the queue hasn't been
1553 * started yet. It also removes the lookup from the head of the queue,
1554 * setting the current_lookup pointer pointing to it.
1557 start_lookup(void) {
1558 debug("start_lookup()");
1563 * If there's a current lookup running, we really shouldn't get
1566 INSIST(current_lookup == NULL);
1568 current_lookup = ISC_LIST_HEAD(lookup_list);
1570 * Put the current lookup somewhere so cancel_all can find it
1572 if (current_lookup != NULL) {
1573 ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
1575 if (current_lookup->do_topdown &&
1576 !current_lookup->rdtype_sigchaseset) {
1577 dst_key_t *trustedkey = NULL;
1578 isc_buffer_t *b = NULL;
1580 isc_result_t result;
1581 dns_name_t query_name;
1582 dns_name_t *key_name;
1585 result = get_trusted_key(mctx);
1586 if (result != ISC_R_SUCCESS) {
1587 printf("\n;; No trusted key, "
1588 "+sigchase option is disabled\n");
1589 current_lookup->sigchase = ISC_FALSE;
1592 dns_name_init(&query_name, NULL);
1593 nameFromString(current_lookup->textname, &query_name);
1595 for (i = 0; i < tk_list.nb_tk; i++) {
1596 key_name = dst_key_name(tk_list.key[i]);
1598 if (dns_name_issubdomain(&query_name,
1599 key_name) == ISC_TRUE)
1600 trustedkey = tk_list.key[i];
1602 * Verify temp is really the lowest
1606 if (trustedkey == NULL) {
1607 printf("\n;; The queried zone: ");
1608 dns_name_print(&query_name, stdout);
1609 printf(" isn't a subdomain of any Trusted Keys"
1610 ": +sigchase option is disable\n");
1611 current_lookup->sigchase = ISC_FALSE;
1612 free_name(&query_name, mctx);
1615 free_name(&query_name, mctx);
1617 current_lookup->rdtype_sigchase
1618 = current_lookup->rdtype;
1619 current_lookup->rdtype_sigchaseset
1620 = current_lookup->rdtypeset;
1621 current_lookup->rdtype = dns_rdatatype_ns;
1623 current_lookup->qrdtype_sigchase
1624 = current_lookup->qrdtype;
1625 current_lookup->qrdtype = dns_rdatatype_ns;
1627 current_lookup->rdclass_sigchase
1628 = current_lookup->rdclass;
1629 current_lookup->rdclass_sigchaseset
1630 = current_lookup->rdclassset;
1631 current_lookup->rdclass = dns_rdataclass_in;
1633 strncpy(current_lookup->textnamesigchase,
1634 current_lookup->textname, MXNAME);
1636 current_lookup->trace_root_sigchase = ISC_TRUE;
1638 result = isc_buffer_allocate(mctx, &b, BUFSIZE);
1639 check_result(result, "isc_buffer_allocate");
1640 result = dns_name_totext(dst_key_name(trustedkey),
1642 check_result(result, "dns_name_totext");
1643 isc_buffer_usedregion(b, &r);
1644 r.base[r.length] = '\0';
1645 strncpy(current_lookup->textname, (char*)r.base,
1647 isc_buffer_free(&b);
1649 nameFromString(current_lookup->textnamesigchase,
1652 dns_name_init(&chase_authority_name, NULL);
1656 setup_lookup(current_lookup);
1657 do_lookup(current_lookup);
1664 * If we can, clear the current lookup and start the next one running.
1665 * This calls try_clear_lookup, so may invalidate the lookup pointer.
1668 check_next_lookup(dig_lookup_t *lookup) {
1672 debug("check_next_lookup(%p)", lookup);
1674 if (ISC_LIST_HEAD(lookup->q) != NULL) {
1675 debug("still have a worker");
1678 if (try_clear_lookup(lookup)) {
1679 current_lookup = NULL;
1685 * Create and queue a new lookup as a followup to the current lookup,
1686 * based on the supplied message and section. This is used in trace and
1687 * name server search modes to start a new lookup using servers from
1688 * NS records in a reply. Returns the number of followup lookups made.
1691 followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section)
1693 dig_lookup_t *lookup = NULL;
1694 dig_server_t *srv = NULL;
1695 dns_rdataset_t *rdataset = NULL;
1696 dns_rdata_t rdata = DNS_RDATA_INIT;
1697 dns_name_t *name = NULL;
1698 isc_result_t result;
1699 isc_boolean_t success = ISC_FALSE;
1702 isc_boolean_t horizontal = ISC_FALSE, bad = ISC_FALSE;
1706 debug("following up %s", query->lookup->textname);
1708 for (result = dns_message_firstname(msg, section);
1709 result == ISC_R_SUCCESS;
1710 result = dns_message_nextname(msg, section)) {
1712 dns_message_currentname(msg, section, &name);
1714 if (section == DNS_SECTION_AUTHORITY) {
1716 result = dns_message_findtype(name, dns_rdatatype_soa,
1718 if (result == ISC_R_SUCCESS)
1722 result = dns_message_findtype(name, dns_rdatatype_ns, 0,
1724 if (result != ISC_R_SUCCESS)
1727 debug("found NS set");
1729 if (query->lookup->trace && !query->lookup->trace_root) {
1730 dns_namereln_t namereln;
1731 unsigned int nlabels;
1734 domain = dns_fixedname_name(&query->lookup->fdomain);
1735 namereln = dns_name_fullcompare(name, domain,
1737 if (namereln == dns_namereln_equal) {
1739 printf(";; BAD (HORIZONTAL) REFERRAL\n");
1740 horizontal = ISC_TRUE;
1741 } else if (namereln != dns_namereln_subdomain) {
1743 printf(";; BAD REFERRAL\n");
1749 for (result = dns_rdataset_first(rdataset);
1750 result == ISC_R_SUCCESS;
1751 result = dns_rdataset_next(rdataset)) {
1752 char namestr[DNS_NAME_FORMATSIZE];
1755 if (query->lookup->trace_root &&
1756 query->lookup->nsfound >= MXSERV)
1759 dns_rdataset_current(rdataset, &rdata);
1761 query->lookup->nsfound++;
1762 result = dns_rdata_tostruct(&rdata, &ns, NULL);
1763 check_result(result, "dns_rdata_tostruct");
1764 dns_name_format(&ns.name, namestr, sizeof(namestr));
1765 dns_rdata_freestruct(&ns);
1767 /* Initialize lookup if we've not yet */
1768 debug("found NS %s", namestr);
1772 lookup = requeue_lookup(query->lookup,
1774 cancel_lookup(query->lookup);
1775 lookup->doing_xfr = ISC_FALSE;
1776 if (!lookup->trace_root &&
1777 section == DNS_SECTION_ANSWER)
1778 lookup->trace = ISC_FALSE;
1780 lookup->trace = query->lookup->trace;
1781 lookup->ns_search_only =
1782 query->lookup->ns_search_only;
1783 lookup->trace_root = ISC_FALSE;
1784 if (lookup->ns_search_only)
1785 lookup->recurse = ISC_FALSE;
1786 dns_fixedname_init(&lookup->fdomain);
1787 domain = dns_fixedname_name(&lookup->fdomain);
1788 dns_name_copy(name, domain, NULL);
1790 debug("adding server %s", namestr);
1791 numLookups += getaddresses(lookup, namestr);
1792 dns_rdata_reset(&rdata);
1796 if (lookup == NULL &&
1797 section == DNS_SECTION_ANSWER &&
1798 (query->lookup->trace || query->lookup->ns_search_only))
1799 return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY));
1802 * Randomize the order the nameserver will be tried.
1804 if (numLookups > 1) {
1806 dig_serverlist_t my_server_list;
1809 ISC_LIST_INIT(my_server_list);
1812 for (srv = ISC_LIST_HEAD(lookup->my_server_list);
1814 srv = ISC_LIST_HEAD(lookup->my_server_list)) {
1818 next = ISC_LIST_NEXT(srv, link);
1819 while (j-- > 0 && next != NULL) {
1821 next = ISC_LIST_NEXT(srv, link);
1823 ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link);
1824 ISC_LIST_APPEND(my_server_list, srv, link);
1827 ISC_LIST_APPENDLIST(lookup->my_server_list,
1828 my_server_list, link);
1831 return (numLookups);
1835 * Create and queue a new lookup using the next origin from the search
1836 * list, read in setup_system().
1838 * Return ISC_TRUE iff there was another searchlist entry.
1840 static isc_boolean_t
1841 next_origin(dns_message_t *msg, dig_query_t *query) {
1842 dig_lookup_t *lookup;
1843 dig_searchlist_t *search;
1849 debug("next_origin()");
1850 debug("following up %s", query->lookup->textname);
1854 * We're not using a search list, so don't even think
1855 * about finding the next entry.
1858 if (query->lookup->origin == NULL && !query->lookup->need_search)
1860 * Then we just did rootorg; there's nothing left.
1863 if (query->lookup->origin == NULL && query->lookup->need_search) {
1864 lookup = requeue_lookup(query->lookup, ISC_TRUE);
1865 lookup->origin = ISC_LIST_HEAD(search_list);
1866 lookup->need_search = ISC_FALSE;
1868 search = ISC_LIST_NEXT(query->lookup->origin, link);
1869 if (search == NULL && query->lookup->done_as_is)
1871 lookup = requeue_lookup(query->lookup, ISC_TRUE);
1872 lookup->origin = search;
1874 cancel_lookup(query->lookup);
1879 * Insert an SOA record into the sendmessage in a lookup. Used for
1880 * creating IXFR queries.
1883 insert_soa(dig_lookup_t *lookup) {
1884 isc_result_t result;
1885 dns_rdata_soa_t soa;
1886 dns_rdata_t *rdata = NULL;
1887 dns_rdatalist_t *rdatalist = NULL;
1888 dns_rdataset_t *rdataset = NULL;
1889 dns_name_t *soaname = NULL;
1891 debug("insert_soa()");
1893 soa.serial = lookup->ixfr_serial;
1898 soa.common.rdclass = lookup->rdclass;
1899 soa.common.rdtype = dns_rdatatype_soa;
1901 dns_name_init(&soa.origin, NULL);
1902 dns_name_init(&soa.contact, NULL);
1904 dns_name_clone(dns_rootname, &soa.origin);
1905 dns_name_clone(dns_rootname, &soa.contact);
1907 isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
1908 sizeof(lookup->rdatastore));
1910 result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
1911 check_result(result, "dns_message_gettemprdata");
1913 result = dns_rdata_fromstruct(rdata, lookup->rdclass,
1914 dns_rdatatype_soa, &soa,
1916 check_result(result, "isc_rdata_fromstruct");
1918 result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
1919 check_result(result, "dns_message_gettemprdatalist");
1921 result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
1922 check_result(result, "dns_message_gettemprdataset");
1924 dns_rdatalist_init(rdatalist);
1925 rdatalist->type = dns_rdatatype_soa;
1926 rdatalist->rdclass = lookup->rdclass;
1927 rdatalist->covers = 0;
1929 ISC_LIST_INIT(rdatalist->rdata);
1930 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1932 dns_rdataset_init(rdataset);
1933 dns_rdatalist_tordataset(rdatalist, rdataset);
1935 result = dns_message_gettempname(lookup->sendmsg, &soaname);
1936 check_result(result, "dns_message_gettempname");
1937 dns_name_init(soaname, NULL);
1938 dns_name_clone(lookup->name, soaname);
1939 ISC_LIST_INIT(soaname->list);
1940 ISC_LIST_APPEND(soaname->list, rdataset, link);
1941 dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
1945 * Setup the supplied lookup structure, making it ready to start sending
1946 * queries to servers. Create and initialize the message to be sent as
1947 * well as the query structures and buffer space for the replies. If the
1948 * server list is empty, clone it from the system default list.
1951 setup_lookup(dig_lookup_t *lookup) {
1952 isc_result_t result;
1958 dns_compress_t cctx;
1962 char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME];
1966 result = dns_name_settotextfilter(output_filter);
1967 check_result(result, "dns_name_settotextfilter");
1970 REQUIRE(lookup != NULL);
1973 debug("setup_lookup(%p)", lookup);
1975 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
1977 check_result(result, "dns_message_create");
1979 if (lookup->new_search) {
1980 debug("resetting lookup counter.");
1984 if (ISC_LIST_EMPTY(lookup->my_server_list)) {
1985 debug("cloning server list");
1986 clone_server_list(server_list, &lookup->my_server_list);
1988 result = dns_message_gettempname(lookup->sendmsg, &lookup->name);
1989 check_result(result, "dns_message_gettempname");
1990 dns_name_init(lookup->name, NULL);
1992 isc_buffer_init(&lookup->namebuf, lookup->namespace,
1993 sizeof(lookup->namespace));
1994 isc_buffer_init(&lookup->onamebuf, lookup->onamespace,
1995 sizeof(lookup->onamespace));
1999 * We cannot convert `textname' and `origin' separately.
2000 * `textname' doesn't contain TLD, but local mapping needs
2003 mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname,
2004 utf8_textname, sizeof(utf8_textname));
2005 idn_check_result(mr, "convert textname to UTF-8");
2009 * If the name has too many dots, force the origin to be NULL
2010 * (which produces an absolute lookup). Otherwise, take the origin
2011 * we have if there's one in the struct already. If it's NULL,
2012 * take the first entry in the searchlist iff either usesearch
2013 * is TRUE or we got a domain line in the resolv.conf file.
2015 if (lookup->new_search) {
2017 if ((count_dots(utf8_textname) >= ndots) || !usesearch) {
2018 lookup->origin = NULL; /* Force abs lookup */
2019 lookup->done_as_is = ISC_TRUE;
2020 lookup->need_search = usesearch;
2021 } else if (lookup->origin == NULL && usesearch) {
2022 lookup->origin = ISC_LIST_HEAD(search_list);
2023 lookup->need_search = ISC_FALSE;
2026 if ((count_dots(lookup->textname) >= ndots) || !usesearch) {
2027 lookup->origin = NULL; /* Force abs lookup */
2028 lookup->done_as_is = ISC_TRUE;
2029 lookup->need_search = usesearch;
2030 } else if (lookup->origin == NULL && usesearch) {
2031 lookup->origin = ISC_LIST_HEAD(search_list);
2032 lookup->need_search = ISC_FALSE;
2038 if (lookup->origin != NULL) {
2039 mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP,
2040 lookup->origin->origin, utf8_origin,
2041 sizeof(utf8_origin));
2042 idn_check_result(mr, "convert origin to UTF-8");
2043 mr = append_textname(utf8_textname, utf8_origin,
2044 sizeof(utf8_textname));
2045 idn_check_result(mr, "append origin to textname");
2047 mr = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP |
2048 IDN_IDNCONV | IDN_LENCHECK, utf8_textname,
2049 idn_textname, sizeof(idn_textname));
2050 idn_check_result(mr, "convert UTF-8 textname to IDN encoding");
2052 if (lookup->origin != NULL) {
2053 debug("trying origin %s", lookup->origin->origin);
2054 result = dns_message_gettempname(lookup->sendmsg,
2056 check_result(result, "dns_message_gettempname");
2057 dns_name_init(lookup->oname, NULL);
2058 /* XXX Helper funct to conv char* to name? */
2059 len = strlen(lookup->origin->origin);
2060 isc_buffer_init(&b, lookup->origin->origin, len);
2061 isc_buffer_add(&b, len);
2062 result = dns_name_fromtext(lookup->oname, &b, dns_rootname,
2063 0, &lookup->onamebuf);
2064 if (result != ISC_R_SUCCESS) {
2065 dns_message_puttempname(lookup->sendmsg,
2067 dns_message_puttempname(lookup->sendmsg,
2069 fatal("'%s' is not in legal name syntax (%s)",
2070 lookup->origin->origin,
2071 isc_result_totext(result));
2073 if (lookup->trace && lookup->trace_root) {
2074 dns_name_clone(dns_rootname, lookup->name);
2076 len = strlen(lookup->textname);
2077 isc_buffer_init(&b, lookup->textname, len);
2078 isc_buffer_add(&b, len);
2079 result = dns_name_fromtext(lookup->name, &b,
2083 if (result != ISC_R_SUCCESS) {
2084 dns_message_puttempname(lookup->sendmsg,
2086 dns_message_puttempname(lookup->sendmsg,
2088 fatal("'%s' is not in legal name syntax (%s)",
2089 lookup->textname, isc_result_totext(result));
2091 dns_message_puttempname(lookup->sendmsg, &lookup->oname);
2095 debug("using root origin");
2096 if (lookup->trace && lookup->trace_root)
2097 dns_name_clone(dns_rootname, lookup->name);
2100 len = strlen(idn_textname);
2101 isc_buffer_init(&b, idn_textname, len);
2102 isc_buffer_add(&b, len);
2103 result = dns_name_fromtext(lookup->name, &b,
2107 len = strlen(lookup->textname);
2108 isc_buffer_init(&b, lookup->textname, len);
2109 isc_buffer_add(&b, len);
2110 result = dns_name_fromtext(lookup->name, &b,
2115 if (result != ISC_R_SUCCESS) {
2116 dns_message_puttempname(lookup->sendmsg,
2118 isc_buffer_init(&b, store, MXNAME);
2119 fatal("'%s' is not a legal name "
2120 "(%s)", lookup->textname,
2121 isc_result_totext(result));
2124 dns_name_format(lookup->name, store, sizeof(store));
2125 trying(store, lookup);
2126 INSIST(dns_name_isabsolute(lookup->name));
2128 isc_random_get(&id);
2129 lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
2130 lookup->sendmsg->opcode = dns_opcode_query;
2131 lookup->msgcounter = 0;
2133 * If this is a trace request, completely disallow recursion, since
2134 * it's meaningless for traces.
2136 if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root))
2137 lookup->recurse = ISC_FALSE;
2139 if (lookup->recurse &&
2140 lookup->rdtype != dns_rdatatype_axfr &&
2141 lookup->rdtype != dns_rdatatype_ixfr) {
2142 debug("recursive query");
2143 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD;
2147 if (lookup->aaonly) {
2149 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA;
2152 if (lookup->adflag) {
2154 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD;
2157 if (lookup->cdflag) {
2159 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD;
2162 dns_message_addname(lookup->sendmsg, lookup->name,
2163 DNS_SECTION_QUESTION);
2165 if (lookup->trace && lookup->trace_root) {
2166 lookup->qrdtype = lookup->rdtype;
2167 lookup->rdtype = dns_rdatatype_ns;
2170 if ((lookup->rdtype == dns_rdatatype_axfr) ||
2171 (lookup->rdtype == dns_rdatatype_ixfr)) {
2173 * Force TCP mode if we're doing an axfr.
2175 if (lookup->rdtype == dns_rdatatype_axfr) {
2176 lookup->doing_xfr = ISC_TRUE;
2177 lookup->tcp_mode = ISC_TRUE;
2178 } else if (lookup->tcp_mode) {
2179 lookup->doing_xfr = ISC_TRUE;
2183 add_question(lookup->sendmsg, lookup->name, lookup->rdclass,
2187 if (lookup->rdtype == dns_rdatatype_ixfr)
2190 /* XXX Insist this? */
2191 lookup->tsigctx = NULL;
2192 lookup->querysig = NULL;
2194 debug("initializing keys");
2195 result = dns_message_settsigkey(lookup->sendmsg, key);
2196 check_result(result, "dns_message_settsigkey");
2199 lookup->sendspace = isc_mempool_get(commctx);
2200 if (lookup->sendspace == NULL)
2201 fatal("memory allocation failure");
2203 result = dns_compress_init(&cctx, -1, mctx);
2204 check_result(result, "dns_compress_init");
2206 debug("starting to render the message");
2207 isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE);
2208 result = dns_message_renderbegin(lookup->sendmsg, &cctx,
2209 &lookup->renderbuf);
2210 check_result(result, "dns_message_renderbegin");
2211 if (lookup->udpsize > 0 || lookup->dnssec || lookup->edns > -1) {
2212 if (lookup->udpsize == 0)
2213 lookup->udpsize = 4096;
2214 if (lookup->edns < 0)
2216 add_opt(lookup->sendmsg, lookup->udpsize,
2217 lookup->edns, lookup->dnssec, lookup->nsid);
2220 result = dns_message_rendersection(lookup->sendmsg,
2221 DNS_SECTION_QUESTION, 0);
2222 check_result(result, "dns_message_rendersection");
2223 result = dns_message_rendersection(lookup->sendmsg,
2224 DNS_SECTION_AUTHORITY, 0);
2225 check_result(result, "dns_message_rendersection");
2226 result = dns_message_renderend(lookup->sendmsg);
2227 check_result(result, "dns_message_renderend");
2228 debug("done rendering");
2230 dns_compress_invalidate(&cctx);
2233 * Force TCP mode if the request is larger than 512 bytes.
2235 if (isc_buffer_usedlength(&lookup->renderbuf) > 512)
2236 lookup->tcp_mode = ISC_TRUE;
2238 lookup->pending = ISC_FALSE;
2240 for (serv = ISC_LIST_HEAD(lookup->my_server_list);
2242 serv = ISC_LIST_NEXT(serv, link)) {
2243 query = isc_mem_allocate(mctx, sizeof(dig_query_t));
2245 fatal("memory allocation failure in %s:%d",
2246 __FILE__, __LINE__);
2247 debug("create query %p linked to lookup %p",
2249 query->lookup = lookup;
2250 query->waiting_connect = ISC_FALSE;
2251 query->waiting_senddone = ISC_FALSE;
2252 query->pending_free = ISC_FALSE;
2253 query->recv_made = ISC_FALSE;
2254 query->first_pass = ISC_TRUE;
2255 query->first_soa_rcvd = ISC_FALSE;
2256 query->second_rr_rcvd = ISC_FALSE;
2257 query->first_repeat_rcvd = ISC_FALSE;
2258 query->warn_id = ISC_TRUE;
2259 query->first_rr_serial = 0;
2260 query->second_rr_serial = 0;
2261 query->servname = serv->servername;
2262 query->userarg = serv->userarg;
2263 query->rr_count = 0;
2264 query->msg_count = 0;
2265 query->byte_count = 0;
2266 ISC_LINK_INIT(query, link);
2267 ISC_LIST_INIT(query->recvlist);
2268 ISC_LIST_INIT(query->lengthlist);
2270 query->recvspace = isc_mempool_get(commctx);
2271 if (query->recvspace == NULL)
2272 fatal("memory allocation failure");
2274 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
2275 isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
2276 isc_buffer_init(&query->slbuf, query->slspace, 2);
2277 query->sendbuf = lookup->renderbuf;
2279 ISC_LINK_INIT(query, link);
2280 ISC_LIST_ENQUEUE(lookup->q, query, link);
2282 /* XXX qrflag, print_query, etc... */
2283 if (!ISC_LIST_EMPTY(lookup->q) && qr) {
2285 printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg,
2291 * Event handler for send completion. Track send counter, and clear out
2292 * the query if the send was canceled.
2295 send_done(isc_task_t *_task, isc_event_t *event) {
2296 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
2297 isc_buffer_t *b = NULL;
2298 dig_query_t *query, *next;
2301 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
2307 debug("send_done()");
2309 debug("sendcount=%d", sendcount);
2310 INSIST(sendcount >= 0);
2312 for (b = ISC_LIST_HEAD(sevent->bufferlist);
2314 b = ISC_LIST_HEAD(sevent->bufferlist))
2315 ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2317 query = event->ev_arg;
2318 query->waiting_senddone = ISC_FALSE;
2321 if (l->ns_search_only && !l->trace_root) {
2322 debug("sending next, since searching");
2323 next = ISC_LIST_NEXT(query, link);
2328 isc_event_free(&event);
2330 if (query->pending_free)
2331 isc_mem_free(mctx, query);
2338 * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
2339 * IO sockets. The cancel handlers should take care of cleaning up the
2340 * query and lookup structures
2343 cancel_lookup(dig_lookup_t *lookup) {
2344 dig_query_t *query, *next;
2346 debug("cancel_lookup()");
2347 query = ISC_LIST_HEAD(lookup->q);
2348 while (query != NULL) {
2349 next = ISC_LIST_NEXT(query, link);
2350 if (query->sock != NULL) {
2351 isc_socket_cancel(query->sock, global_task,
2352 ISC_SOCKCANCEL_ALL);
2359 if (lookup->timer != NULL)
2360 isc_timer_detach(&lookup->timer);
2361 lookup->pending = ISC_FALSE;
2362 lookup->retries = 0;
2366 bringup_timer(dig_query_t *query, unsigned int default_timeout) {
2368 unsigned int local_timeout;
2369 isc_result_t result;
2371 debug("bringup_timer()");
2373 * If the timer already exists, that means we're calling this
2374 * a second time (for a retry). Don't need to recreate it,
2378 if (ISC_LIST_NEXT(query, link) != NULL)
2379 local_timeout = SERVER_TIMEOUT;
2382 local_timeout = default_timeout;
2384 local_timeout = timeout;
2386 debug("have local timeout of %d", local_timeout);
2387 isc_interval_set(&l->interval, local_timeout, 0);
2388 if (l->timer != NULL)
2389 isc_timer_detach(&l->timer);
2390 result = isc_timer_create(timermgr, isc_timertype_once, NULL,
2391 &l->interval, global_task, connect_timeout,
2393 check_result(result, "isc_timer_create");
2397 force_timeout(dig_lookup_t *l, dig_query_t *query) {
2400 event = isc_event_allocate(mctx, query, ISC_TIMEREVENT_IDLE,
2402 sizeof(isc_event_t));
2403 if (event == NULL) {
2404 fatal("isc_event_allocate: %s",
2405 isc_result_totext(ISC_R_NOMEMORY));
2407 isc_task_send(global_task, &event);
2410 * The timer may have expired if, for example, get_address() takes
2411 * long time and the timer was running on a different thread.
2412 * We need to cancel the possible timeout event not to confuse
2413 * ourselves due to the duplicate events.
2415 if (l->timer != NULL)
2416 isc_timer_detach(&l->timer);
2421 connect_done(isc_task_t *task, isc_event_t *event);
2424 * Unlike send_udp, this can't be called multiple times with the same
2425 * query. When we retry TCP, we requeue the whole lookup, which should
2429 send_tcp_connect(dig_query_t *query) {
2430 isc_result_t result;
2434 debug("send_tcp_connect(%p)", query);
2437 query->waiting_connect = ISC_TRUE;
2438 query->lookup->current_query = query;
2439 result = get_address(query->servname, port, &query->sockaddr);
2440 if (result != ISC_R_SUCCESS) {
2442 * This servname doesn't have an address. Try the next server
2443 * by triggering an immediate 'timeout' (we lie, but the effect
2446 force_timeout(l, query);
2450 if (specified_source &&
2451 (isc_sockaddr_pf(&query->sockaddr) !=
2452 isc_sockaddr_pf(&bind_address))) {
2453 printf(";; Skipping server %s, incompatible "
2454 "address family\n", query->servname);
2455 query->waiting_connect = ISC_FALSE;
2456 next = ISC_LIST_NEXT(query, link);
2460 printf(";; No acceptable nameservers\n");
2461 check_next_lookup(l);
2464 send_tcp_connect(next);
2467 INSIST(query->sock == NULL);
2468 result = isc_socket_create(socketmgr,
2469 isc_sockaddr_pf(&query->sockaddr),
2470 isc_sockettype_tcp, &query->sock);
2471 check_result(result, "isc_socket_create");
2473 debug("sockcount=%d", sockcount);
2474 if (specified_source)
2475 result = isc_socket_bind(query->sock, &bind_address,
2476 ISC_SOCKET_REUSEADDRESS);
2478 if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
2480 isc_sockaddr_any(&bind_any);
2482 isc_sockaddr_any6(&bind_any);
2483 result = isc_socket_bind(query->sock, &bind_any, 0);
2485 check_result(result, "isc_socket_bind");
2486 bringup_timer(query, TCP_TIMEOUT);
2487 result = isc_socket_connect(query->sock, &query->sockaddr,
2488 global_task, connect_done, query);
2489 check_result(result, "isc_socket_connect");
2491 * If we're at the endgame of a nameserver search, we need to
2492 * immediately bring up all the queries. Do it here.
2494 if (l->ns_search_only && !l->trace_root) {
2495 debug("sending next, since searching");
2496 next = ISC_LIST_NEXT(query, link);
2498 send_tcp_connect(next);
2503 * Send a UDP packet to the remote nameserver, possible starting the
2504 * recv action as well. Also make sure that the timer is running and
2505 * is properly reset.
2508 send_udp(dig_query_t *query) {
2509 dig_lookup_t *l = NULL;
2510 isc_result_t result;
2512 debug("send_udp(%p)", query);
2515 bringup_timer(query, UDP_TIMEOUT);
2516 l->current_query = query;
2517 debug("working on lookup %p, query %p", query->lookup, query);
2518 if (!query->recv_made) {
2519 /* XXX Check the sense of this, need assertion? */
2520 query->waiting_connect = ISC_FALSE;
2521 result = get_address(query->servname, port, &query->sockaddr);
2522 if (result != ISC_R_SUCCESS) {
2523 /* This servname doesn't have an address. */
2524 force_timeout(l, query);
2528 result = isc_socket_create(socketmgr,
2529 isc_sockaddr_pf(&query->sockaddr),
2530 isc_sockettype_udp, &query->sock);
2531 check_result(result, "isc_socket_create");
2533 debug("sockcount=%d", sockcount);
2534 if (specified_source) {
2535 result = isc_socket_bind(query->sock, &bind_address,
2536 ISC_SOCKET_REUSEADDRESS);
2538 isc_sockaddr_anyofpf(&bind_any,
2539 isc_sockaddr_pf(&query->sockaddr));
2540 result = isc_socket_bind(query->sock, &bind_any, 0);
2542 check_result(result, "isc_socket_bind");
2544 query->recv_made = ISC_TRUE;
2545 ISC_LINK_INIT(&query->recvbuf, link);
2546 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf,
2548 debug("recving with lookup=%p, query=%p, sock=%p",
2549 query->lookup, query, query->sock);
2550 result = isc_socket_recvv(query->sock, &query->recvlist, 1,
2551 global_task, recv_done, query);
2552 check_result(result, "isc_socket_recvv");
2554 debug("recvcount=%d", recvcount);
2556 ISC_LIST_INIT(query->sendlist);
2557 ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link);
2558 debug("sending a request");
2559 TIME_NOW(&query->time_sent);
2560 INSIST(query->sock != NULL);
2561 query->waiting_senddone = ISC_TRUE;
2562 result = isc_socket_sendtov(query->sock, &query->sendlist,
2563 global_task, send_done, query,
2564 &query->sockaddr, NULL);
2565 check_result(result, "isc_socket_sendtov");
2570 * IO timeout handler, used for both connect and recv timeouts. If
2571 * retries are still allowed, either resend the UDP packet or queue a
2572 * new TCP lookup. Otherwise, cancel the lookup.
2575 connect_timeout(isc_task_t *task, isc_event_t *event) {
2576 dig_lookup_t *l = NULL;
2577 dig_query_t *query = NULL, *cq;
2580 REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE);
2582 debug("connect_timeout()");
2586 query = l->current_query;
2587 isc_event_free(&event);
2591 if ((query != NULL) && (query->lookup->current_query != NULL) &&
2592 (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) {
2593 debug("trying next server...");
2594 cq = query->lookup->current_query;
2596 send_udp(ISC_LIST_NEXT(cq, link));
2598 if (query->sock != NULL)
2599 isc_socket_cancel(query->sock, NULL,
2600 ISC_SOCKCANCEL_ALL);
2601 send_tcp_connect(ISC_LIST_NEXT(cq, link));
2607 if (l->retries > 1) {
2610 debug("resending UDP request to first server");
2611 send_udp(ISC_LIST_HEAD(l->q));
2613 debug("making new TCP request, %d tries left",
2616 requeue_lookup(l, ISC_TRUE);
2618 check_next_lookup(l);
2621 fputs(l->cmdline, stdout);
2622 printf(";; connection timed out; no servers could be "
2625 check_next_lookup(l);
2633 * Event handler for the TCP recv which gets the length header of TCP
2634 * packets. Start the next recv of length bytes.
2637 tcp_length_done(isc_task_t *task, isc_event_t *event) {
2638 isc_socketevent_t *sevent;
2639 isc_buffer_t *b = NULL;
2640 isc_result_t result;
2641 dig_query_t *query = NULL;
2643 isc_uint16_t length;
2645 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
2650 debug("tcp_length_done()");
2653 sevent = (isc_socketevent_t *)event;
2654 query = event->ev_arg;
2657 INSIST(recvcount >= 0);
2659 b = ISC_LIST_HEAD(sevent->bufferlist);
2660 INSIST(b == &query->lengthbuf);
2661 ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2663 if (sevent->result == ISC_R_CANCELED) {
2664 isc_event_free(&event);
2667 check_next_lookup(l);
2671 if (sevent->result != ISC_R_SUCCESS) {
2672 char sockstr[ISC_SOCKADDR_FORMATSIZE];
2673 isc_sockaddr_format(&query->sockaddr, sockstr,
2675 printf(";; communications error to %s: %s\n",
2676 sockstr, isc_result_totext(sevent->result));
2678 isc_socket_detach(&query->sock);
2680 debug("sockcount=%d", sockcount);
2681 INSIST(sockcount >= 0);
2682 isc_event_free(&event);
2684 check_next_lookup(l);
2688 length = isc_buffer_getuint16(b);
2690 isc_event_free(&event);
2691 launch_next_query(query, ISC_FALSE);
2697 * Even though the buffer was already init'ed, we need
2698 * to redo it now, to force the length we want.
2700 isc_buffer_invalidate(&query->recvbuf);
2701 isc_buffer_init(&query->recvbuf, query->recvspace, length);
2702 ENSURE(ISC_LIST_EMPTY(query->recvlist));
2703 ISC_LINK_INIT(&query->recvbuf, link);
2704 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
2705 debug("recving with lookup=%p, query=%p", query->lookup, query);
2706 result = isc_socket_recvv(query->sock, &query->recvlist, length, task,
2708 check_result(result, "isc_socket_recvv");
2710 debug("resubmitted recv request with length %d, recvcount=%d",
2712 isc_event_free(&event);
2717 * For transfers that involve multiple recvs (XFR's in particular),
2718 * launch the next recv.
2721 launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
2722 isc_result_t result;
2727 debug("launch_next_query()");
2729 if (!query->lookup->pending) {
2730 debug("ignoring launch_next_query because !pending");
2731 isc_socket_detach(&query->sock);
2733 debug("sockcount=%d", sockcount);
2734 INSIST(sockcount >= 0);
2735 query->waiting_connect = ISC_FALSE;
2738 check_next_lookup(l);
2742 isc_buffer_clear(&query->slbuf);
2743 isc_buffer_clear(&query->lengthbuf);
2744 isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->sendbuf.used);
2745 ISC_LIST_INIT(query->sendlist);
2746 ISC_LINK_INIT(&query->slbuf, link);
2747 ISC_LIST_ENQUEUE(query->sendlist, &query->slbuf, link);
2748 if (include_question)
2749 ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link);
2750 ISC_LINK_INIT(&query->lengthbuf, link);
2751 ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
2753 result = isc_socket_recvv(query->sock, &query->lengthlist, 0,
2754 global_task, tcp_length_done, query);
2755 check_result(result, "isc_socket_recvv");
2757 debug("recvcount=%d", recvcount);
2758 if (!query->first_soa_rcvd) {
2759 debug("sending a request in launch_next_query");
2760 TIME_NOW(&query->time_sent);
2761 query->waiting_senddone = ISC_TRUE;
2762 result = isc_socket_sendv(query->sock, &query->sendlist,
2763 global_task, send_done, query);
2764 check_result(result, "isc_socket_sendv");
2766 debug("sendcount=%d", sendcount);
2768 query->waiting_connect = ISC_FALSE;
2770 check_next_lookup(query->lookup);
2776 * Event handler for TCP connect complete. Make sure the connection was
2777 * successful, then pass into launch_next_query to actually send the
2781 connect_done(isc_task_t *task, isc_event_t *event) {
2782 isc_socketevent_t *sevent = NULL;
2783 dig_query_t *query = NULL, *next;
2788 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
2791 debug("connect_done()");
2794 sevent = (isc_socketevent_t *)event;
2795 query = sevent->ev_arg;
2797 INSIST(query->waiting_connect);
2799 query->waiting_connect = ISC_FALSE;
2801 if (sevent->result == ISC_R_CANCELED) {
2802 debug("in cancel handler");
2803 isc_socket_detach(&query->sock);
2804 INSIST(sockcount > 0);
2806 debug("sockcount=%d", sockcount);
2807 query->waiting_connect = ISC_FALSE;
2808 isc_event_free(&event);
2811 check_next_lookup(l);
2815 if (sevent->result != ISC_R_SUCCESS) {
2816 char sockstr[ISC_SOCKADDR_FORMATSIZE];
2818 debug("unsuccessful connection: %s",
2819 isc_result_totext(sevent->result));
2820 isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
2821 if (sevent->result != ISC_R_CANCELED)
2822 printf(";; Connection to %s(%s) for %s failed: "
2824 query->servname, query->lookup->textname,
2825 isc_result_totext(sevent->result));
2826 isc_socket_detach(&query->sock);
2828 INSIST(sockcount >= 0);
2829 /* XXX Clean up exitcodes */
2832 debug("sockcount=%d", sockcount);
2833 query->waiting_connect = ISC_FALSE;
2834 isc_event_free(&event);
2836 if (l->current_query != NULL)
2837 next = ISC_LIST_NEXT(l->current_query, link);
2842 bringup_timer(next, TCP_TIMEOUT);
2843 send_tcp_connect(next);
2845 check_next_lookup(l);
2850 launch_next_query(query, ISC_TRUE);
2851 isc_event_free(&event);
2856 * Check if the ongoing XFR needs more data before it's complete, using
2857 * the semantics of IXFR and AXFR protocols. Much of the complexity of
2858 * this routine comes from determining when an IXFR is complete.
2859 * ISC_FALSE means more data is on the way, and the recv has been issued.
2861 static isc_boolean_t
2862 check_for_more_data(dig_query_t *query, dns_message_t *msg,
2863 isc_socketevent_t *sevent)
2865 dns_rdataset_t *rdataset = NULL;
2866 dns_rdata_t rdata = DNS_RDATA_INIT;
2867 dns_rdata_soa_t soa;
2868 isc_uint32_t serial;
2869 isc_result_t result;
2871 debug("check_for_more_data()");
2874 * By the time we're in this routine, we know we're doing
2875 * either an AXFR or IXFR. If there's no second_rr_type,
2876 * then we don't yet know which kind of answer we got back
2877 * from the server. Here, we're going to walk through the
2878 * rr's in the message, acting as necessary whenever we hit
2883 query->byte_count += sevent->n;
2884 result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
2885 if (result != ISC_R_SUCCESS) {
2886 puts("; Transfer failed.");
2892 dns_message_currentname(msg, DNS_SECTION_ANSWER,
2894 for (rdataset = ISC_LIST_HEAD(name->list);
2896 rdataset = ISC_LIST_NEXT(rdataset, link)) {
2897 result = dns_rdataset_first(rdataset);
2898 if (result != ISC_R_SUCCESS)
2902 dns_rdata_reset(&rdata);
2903 dns_rdataset_current(rdataset, &rdata);
2905 * If this is the first rr, make sure
2908 if ((!query->first_soa_rcvd) &&
2909 (rdata.type != dns_rdatatype_soa)) {
2910 puts("; Transfer failed. "
2911 "Didn't start with SOA answer.");
2914 if ((!query->second_rr_rcvd) &&
2915 (rdata.type != dns_rdatatype_soa)) {
2916 query->second_rr_rcvd = ISC_TRUE;
2917 query->second_rr_serial = 0;
2918 debug("got the second rr as nonsoa");
2923 * If the record is anything except an SOA
2924 * now, just continue on...
2926 if (rdata.type != dns_rdatatype_soa)
2928 /* Now we have an SOA. Work with it. */
2929 debug("got an SOA");
2930 result = dns_rdata_tostruct(&rdata, &soa, NULL);
2931 check_result(result, "dns_rdata_tostruct");
2932 serial = soa.serial;
2933 dns_rdata_freestruct(&soa);
2934 if (!query->first_soa_rcvd) {
2935 query->first_soa_rcvd = ISC_TRUE;
2936 query->first_rr_serial = serial;
2937 debug("this is the first %d",
2938 query->lookup->ixfr_serial);
2939 if (query->lookup->ixfr_serial >=
2944 if (query->lookup->rdtype ==
2945 dns_rdatatype_axfr) {
2946 debug("doing axfr, got second SOA");
2949 if (!query->second_rr_rcvd) {
2950 if (query->first_rr_serial == serial) {
2951 debug("doing ixfr, got "
2955 debug("this is the second %d",
2956 query->lookup->ixfr_serial);
2957 query->second_rr_rcvd = ISC_TRUE;
2958 query->second_rr_serial = serial;
2961 if (query->second_rr_serial == 0) {
2963 * If the second RR was a non-SOA
2964 * record, and we're getting any
2965 * other SOA, then this is an
2966 * AXFR, and we're done.
2968 debug("done, since axfr");
2972 * If we get to this point, we're doing an
2973 * IXFR and have to start really looking
2974 * at serial numbers.
2976 if (query->first_rr_serial == serial) {
2977 debug("got a match for ixfr");
2978 if (!query->first_repeat_rcvd) {
2979 query->first_repeat_rcvd =
2983 debug("done with ixfr");
2986 debug("meaningless soa %d", serial);
2988 result = dns_rdataset_next(rdataset);
2989 } while (result == ISC_R_SUCCESS);
2991 result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
2992 } while (result == ISC_R_SUCCESS);
2993 launch_next_query(query, ISC_FALSE);
2996 received(sevent->n, &sevent->address, query);
3001 * Event handler for recv complete. Perform whatever actions are necessary,
3002 * based on the specifics of the user's request.
3005 recv_done(isc_task_t *task, isc_event_t *event) {
3006 isc_socketevent_t *sevent = NULL;
3007 dig_query_t *query = NULL;
3008 isc_buffer_t *b = NULL;
3009 dns_message_t *msg = NULL;
3011 dig_message_t *chase_msg = NULL;
3012 dig_message_t *chase_msg2 = NULL;
3014 isc_result_t result;
3015 dig_lookup_t *n, *l;
3016 isc_boolean_t docancel = ISC_FALSE;
3017 isc_boolean_t match = ISC_TRUE;
3018 unsigned int parseflags;
3020 unsigned int msgflags;
3022 isc_result_t do_sigchase = ISC_FALSE;
3024 dns_message_t *msg_temp = NULL;
3026 isc_buffer_t *buf = NULL;
3032 debug("recv_done()");
3036 debug("recvcount=%d", recvcount);
3037 INSIST(recvcount >= 0);
3039 query = event->ev_arg;
3040 debug("lookup=%p, query=%p", query->lookup, query);
3044 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
3045 sevent = (isc_socketevent_t *)event;
3047 b = ISC_LIST_HEAD(sevent->bufferlist);
3048 INSIST(b == &query->recvbuf);
3049 ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link);
3051 if ((l->tcp_mode) && (l->timer != NULL))
3052 isc_timer_touch(l->timer);
3053 if ((!l->pending && !l->ns_search_only) || cancel_now) {
3054 debug("no longer pending. Got %s",
3055 isc_result_totext(sevent->result));
3056 query->waiting_connect = ISC_FALSE;
3058 isc_event_free(&event);
3060 check_next_lookup(l);
3065 if (sevent->result != ISC_R_SUCCESS) {
3066 if (sevent->result == ISC_R_CANCELED) {
3067 debug("in recv cancel handler");
3068 query->waiting_connect = ISC_FALSE;
3070 printf(";; communications error: %s\n",
3071 isc_result_totext(sevent->result));
3072 isc_socket_detach(&query->sock);
3074 debug("sockcount=%d", sockcount);
3075 INSIST(sockcount >= 0);
3077 isc_event_free(&event);
3079 check_next_lookup(l);
3085 !isc_sockaddr_compare(&sevent->address, &query->sockaddr,
3086 ISC_SOCKADDR_CMPADDR|
3087 ISC_SOCKADDR_CMPPORT|
3088 ISC_SOCKADDR_CMPSCOPE|
3089 ISC_SOCKADDR_CMPSCOPEZERO)) {
3090 char buf1[ISC_SOCKADDR_FORMATSIZE];
3091 char buf2[ISC_SOCKADDR_FORMATSIZE];
3094 if (isc_sockaddr_pf(&query->sockaddr) == AF_INET)
3095 isc_sockaddr_any(&any);
3097 isc_sockaddr_any6(&any);
3100 * We don't expect a match when the packet is
3101 * sent to 0.0.0.0, :: or to a multicast addresses.
3102 * XXXMPA broadcast needs to be handled here as well.
3104 if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) &&
3105 !isc_sockaddr_ismulticast(&query->sockaddr)) ||
3106 isc_sockaddr_getport(&query->sockaddr) !=
3107 isc_sockaddr_getport(&sevent->address)) {
3108 isc_sockaddr_format(&sevent->address, buf1,
3110 isc_sockaddr_format(&query->sockaddr, buf2,
3112 printf(";; reply from unexpected source: %s,"
3113 " expected %s\n", buf1, buf2);
3118 result = dns_message_peekheader(b, &id, &msgflags);
3119 if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
3122 isc_boolean_t fail = ISC_TRUE;
3123 if (result == ISC_R_SUCCESS) {
3124 if (!query->first_soa_rcvd ||
3126 printf(";; %s: ID mismatch: "
3127 "expected ID %u, got %u\n",
3128 query->first_soa_rcvd ?
3129 "WARNING" : "ERROR",
3130 l->sendmsg->id, id);
3131 if (query->first_soa_rcvd)
3133 query->warn_id = ISC_FALSE;
3135 printf(";; ERROR: short "
3136 "(< header size) message\n");
3138 isc_event_free(&event);
3140 check_next_lookup(l);
3145 } else if (result == ISC_R_SUCCESS)
3146 printf(";; Warning: ID mismatch: "
3147 "expected ID %u, got %u\n", l->sendmsg->id, id);
3149 printf(";; Warning: short "
3150 "(< header size) message received\n");
3153 if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0)
3154 printf(";; Warning: query response not set\n");
3159 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
3160 check_result(result, "dns_message_create");
3163 if (l->querysig == NULL) {
3164 debug("getting initial querysig");
3165 result = dns_message_getquerytsig(l->sendmsg, mctx,
3167 check_result(result, "dns_message_getquerytsig");
3169 result = dns_message_setquerytsig(msg, l->querysig);
3170 check_result(result, "dns_message_setquerytsig");
3171 result = dns_message_settsigkey(msg, key);
3172 check_result(result, "dns_message_settsigkey");
3173 msg->tsigctx = l->tsigctx;
3175 if (l->msgcounter != 0)
3176 msg->tcp_continuation = 1;
3180 debug("before parse starts");
3181 parseflags = DNS_MESSAGEPARSE_PRESERVEORDER;
3184 do_sigchase = ISC_FALSE;
3187 do_sigchase = ISC_TRUE;
3190 if (l->besteffort) {
3191 parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
3192 parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
3194 result = dns_message_parse(msg, b, parseflags);
3195 if (result == DNS_R_RECOVERABLE) {
3196 printf(";; Warning: Message parser reports malformed "
3197 "message packet.\n");
3198 result = ISC_R_SUCCESS;
3200 if (result != ISC_R_SUCCESS) {
3201 printf(";; Got bad packet: %s\n", isc_result_totext(result));
3203 query->waiting_connect = ISC_FALSE;
3204 dns_message_destroy(&msg);
3205 isc_event_free(&event);
3208 check_next_lookup(l);
3212 if (msg->counts[DNS_SECTION_QUESTION] != 0) {
3214 for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
3215 result == ISC_R_SUCCESS && match;
3216 result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) {
3217 dns_name_t *name = NULL;
3218 dns_rdataset_t *rdataset;
3220 dns_message_currentname(msg, DNS_SECTION_QUESTION,
3222 for (rdataset = ISC_LIST_HEAD(name->list);
3224 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3225 if (l->rdtype != rdataset->type ||
3226 l->rdclass != rdataset->rdclass ||
3227 !dns_name_equal(l->name, name)) {
3228 char namestr[DNS_NAME_FORMATSIZE];
3229 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3230 char classbuf[DNS_RDATACLASS_FORMATSIZE];
3231 dns_name_format(name, namestr,
3233 dns_rdatatype_format(rdataset->type,
3236 dns_rdataclass_format(rdataset->rdclass,
3239 printf(";; Question section mismatch: "
3241 namestr, typebuf, classbuf);
3247 dns_message_destroy(&msg);
3249 isc_event_free(&event);
3251 check_next_lookup(l);
3258 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 &&
3259 !l->ignore && !l->tcp_mode) {
3260 printf(";; Truncated, retrying in TCP mode.\n");
3261 n = requeue_lookup(l, ISC_TRUE);
3262 n->tcp_mode = ISC_TRUE;
3263 n->origin = query->lookup->origin;
3264 dns_message_destroy(&msg);
3265 isc_event_free(&event);
3268 check_next_lookup(l);
3272 if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) ||
3273 (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse))
3275 dig_query_t *next = ISC_LIST_NEXT(query, link);
3276 if (l->current_query == query)
3277 l->current_query = NULL;
3279 debug("sending query %p\n", next);
3281 send_tcp_connect(next);
3286 * If our query is at the head of the list and there
3287 * is no next, we're the only one left, so fall
3288 * through to print the message.
3290 if ((ISC_LIST_HEAD(l->q) != query) ||
3291 (ISC_LIST_NEXT(query, link) != NULL)) {
3292 if( l->comments == ISC_TRUE )
3293 printf(";; Got %s from %s, "
3294 "trying next server\n",
3295 msg->rcode == dns_rcode_servfail ?
3297 "recursion not available",
3300 check_next_lookup(l);
3301 dns_message_destroy(&msg);
3302 isc_event_free(&event);
3309 result = dns_tsig_verify(&query->recvbuf, msg, NULL, NULL);
3310 if (result != ISC_R_SUCCESS) {
3311 printf(";; Couldn't verify signature: %s\n",
3312 isc_result_totext(result));
3313 validated = ISC_FALSE;
3315 l->tsigctx = msg->tsigctx;
3316 msg->tsigctx = NULL;
3317 if (l->querysig != NULL) {
3318 debug("freeing querysig buffer %p", l->querysig);
3319 isc_buffer_free(&l->querysig);
3321 result = dns_message_getquerytsig(msg, mctx, &l->querysig);
3322 check_result(result,"dns_message_getquerytsig");
3325 extrabytes = isc_buffer_remaininglength(b);
3327 debug("after parse");
3328 if (l->doing_xfr && l->xfr_q == NULL) {
3331 * Once we are in the XFR message, increase
3332 * the timeout to much longer, so brief network
3333 * outages won't cause the XFR to abort
3335 if (timeout != INT_MAX && l->timer != NULL) {
3336 unsigned int local_timeout;
3340 local_timeout = TCP_TIMEOUT * 4;
3342 local_timeout = UDP_TIMEOUT * 4;
3344 if (timeout < (INT_MAX / 4))
3345 local_timeout = timeout * 4;
3347 local_timeout = INT_MAX;
3349 debug("have local timeout of %d", local_timeout);
3350 isc_interval_set(&l->interval, local_timeout, 0);
3351 result = isc_timer_reset(l->timer,
3356 check_result(result, "isc_timer_reset");
3360 if (!l->doing_xfr || l->xfr_q == query) {
3361 if (msg->rcode != dns_rcode_noerror &&
3362 (l->origin != NULL || l->need_search)) {
3363 if (!next_origin(msg, query) || showsearch) {
3364 printmessage(query, msg, ISC_TRUE);
3365 received(b->used, &sevent->address, query);
3367 } else if (!l->trace && !l->ns_search_only) {
3371 printmessage(query, msg, ISC_TRUE);
3372 } else if (l->trace) {
3374 int count = msg->counts[DNS_SECTION_ANSWER];
3376 debug("in TRACE code");
3377 if (!l->ns_search_only)
3378 printmessage(query, msg, ISC_TRUE);
3380 l->rdtype = l->qrdtype;
3381 if (l->trace_root || (l->ns_search_only && count > 0)) {
3383 l->rdtype = dns_rdatatype_soa;
3384 n = followup_lookup(msg, query,
3385 DNS_SECTION_ANSWER);
3386 l->trace_root = ISC_FALSE;
3387 } else if (count == 0)
3388 n = followup_lookup(msg, query,
3389 DNS_SECTION_AUTHORITY);
3391 docancel = ISC_TRUE;
3393 debug("in NSSEARCH code");
3395 if (l->trace_root) {
3397 * This is the initial NS query.
3401 l->rdtype = dns_rdatatype_soa;
3402 n = followup_lookup(msg, query,
3403 DNS_SECTION_ANSWER);
3405 docancel = ISC_TRUE;
3406 l->trace_root = ISC_FALSE;
3411 printmessage(query, msg, ISC_TRUE);
3415 chase_msg = isc_mem_allocate(mctx,
3416 sizeof(dig_message_t));
3417 if (chase_msg == NULL) {
3418 fatal("Memory allocation failure in %s:%d",
3419 __FILE__, __LINE__);
3421 ISC_LIST_INITANDAPPEND(chase_message_list, chase_msg,
3423 if (dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
3424 &msg_temp) != ISC_R_SUCCESS) {
3425 fatal("dns_message_create in %s:%d",
3426 __FILE__, __LINE__);
3429 isc_buffer_usedregion(b, &r);
3430 result = isc_buffer_allocate(mctx, &buf, r.length);
3432 check_result(result, "isc_buffer_allocate");
3433 result = isc_buffer_copyregion(buf, &r);
3434 check_result(result, "isc_buffer_copyregion");
3436 result = dns_message_parse(msg_temp, buf, 0);
3438 isc_buffer_free(&buf);
3439 chase_msg->msg = msg_temp;
3441 chase_msg2 = isc_mem_allocate(mctx,
3442 sizeof(dig_message_t));
3443 if (chase_msg2 == NULL) {
3444 fatal("Memory allocation failure in %s:%d",
3445 __FILE__, __LINE__);
3447 ISC_LIST_INITANDAPPEND(chase_message_list2, chase_msg2,
3449 chase_msg2->msg = msg;
3455 if (l->sigchase && ISC_LIST_EMPTY(lookup_list)) {
3461 debug("still pending.");
3463 if (query != l->xfr_q) {
3464 dns_message_destroy(&msg);
3465 isc_event_free(&event);
3466 query->waiting_connect = ISC_FALSE;
3471 docancel = check_for_more_data(query, msg, sevent);
3473 dns_message_destroy(&msg);
3476 check_next_lookup(l);
3480 if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
3485 received(b->used, &sevent->address, query);
3488 if (!query->lookup->ns_search_only)
3489 query->lookup->pending = ISC_FALSE;
3490 if (!query->lookup->ns_search_only ||
3491 query->lookup->trace_root || docancel) {
3495 dns_message_destroy(&msg);
3500 check_next_lookup(l);
3508 dns_message_destroy(&msg);
3510 isc_event_free(&event);
3515 isc_buffer_invalidate(&query->recvbuf);
3516 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
3517 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
3518 result = isc_socket_recvv(query->sock, &query->recvlist, 1,
3519 global_task, recv_done, query);
3520 check_result(result, "isc_socket_recvv");
3522 isc_event_free(&event);
3528 * Turn a name into an address, using system-supplied routines. This is
3529 * used in looking up server names, etc... and needs to use system-supplied
3530 * routines, since they may be using a non-DNS system for these lookups.
3533 get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
3535 isc_result_t result;
3538 result = bind9_getaddresses(host, port, sockaddr, 1, &count);
3540 if (result != ISC_R_SUCCESS)
3545 return (ISC_R_SUCCESS);
3549 getaddresses(dig_lookup_t *lookup, const char *host) {
3550 isc_result_t result;
3551 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
3552 isc_netaddr_t netaddr;
3555 char tmp[ISC_NETADDR_FORMATSIZE];
3557 result = bind9_getaddresses(host, 0, sockaddrs,
3558 DIG_MAX_ADDRESSES, &count);
3559 if (result != ISC_R_SUCCESS)
3560 fatal("couldn't get address for '%s': %s",
3561 host, isc_result_totext(result));
3563 for (i = 0; i < count; i++) {
3564 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
3565 isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
3566 srv = make_server(tmp, host);
3567 ISC_LIST_APPEND(lookup->my_server_list, srv, link);
3574 * Initiate either a TCP or UDP lookup
3577 do_lookup(dig_lookup_t *lookup) {
3579 REQUIRE(lookup != NULL);
3581 debug("do_lookup()");
3582 lookup->pending = ISC_TRUE;
3583 if (lookup->tcp_mode)
3584 send_tcp_connect(ISC_LIST_HEAD(lookup->q));
3586 send_udp(ISC_LIST_HEAD(lookup->q));
3590 * Start everything in action upon task startup.
3593 onrun_callback(isc_task_t *task, isc_event_t *event) {
3596 isc_event_free(&event);
3603 * Make everything on the lookup queue go away. Mainly used by the
3608 dig_lookup_t *l, *n;
3609 dig_query_t *q, *nq;
3611 debug("cancel_all()");
3618 cancel_now = ISC_TRUE;
3619 if (current_lookup != NULL) {
3620 if (current_lookup->timer != NULL)
3621 isc_timer_detach(¤t_lookup->timer);
3622 q = ISC_LIST_HEAD(current_lookup->q);
3624 debug("canceling query %p, belonging to %p",
3626 nq = ISC_LIST_NEXT(q, link);
3627 if (q->sock != NULL) {
3628 isc_socket_cancel(q->sock, NULL,
3629 ISC_SOCKCANCEL_ALL);
3636 l = ISC_LIST_HEAD(lookup_list);
3638 n = ISC_LIST_NEXT(l, link);
3639 ISC_LIST_DEQUEUE(lookup_list, l, link);
3640 try_clear_lookup(l);
3647 * Destroy all of the libs we are using, and get everything ready for a
3651 destroy_libs(void) {
3654 dig_message_t *chase_msg;
3657 isc_result_t result;
3660 debug("destroy_libs()");
3661 if (global_task != NULL) {
3662 debug("freeing task");
3663 isc_task_detach(&global_task);
3666 * The taskmgr_destroy() call blocks until all events are cleared
3669 if (taskmgr != NULL) {
3670 debug("freeing taskmgr");
3671 isc_taskmgr_destroy(&taskmgr);
3674 REQUIRE(sockcount == 0);
3675 REQUIRE(recvcount == 0);
3676 REQUIRE(sendcount == 0);
3678 INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
3679 INSIST(current_lookup == NULL);
3682 free_now = ISC_TRUE;
3684 lwres_conf_clear(lwctx);
3685 lwres_context_destroy(&lwctx);
3687 flush_server_list();
3692 result = dns_name_settotextfilter(NULL);
3693 check_result(result, "dns_name_settotextfilter");
3697 if (commctx != NULL) {
3698 debug("freeing commctx");
3699 isc_mempool_destroy(&commctx);
3701 if (socketmgr != NULL) {
3702 debug("freeing socketmgr");
3703 isc_socketmgr_destroy(&socketmgr);
3705 if (timermgr != NULL) {
3706 debug("freeing timermgr");
3707 isc_timermgr_destroy(&timermgr);
3710 debug("freeing key %p", key);
3711 dns_tsigkey_detach(&key);
3713 if (namebuf != NULL)
3714 isc_buffer_free(&namebuf);
3717 debug("destroy DST lib");
3719 is_dst_up = ISC_FALSE;
3722 debug("detach from entropy");
3723 isc_entropy_detach(&entp);
3727 DESTROYLOCK(&lookup_lock);
3730 debug("Destroy the messages kept for sigchase");
3731 /* Destroy the messages kept for sigchase */
3732 chase_msg = ISC_LIST_HEAD(chase_message_list);
3734 while (chase_msg != NULL) {
3735 INSIST(chase_msg->msg != NULL);
3736 dns_message_destroy(&(chase_msg->msg));
3738 chase_msg = ISC_LIST_NEXT(chase_msg, link);
3739 isc_mem_free(mctx, ptr);
3742 chase_msg = ISC_LIST_HEAD(chase_message_list2);
3744 while (chase_msg != NULL) {
3745 INSIST(chase_msg->msg != NULL);
3746 dns_message_destroy(&(chase_msg->msg));
3748 chase_msg = ISC_LIST_NEXT(chase_msg, link);
3749 isc_mem_free(mctx, ptr);
3751 if (dns_name_dynamic(&chase_name))
3752 free_name(&chase_name, mctx);
3754 if (dns_name_dynamic(&chase_current_name))
3755 free_name(&chase_current_name, mctx);
3756 if (dns_name_dynamic(&chase_authority_name))
3757 free_name(&chase_authority_name, mctx);
3760 if (dns_name_dynamic(&chase_signame))
3761 free_name(&chase_signame, mctx);
3765 debug("Removing log context");
3766 isc_log_destroy(&lctx);
3768 debug("Destroy memory");
3769 if (memdebugging != 0)
3770 isc_mem_stats(mctx, stderr);
3772 isc_mem_destroy(&mctx);
3777 initialize_idn(void) {
3779 isc_result_t result;
3781 #ifdef HAVE_SETLOCALE
3783 (void)setlocale(LC_ALL, "");
3785 /* Create configuration context. */
3786 r = idn_nameinit(1);
3787 if (r != idn_success)
3788 fatal("idn api initialization failed: %s",
3789 idn_result_tostring(r));
3791 /* Set domain name -> text post-conversion filter. */
3792 result = dns_name_settotextfilter(output_filter);
3793 check_result(result, "dns_name_settotextfilter");
3797 output_filter(isc_buffer_t *buffer, unsigned int used_org,
3798 isc_boolean_t absolute)
3800 char tmp1[MAXDLEN], tmp2[MAXDLEN];
3801 size_t fromlen, tolen;
3802 isc_boolean_t end_with_dot;
3805 * Copy contents of 'buffer' to 'tmp1', supply trailing dot
3806 * if 'absolute' is true, and terminate with NUL.
3808 fromlen = isc_buffer_usedlength(buffer) - used_org;
3809 if (fromlen >= MAXDLEN)
3810 return (ISC_R_SUCCESS);
3811 memcpy(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
3812 end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE;
3813 if (absolute && !end_with_dot) {
3815 if (fromlen >= MAXDLEN)
3816 return (ISC_R_SUCCESS);
3817 tmp1[fromlen - 1] = '.';
3819 tmp1[fromlen] = '\0';
3822 * Convert contents of 'tmp1' to local encoding.
3824 if (idn_decodename(IDN_DECODE_APP, tmp1, tmp2, MAXDLEN) != idn_success)
3825 return (ISC_R_SUCCESS);
3829 * Copy the converted contents in 'tmp1' back to 'buffer'.
3830 * If we have appended trailing dot, remove it.
3832 tolen = strlen(tmp1);
3833 if (absolute && !end_with_dot && tmp1[tolen - 1] == '.')
3836 if (isc_buffer_length(buffer) < used_org + tolen)
3837 return (ISC_R_NOSPACE);
3839 isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org);
3840 memcpy(isc_buffer_used(buffer), tmp1, tolen);
3841 isc_buffer_add(buffer, tolen);
3843 return (ISC_R_SUCCESS);
3847 append_textname(char *name, const char *origin, size_t namesize) {
3848 size_t namelen = strlen(name);
3849 size_t originlen = strlen(origin);
3851 /* Already absolute? */
3852 if (namelen > 0 && name[namelen - 1] == '.')
3855 /* Append dot and origin */
3857 if (namelen + 1 + originlen >= namesize)
3858 return idn_buffer_overflow;
3860 name[namelen++] = '.';
3861 (void)strcpy(name + namelen, origin);
3866 idn_check_result(idn_result_t r, const char *msg) {
3867 if (r != idn_success) {
3869 fatal("%s: %s", msg, idn_result_tostring(r));
3872 #endif /* WITH_IDN */
3876 print_type(dns_rdatatype_t type)
3878 isc_buffer_t * b = NULL;
3879 isc_result_t result;
3882 result = isc_buffer_allocate(mctx, &b, 4000);
3883 check_result(result, "isc_buffer_allocate");
3885 result = dns_rdatatype_totext(type, b);
3886 check_result(result, "print_type");
3888 isc_buffer_usedregion(b, &r);
3889 r.base[r.length] = '\0';
3891 printf("%s", r.base);
3893 isc_buffer_free(&b);
3897 dump_database_section(dns_message_t *msg, int section)
3899 dns_name_t *msg_name=NULL;
3901 dns_rdataset_t *rdataset;
3904 dns_message_currentname(msg, section, &msg_name);
3906 for (rdataset = ISC_LIST_HEAD(msg_name->list); rdataset != NULL;
3907 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3908 dns_name_print(msg_name, stdout);
3910 print_rdataset(msg_name, rdataset, mctx);
3914 } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
3918 dump_database(void) {
3919 dig_message_t * msg;
3921 for (msg = ISC_LIST_HEAD(chase_message_list); msg != NULL;
3922 msg = ISC_LIST_NEXT(msg, link)) {
3923 if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
3925 dump_database_section(msg->msg, DNS_SECTION_ANSWER);
3927 if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
3929 dump_database_section(msg->msg, DNS_SECTION_AUTHORITY);
3931 if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
3933 dump_database_section(msg->msg, DNS_SECTION_ADDITIONAL);
3939 search_type(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) {
3940 dns_rdataset_t *rdataset;
3941 dns_rdata_sig_t siginfo;
3942 dns_rdata_t sigrdata = DNS_RDATA_INIT;
3943 isc_result_t result;
3945 for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
3946 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3947 if (type == dns_rdatatype_any) {
3948 if (rdataset->type != dns_rdatatype_rrsig)
3950 } else if ((type == dns_rdatatype_rrsig) &&
3951 (rdataset->type == dns_rdatatype_rrsig)) {
3952 result = dns_rdataset_first(rdataset);
3953 check_result(result, "empty rdataset");
3954 dns_rdataset_current(rdataset, &sigrdata);
3955 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
3956 check_result(result, "sigrdata tostruct siginfo");
3958 if ((siginfo.covered == covers) ||
3959 (covers == dns_rdatatype_any)) {
3960 dns_rdata_reset(&sigrdata);
3961 dns_rdata_freestruct(&siginfo);
3964 dns_rdata_reset(&sigrdata);
3965 dns_rdata_freestruct(&siginfo);
3966 } else if (rdataset->type == type)
3973 chase_scanname_section(dns_message_t *msg, dns_name_t *name,
3974 dns_rdatatype_t type, dns_rdatatype_t covers,
3977 dns_rdataset_t *rdataset;
3978 dns_name_t *msg_name = NULL;
3981 dns_message_currentname(msg, section, &msg_name);
3982 if (dns_name_compare(msg_name, name) == 0) {
3983 rdataset = search_type(msg_name, type, covers);
3984 if (rdataset != NULL)
3988 } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
3995 chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers)
3997 dns_rdataset_t *rdataset = NULL;
3998 dig_message_t * msg;
4000 for (msg = ISC_LIST_HEAD(chase_message_list2); msg != NULL;
4001 msg = ISC_LIST_NEXT(msg, link)) {
4002 if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
4004 rdataset = chase_scanname_section(msg->msg, name,
4006 DNS_SECTION_ANSWER);
4007 if (rdataset != NULL)
4009 if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
4012 chase_scanname_section(msg->msg, name,
4014 DNS_SECTION_AUTHORITY);
4015 if (rdataset != NULL)
4017 if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
4020 chase_scanname_section(msg->msg, name, type,
4022 DNS_SECTION_ADDITIONAL);
4023 if (rdataset != NULL)
4031 sigchase_scanname(dns_rdatatype_t type, dns_rdatatype_t covers,
4032 isc_boolean_t * lookedup, dns_name_t *rdata_name)
4034 dig_lookup_t *lookup;
4035 isc_buffer_t *b = NULL;
4037 isc_result_t result;
4038 dns_rdataset_t * temp;
4039 dns_rdatatype_t querytype;
4041 temp = chase_scanname(rdata_name, type, covers);
4045 if (*lookedup == ISC_TRUE)
4048 lookup = clone_lookup(current_lookup, ISC_TRUE);
4049 lookup->trace_root = ISC_FALSE;
4050 lookup->new_search = ISC_TRUE;
4052 result = isc_buffer_allocate(mctx, &b, BUFSIZE);
4053 check_result(result, "isc_buffer_allocate");
4054 result = dns_name_totext(rdata_name, ISC_FALSE, b);
4055 check_result(result, "dns_name_totext");
4056 isc_buffer_usedregion(b, &r);
4057 r.base[r.length] = '\0';
4058 strcpy(lookup->textname, (char*)r.base);
4059 isc_buffer_free(&b);
4061 if (type == dns_rdatatype_rrsig)
4066 if (querytype == 0 || querytype == 255) {
4067 printf("Error in the queried type: %d\n", querytype);
4071 lookup->rdtype = querytype;
4072 lookup->rdtypeset = ISC_TRUE;
4073 lookup->qrdtype = querytype;
4074 *lookedup = ISC_TRUE;
4076 ISC_LIST_APPEND(lookup_list, lookup, link);
4077 printf("\n\nLaunch a query to find a RRset of type ");
4079 printf(" for zone: %s\n", lookup->textname);
4084 insert_trustedkey(dst_key_t **keyp)
4088 if (tk_list.nb_tk >= MAX_TRUSTED_KEY)
4091 tk_list.key[tk_list.nb_tk++] = *keyp;
4101 for (i= 0; i < MAX_TRUSTED_KEY; i++) {
4102 if (tk_list.key[i] != NULL) {
4103 dst_key_free(&tk_list.key[i]);
4104 tk_list.key[i] = NULL;
4113 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
4116 removetmpkey(isc_mem_t *mctx, const char *file)
4118 char *tempnamekey = NULL;
4120 isc_result_t result;
4122 tempnamekeylen = strlen(file)+10;
4124 tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
4125 if (tempnamekey == NULL)
4126 return (ISC_R_NOMEMORY);
4128 memset(tempnamekey, 0, tempnamekeylen);
4130 strcat(tempnamekey, file);
4131 strcat(tempnamekey,".key");
4132 isc_file_remove(tempnamekey);
4134 result = isc_file_remove(tempnamekey);
4135 isc_mem_free(mctx, tempnamekey);
4140 opentmpkey(isc_mem_t *mctx, const char *file, char **tempp, FILE **fp) {
4142 isc_result_t result;
4143 char *tempname = NULL;
4144 char *tempnamekey = NULL;
4152 tempnamelen = strlen(file) + 20;
4153 tempname = isc_mem_allocate(mctx, tempnamelen);
4154 if (tempname == NULL)
4155 return (ISC_R_NOMEMORY);
4156 memset(tempname, 0, tempnamelen);
4158 result = isc_file_mktemplate(file, tempname, tempnamelen);
4159 if (result != ISC_R_SUCCESS)
4165 if (cp == tempname) {
4166 isc_mem_free(mctx, tempname);
4167 return (ISC_R_FAILURE);
4171 while (cp >= tempname && *cp == 'X') {
4172 isc_random_get(&which);
4173 *cp = alphnum[which % (sizeof(alphnum) - 1)];
4177 tempnamekeylen = tempnamelen+5;
4178 tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
4179 if (tempnamekey == NULL)
4180 return (ISC_R_NOMEMORY);
4182 memset(tempnamekey, 0, tempnamekeylen);
4183 strncpy(tempnamekey, tempname, tempnamelen);
4184 strcat(tempnamekey ,".key");
4187 if (isc_file_exists(tempnamekey)) {
4188 isc_mem_free(mctx, tempnamekey);
4189 isc_mem_free(mctx, tempname);
4193 if ((f = fopen(tempnamekey, "w")) == NULL) {
4194 printf("get_trusted_key(): trusted key not found %s\n",
4196 return (ISC_R_FAILURE);
4200 isc_mem_free(mctx, tempnamekey);
4203 return (ISC_R_SUCCESS);
4206 isc_mem_free(mctx, tempname);
4213 get_trusted_key(isc_mem_t *mctx)
4215 isc_result_t result;
4216 const char *filename = NULL;
4217 char *filetemp = NULL;
4220 dst_key_t *key = NULL;
4222 result = isc_file_exists(trustedkey);
4223 if (result != ISC_TRUE) {
4224 result = isc_file_exists("/etc/trusted-key.key");
4225 if (result != ISC_TRUE) {
4226 result = isc_file_exists("./trusted-key.key");
4227 if (result != ISC_TRUE)
4228 return (ISC_R_FAILURE);
4230 filename = "./trusted-key.key";
4232 filename = "/etc/trusted-key.key";
4234 filename = trustedkey;
4236 if (filename == NULL) {
4237 printf("No trusted key\n");
4238 return (ISC_R_FAILURE);
4241 if ((fp = fopen(filename, "r")) == NULL) {
4242 printf("get_trusted_key(): trusted key not found %s\n",
4244 return (ISC_R_FAILURE);
4246 while (fgets(buf, sizeof(buf), fp) != NULL) {
4247 result = opentmpkey(mctx,"tmp_file", &filetemp, &fptemp);
4248 if (result != ISC_R_SUCCESS) {
4250 return (ISC_R_FAILURE);
4252 if (fputs(buf, fptemp) < 0) {
4255 return (ISC_R_FAILURE);
4258 result = dst_key_fromnamedfile(filetemp, NULL, DST_TYPE_PUBLIC,
4260 removetmpkey(mctx, filetemp);
4261 isc_mem_free(mctx, filetemp);
4262 if (result != ISC_R_SUCCESS) {
4264 return (ISC_R_FAILURE);
4267 dst_key_tofile(key, DST_TYPE_PUBLIC,"/tmp");
4269 insert_trustedkey(&key);
4273 return (ISC_R_SUCCESS);
4278 nameFromString(const char *str, dns_name_t *p_ret) {
4279 size_t len = strlen(str);
4280 isc_result_t result;
4281 isc_buffer_t buffer;
4282 dns_fixedname_t fixedname;
4284 REQUIRE(p_ret != NULL);
4285 REQUIRE(str != NULL);
4287 isc_buffer_init(&buffer, str, len);
4288 isc_buffer_add(&buffer, len);
4290 dns_fixedname_init(&fixedname);
4291 result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer,
4292 dns_rootname, DNS_NAME_DOWNCASE, NULL);
4293 check_result(result, "nameFromString");
4295 if (dns_name_dynamic(p_ret))
4296 free_name(p_ret, mctx);
4298 result = dns_name_dup(dns_fixedname_name(&fixedname), mctx, p_ret);
4299 check_result(result, "nameFromString");
4305 prepare_lookup(dns_name_t *name)
4307 isc_result_t result;
4308 dig_lookup_t *lookup = NULL;
4312 lookup = clone_lookup(current_lookup, ISC_TRUE);
4313 lookup->trace_root = ISC_FALSE;
4314 lookup->new_search = ISC_TRUE;
4315 lookup->trace_root_sigchase = ISC_FALSE;
4317 strncpy(lookup->textname, lookup->textnamesigchase, MXNAME);
4319 lookup->rdtype = lookup->rdtype_sigchase;
4320 lookup->rdtypeset = ISC_TRUE;
4321 lookup->qrdtype = lookup->qrdtype_sigchase;
4323 s = ISC_LIST_HEAD(lookup->my_server_list);
4325 debug("freeing server %p belonging to %p",
4328 s = ISC_LIST_NEXT(s, link);
4329 ISC_LIST_DEQUEUE(lookup->my_server_list,
4330 (dig_server_t *)ptr, link);
4331 isc_mem_free(mctx, ptr);
4335 for (result = dns_rdataset_first(chase_nsrdataset);
4336 result == ISC_R_SUCCESS;
4337 result = dns_rdataset_next(chase_nsrdataset)) {
4338 char namestr[DNS_NAME_FORMATSIZE];
4340 dns_rdata_t rdata = DNS_RDATA_INIT;
4341 dig_server_t * srv = NULL;
4342 #define __FOLLOW_GLUE__
4343 #ifdef __FOLLOW_GLUE__
4344 isc_buffer_t *b = NULL;
4345 isc_result_t result;
4347 dns_rdataset_t *rdataset = NULL;
4348 isc_boolean_t true = ISC_TRUE;
4351 memset(namestr, 0, DNS_NAME_FORMATSIZE);
4353 dns_rdataset_current(chase_nsrdataset, &rdata);
4355 result = dns_rdata_tostruct(&rdata, &ns, NULL);
4356 check_result(result, "dns_rdata_tostruct");
4358 #ifdef __FOLLOW_GLUE__
4360 result = advanced_rrsearch(&rdataset, &ns.name,
4362 dns_rdatatype_any, &true);
4363 if (result == ISC_R_SUCCESS) {
4364 for (result = dns_rdataset_first(rdataset);
4365 result == ISC_R_SUCCESS;
4366 result = dns_rdataset_next(rdataset)) {
4367 dns_rdata_t aaaa = DNS_RDATA_INIT;
4368 dns_rdataset_current(rdataset, &aaaa);
4370 result = isc_buffer_allocate(mctx, &b, 80);
4371 check_result(result, "isc_buffer_allocate");
4373 dns_rdata_totext(&aaaa, &ns.name, b);
4374 isc_buffer_usedregion(b, &r);
4375 r.base[r.length] = '\0';
4376 strncpy(namestr, (char*)r.base,
4377 DNS_NAME_FORMATSIZE);
4378 isc_buffer_free(&b);
4379 dns_rdata_reset(&aaaa);
4382 srv = make_server(namestr, namestr);
4384 ISC_LIST_APPEND(lookup->my_server_list,
4390 result = advanced_rrsearch(&rdataset, &ns.name, dns_rdatatype_a,
4391 dns_rdatatype_any, &true);
4392 if (result == ISC_R_SUCCESS) {
4393 for (result = dns_rdataset_first(rdataset);
4394 result == ISC_R_SUCCESS;
4395 result = dns_rdataset_next(rdataset)) {
4396 dns_rdata_t a = DNS_RDATA_INIT;
4397 dns_rdataset_current(rdataset, &a);
4399 result = isc_buffer_allocate(mctx, &b, 80);
4400 check_result(result, "isc_buffer_allocate");
4402 dns_rdata_totext(&a, &ns.name, b);
4403 isc_buffer_usedregion(b, &r);
4404 r.base[r.length] = '\0';
4405 strncpy(namestr, (char*)r.base,
4406 DNS_NAME_FORMATSIZE);
4407 isc_buffer_free(&b);
4408 dns_rdata_reset(&a);
4409 printf("ns name: %s\n", namestr);
4412 srv = make_server(namestr, namestr);
4414 ISC_LIST_APPEND(lookup->my_server_list,
4420 dns_name_format(&ns.name, namestr, sizeof(namestr));
4421 printf("ns name: ");
4422 dns_name_print(&ns.name, stdout);
4424 srv = make_server(namestr, namestr);
4426 ISC_LIST_APPEND(lookup->my_server_list, srv, link);
4429 dns_rdata_freestruct(&ns);
4430 dns_rdata_reset(&rdata);
4434 ISC_LIST_APPEND(lookup_list, lookup, link);
4435 printf("\nLaunch a query to find a RRset of type ");
4436 print_type(lookup->rdtype);
4437 printf(" for zone: %s", lookup->textname);
4438 printf(" with nameservers:");
4440 print_rdataset(name, chase_nsrdataset, mctx);
4441 return (ISC_R_SUCCESS);
4446 child_of_zone(dns_name_t * name, dns_name_t * zone_name,
4447 dns_name_t * child_name)
4449 dns_namereln_t name_reln;
4451 unsigned int nlabelsp;
4453 name_reln = dns_name_fullcompare(name, zone_name, &orderp, &nlabelsp);
4454 if (name_reln != dns_namereln_subdomain ||
4455 dns_name_countlabels(name) <= dns_name_countlabels(zone_name) + 1) {
4456 printf("\n;; ERROR : ");
4457 dns_name_print(name, stdout);
4458 printf(" is not a subdomain of: ");
4459 dns_name_print(zone_name, stdout);
4460 printf(" FAILED\n\n");
4461 return (ISC_R_FAILURE);
4464 dns_name_getlabelsequence(name,
4465 dns_name_countlabels(name) -
4466 dns_name_countlabels(zone_name) -1,
4467 dns_name_countlabels(zone_name) +1,
4469 return (ISC_R_SUCCESS);
4473 grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t *sigrdataset)
4475 isc_result_t result;
4476 dns_rdata_t sigrdata = DNS_RDATA_INIT;
4477 dns_rdata_sig_t siginfo;
4479 result = dns_rdataset_first(sigrdataset);
4480 check_result(result, "empty RRSIG dataset");
4481 dns_rdata_init(&sigrdata);
4484 dns_rdataset_current(sigrdataset, &sigrdata);
4486 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4487 check_result(result, "sigrdata tostruct siginfo");
4489 if (dns_name_compare(&siginfo.signer, zone_name) == 0) {
4490 dns_rdata_freestruct(&siginfo);
4491 dns_rdata_reset(&sigrdata);
4492 return (ISC_R_SUCCESS);
4495 dns_rdata_freestruct(&siginfo);
4496 dns_rdata_reset(&sigrdata);
4498 } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
4500 dns_rdata_reset(&sigrdata);
4502 return (ISC_R_FAILURE);
4507 initialization(dns_name_t *name)
4509 isc_result_t result;
4510 isc_boolean_t true = ISC_TRUE;
4512 chase_nsrdataset = NULL;
4513 result = advanced_rrsearch(&chase_nsrdataset, name, dns_rdatatype_ns,
4514 dns_rdatatype_any, &true);
4515 if (result != ISC_R_SUCCESS) {
4516 printf("\n;; NS RRset is missing to continue validation:"
4518 return (ISC_R_FAILURE);
4520 INSIST(chase_nsrdataset != NULL);
4521 prepare_lookup(name);
4523 dup_name(name, &chase_current_name, mctx);
4525 return (ISC_R_SUCCESS);
4530 print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset, isc_mem_t *mctx)
4532 isc_buffer_t *b = NULL;
4533 isc_result_t result;
4536 result = isc_buffer_allocate(mctx, &b, 9000);
4537 check_result(result, "isc_buffer_allocate");
4539 printrdataset(name, rdataset, b);
4541 isc_buffer_usedregion(b, &r);
4542 r.base[r.length] = '\0';
4545 printf("%s\n", r.base);
4547 isc_buffer_free(&b);
4552 dup_name(dns_name_t *source, dns_name_t *target, isc_mem_t *mctx) {
4553 isc_result_t result;
4555 if (dns_name_dynamic(target))
4556 free_name(target, mctx);
4557 result = dns_name_dup(source, mctx, target);
4558 check_result(result, "dns_name_dup");
4562 free_name(dns_name_t *name, isc_mem_t *mctx) {
4563 dns_name_free(name, mctx);
4564 dns_name_init(name, NULL);
4569 * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter
4570 * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key
4571 * and the RRset is valid
4572 * return ISC_R_NOTFOUND if not contains trusted key
4573 or if the RRset isn't valid
4574 * return ISC_R_FAILURE if problem
4578 contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset,
4579 dns_rdataset_t *sigrdataset,
4582 isc_result_t result;
4583 dns_rdata_t rdata = DNS_RDATA_INIT;
4584 dst_key_t *trustedKey = NULL;
4585 dst_key_t *dnsseckey = NULL;
4588 if (name == NULL || rdataset == NULL)
4589 return (ISC_R_FAILURE);
4591 result = dns_rdataset_first(rdataset);
4592 check_result(result, "empty rdataset");
4595 dns_rdataset_current(rdataset, &rdata);
4596 INSIST(rdata.type == dns_rdatatype_dnskey);
4598 result = dns_dnssec_keyfromrdata(name, &rdata,
4600 check_result(result, "dns_dnssec_keyfromrdata");
4603 for (i = 0; i < tk_list.nb_tk; i++) {
4604 if (dst_key_compare(tk_list.key[i], dnsseckey)
4606 dns_rdata_reset(&rdata);
4608 printf(";; Ok, find a Trusted Key in the "
4609 "DNSKEY RRset: %d\n",
4610 dst_key_id(dnsseckey));
4611 if (sigchase_verify_sig_key(name, rdataset,
4616 dst_key_free(&dnsseckey);
4618 return (ISC_R_SUCCESS);
4623 dns_rdata_reset(&rdata);
4624 if (dnsseckey != NULL)
4625 dst_key_free(&dnsseckey);
4626 } while (dns_rdataset_next(rdataset) == ISC_R_SUCCESS);
4628 if (trustedKey != NULL)
4629 dst_key_free(&trustedKey);
4632 return (ISC_R_NOTFOUND);
4636 sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset,
4637 dns_rdataset_t *keyrdataset,
4638 dns_rdataset_t *sigrdataset,
4641 isc_result_t result;
4642 dns_rdata_t keyrdata = DNS_RDATA_INIT;
4643 dst_key_t *dnsseckey = NULL;
4645 result = dns_rdataset_first(keyrdataset);
4646 check_result(result, "empty DNSKEY dataset");
4647 dns_rdata_init(&keyrdata);
4650 dns_rdataset_current(keyrdataset, &keyrdata);
4651 INSIST(keyrdata.type == dns_rdatatype_dnskey);
4653 result = dns_dnssec_keyfromrdata(name, &keyrdata,
4655 check_result(result, "dns_dnssec_keyfromrdata");
4657 result = sigchase_verify_sig_key(name, rdataset, dnsseckey,
4659 if (result == ISC_R_SUCCESS) {
4660 dns_rdata_reset(&keyrdata);
4661 dst_key_free(&dnsseckey);
4662 return (ISC_R_SUCCESS);
4664 dst_key_free(&dnsseckey);
4665 dns_rdata_reset(&keyrdata);
4666 } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
4668 dns_rdata_reset(&keyrdata);
4670 return (ISC_R_NOTFOUND);
4674 sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset,
4675 dst_key_t *dnsseckey, dns_rdataset_t *sigrdataset,
4678 isc_result_t result;
4679 dns_rdata_t sigrdata = DNS_RDATA_INIT;
4680 dns_rdata_sig_t siginfo;
4682 result = dns_rdataset_first(sigrdataset);
4683 check_result(result, "empty RRSIG dataset");
4684 dns_rdata_init(&sigrdata);
4687 dns_rdataset_current(sigrdataset, &sigrdata);
4689 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4690 check_result(result, "sigrdata tostruct siginfo");
4693 * Test if the id of the DNSKEY is
4694 * the id of the DNSKEY signer's
4696 if (siginfo.keyid == dst_key_id(dnsseckey)) {
4698 result = dns_rdataset_first(rdataset);
4699 check_result(result, "empty DS dataset");
4701 result = dns_dnssec_verify(name, rdataset, dnsseckey,
4702 ISC_FALSE, mctx, &sigrdata);
4704 printf(";; VERIFYING ");
4705 print_type(rdataset->type);
4706 printf(" RRset for ");
4707 dns_name_print(name, stdout);
4708 printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey),
4709 isc_result_totext(result));
4711 if (result == ISC_R_SUCCESS) {
4712 dns_rdata_reset(&sigrdata);
4716 dns_rdata_freestruct(&siginfo);
4717 dns_rdata_reset(&sigrdata);
4719 } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
4721 dns_rdata_reset(&sigrdata);
4723 return (ISC_R_NOTFOUND);
4728 sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset,
4729 dns_rdataset_t *dsrdataset, isc_mem_t *mctx)
4731 isc_result_t result;
4732 dns_rdata_t keyrdata = DNS_RDATA_INIT;
4733 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
4734 dns_rdata_t dsrdata = DNS_RDATA_INIT;
4735 dns_rdata_ds_t dsinfo;
4736 dst_key_t *dnsseckey = NULL;
4737 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
4739 result = dns_rdataset_first(dsrdataset);
4740 check_result(result, "empty DSset dataset");
4742 dns_rdataset_current(dsrdataset, &dsrdata);
4744 result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL);
4745 check_result(result, "dns_rdata_tostruct for DS");
4747 result = dns_rdataset_first(keyrdataset);
4748 check_result(result, "empty KEY dataset");
4751 dns_rdataset_current(keyrdataset, &keyrdata);
4752 INSIST(keyrdata.type == dns_rdatatype_dnskey);
4754 result = dns_dnssec_keyfromrdata(name, &keyrdata,
4756 check_result(result, "dns_dnssec_keyfromrdata");
4759 * Test if the id of the DNSKEY is the
4760 * id of DNSKEY referenced by the DS
4762 if (dsinfo.key_tag == dst_key_id(dnsseckey)) {
4764 result = dns_ds_buildrdata(name, &keyrdata,
4766 dsbuf, &newdsrdata);
4767 dns_rdata_freestruct(&dsinfo);
4769 if (result != ISC_R_SUCCESS) {
4770 dns_rdata_reset(&keyrdata);
4771 dns_rdata_reset(&newdsrdata);
4772 dns_rdata_reset(&dsrdata);
4773 dst_key_free(&dnsseckey);
4774 dns_rdata_freestruct(&dsinfo);
4775 printf("Oops: impossible to build"
4781 if (dns_rdata_compare(&dsrdata,
4782 &newdsrdata) == 0) {
4783 printf(";; OK a DS valids a DNSKEY"
4785 printf(";; Now verify that this"
4786 " DNSKEY validates the "
4789 result = sigchase_verify_sig_key(name,
4792 chase_sigkeyrdataset,
4794 if (result == ISC_R_SUCCESS) {
4795 dns_rdata_reset(&keyrdata);
4796 dns_rdata_reset(&newdsrdata);
4797 dns_rdata_reset(&dsrdata);
4798 dst_key_free(&dnsseckey);
4803 printf(";; This DS is NOT the DS for"
4804 " the chasing KEY: FAILED\n");
4807 dns_rdata_reset(&newdsrdata);
4809 dst_key_free(&dnsseckey);
4810 dns_rdata_reset(&keyrdata);
4812 } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
4813 dns_rdata_reset(&dsrdata);
4815 } while (dns_rdataset_next(chase_dsrdataset) == ISC_R_SUCCESS);
4817 dns_rdata_reset(&keyrdata);
4818 dns_rdata_reset(&newdsrdata);
4819 dns_rdata_reset(&dsrdata);
4821 return (ISC_R_NOTFOUND);
4826 * take a pointer on a rdataset in parameter and try to resolv it.
4827 * the searched rrset is a rrset on 'name' with type 'type'
4828 * (and if the type is a rrsig the signature cover 'covers').
4829 * the lookedup is to known if you have already done the query on the net.
4830 * ISC_R_SUCCESS: if we found the rrset
4831 * ISC_R_NOTFOUND: we do not found the rrset in cache
4832 * and we do a query on the net
4833 * ISC_R_FAILURE: rrset not found
4836 advanced_rrsearch(dns_rdataset_t **rdataset, dns_name_t *name,
4837 dns_rdatatype_t type, dns_rdatatype_t covers,
4838 isc_boolean_t *lookedup)
4840 isc_boolean_t tmplookedup;
4842 INSIST(rdataset != NULL);
4844 if (*rdataset != NULL)
4845 return (ISC_R_SUCCESS);
4847 tmplookedup = *lookedup;
4848 if ((*rdataset = sigchase_scanname(type, covers,
4849 lookedup, name)) == NULL) {
4851 return (ISC_R_FAILURE);
4852 return (ISC_R_NOTFOUND);
4854 *lookedup = ISC_FALSE;
4855 return (ISC_R_SUCCESS);
4862 sigchase_td(dns_message_t *msg)
4864 isc_result_t result;
4865 dns_name_t *name = NULL;
4866 isc_boolean_t have_answer = ISC_FALSE;
4867 isc_boolean_t true = ISC_TRUE;
4869 if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
4871 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
4872 if (current_lookup->trace_root_sigchase) {
4873 initialization(name);
4878 if (!current_lookup->trace_root_sigchase) {
4879 result = dns_message_firstname(msg,
4880 DNS_SECTION_AUTHORITY);
4881 if (result == ISC_R_SUCCESS)
4882 dns_message_currentname(msg,
4883 DNS_SECTION_AUTHORITY,
4886 = chase_scanname_section(msg, name,
4889 DNS_SECTION_AUTHORITY);
4890 dup_name(name, &chase_authority_name, mctx);
4891 if (chase_nsrdataset != NULL) {
4892 have_delegation_ns = ISC_TRUE;
4893 printf("no response but there is a delegation"
4894 " in authority section:");
4895 dns_name_print(name, stdout);
4898 printf("no response and no delegation in "
4899 "authority section but a reference"
4901 dns_name_print(name, stdout);
4903 error_message = msg;
4906 printf(";; NO ANSWERS: %s\n",
4907 isc_result_totext(result));
4908 free_name(&chase_name, mctx);
4917 = chase_scanname_section(msg, &chase_name,
4921 DNS_SECTION_ANSWER);
4922 if (chase_rdataset != NULL)
4923 have_response = ISC_TRUE;
4926 result = advanced_rrsearch(&chase_keyrdataset,
4927 &chase_current_name,
4928 dns_rdatatype_dnskey,
4930 &chase_keylookedup);
4931 if (result == ISC_R_FAILURE) {
4932 printf("\n;; DNSKEY is missing to continue validation:"
4936 if (result == ISC_R_NOTFOUND)
4938 INSIST(chase_keyrdataset != NULL);
4939 printf("\n;; DNSKEYset:\n");
4940 print_rdataset(&chase_current_name , chase_keyrdataset, mctx);
4943 result = advanced_rrsearch(&chase_sigkeyrdataset,
4944 &chase_current_name,
4945 dns_rdatatype_rrsig,
4946 dns_rdatatype_dnskey,
4947 &chase_sigkeylookedup);
4948 if (result == ISC_R_FAILURE) {
4949 printf("\n;; RRSIG of DNSKEY is missing to continue validation:"
4953 if (result == ISC_R_NOTFOUND)
4955 INSIST(chase_sigkeyrdataset != NULL);
4956 printf("\n;; RRSIG of the DNSKEYset:\n");
4957 print_rdataset(&chase_current_name , chase_sigkeyrdataset, mctx);
4960 if (!chase_dslookedup && !chase_nslookedup) {
4961 if (!delegation_follow) {
4962 result = contains_trusted_key(&chase_current_name,
4964 chase_sigkeyrdataset,
4967 INSIST(chase_dsrdataset != NULL);
4968 INSIST(chase_sigdsrdataset != NULL);
4969 result = sigchase_verify_ds(&chase_current_name,
4975 if (result != ISC_R_SUCCESS) {
4976 printf("\n;; chain of trust can't be validated:"
4980 chase_dsrdataset = NULL;
4981 chase_sigdsrdataset = NULL;
4985 if (have_response || (!have_delegation_ns && !have_response)) {
4986 /* test if it's a grand father case */
4988 if (have_response) {
4989 result = advanced_rrsearch(&chase_sigrdataset,
4991 dns_rdatatype_rrsig,
4995 if (result == ISC_R_FAILURE) {
4996 printf("\n;; RRset is missing to continue"
4997 " validation SHOULD NOT APPEND:"
5003 result = advanced_rrsearch(&chase_sigrdataset,
5004 &chase_authority_name,
5005 dns_rdatatype_rrsig,
5008 if (result == ISC_R_FAILURE) {
5009 printf("\n;; RRSIG is missing to continue"
5010 " validation SHOULD NOT APPEND:"
5015 result = grandfather_pb_test(&chase_current_name,
5017 if (result != ISC_R_SUCCESS) {
5018 dns_name_t tmp_name;
5020 printf("\n;; We are in a Grand Father Problem:"
5021 " See 2.2.1 in RFC 3568\n");
5022 chase_rdataset = NULL;
5023 chase_sigrdataset = NULL;
5024 have_response = ISC_FALSE;
5025 have_delegation_ns = ISC_FALSE;
5027 dns_name_init(&tmp_name, NULL);
5028 result = child_of_zone(&chase_name, &chase_current_name,
5030 if (dns_name_dynamic(&chase_authority_name))
5031 free_name(&chase_authority_name, mctx);
5032 dup_name(&tmp_name, &chase_authority_name, mctx);
5033 printf(";; and we try to continue chain of trust"
5034 " validation of the zone: ");
5035 dns_name_print(&chase_authority_name, stdout);
5037 have_delegation_ns = ISC_TRUE;
5042 chase_sigrdataset = NULL;
5046 if (have_delegation_ns) {
5047 chase_nsrdataset = NULL;
5048 result = advanced_rrsearch(&chase_nsrdataset,
5049 &chase_authority_name,
5053 if (result == ISC_R_FAILURE) {
5054 printf("\n;;NSset is missing to continue validation:"
5058 if (result == ISC_R_NOTFOUND) {
5061 INSIST(chase_nsrdataset != NULL);
5063 result = advanced_rrsearch(&chase_dsrdataset,
5064 &chase_authority_name,
5068 if (result == ISC_R_FAILURE) {
5069 printf("\n;; DSset is missing to continue validation:"
5073 if (result == ISC_R_NOTFOUND)
5075 INSIST(chase_dsrdataset != NULL);
5076 printf("\n;; DSset:\n");
5077 print_rdataset(&chase_authority_name , chase_dsrdataset, mctx);
5079 result = advanced_rrsearch(&chase_sigdsrdataset,
5080 &chase_authority_name,
5081 dns_rdatatype_rrsig,
5084 if (result != ISC_R_SUCCESS) {
5085 printf("\n;; DSset is missing to continue validation:"
5089 printf("\n;; RRSIGset of DSset\n");
5090 print_rdataset(&chase_authority_name,
5091 chase_sigdsrdataset, mctx);
5092 INSIST(chase_sigdsrdataset != NULL);
5094 result = sigchase_verify_sig(&chase_authority_name,
5097 chase_sigdsrdataset, mctx);
5098 if (result != ISC_R_SUCCESS) {
5099 printf("\n;; Impossible to verify the DSset:"
5103 chase_keyrdataset = NULL;
5104 chase_sigkeyrdataset = NULL;
5107 prepare_lookup(&chase_authority_name);
5109 have_response = ISC_FALSE;
5110 have_delegation_ns = ISC_FALSE;
5111 delegation_follow = ISC_TRUE;
5112 error_message = NULL;
5113 dup_name(&chase_authority_name, &chase_current_name, mctx);
5114 free_name(&chase_authority_name, mctx);
5119 if (error_message != NULL) {
5120 dns_rdataset_t *rdataset;
5121 dns_rdataset_t *sigrdataset;
5122 dns_name_t rdata_name;
5123 isc_result_t ret = ISC_R_FAILURE;
5125 dns_name_init(&rdata_name, NULL);
5126 result = prove_nx(error_message, &chase_name,
5127 current_lookup->rdclass_sigchase,
5128 current_lookup->rdtype_sigchase, &rdata_name,
5129 &rdataset, &sigrdataset);
5130 if (rdataset == NULL || sigrdataset == NULL ||
5131 dns_name_countlabels(&rdata_name) == 0) {
5132 printf("\n;; Impossible to verify the non-existence,"
5133 " the NSEC RRset can't be validated:"
5137 ret = sigchase_verify_sig(&rdata_name, rdataset,
5140 if (ret != ISC_R_SUCCESS) {
5141 free_name(&rdata_name, mctx);
5142 printf("\n;; Impossible to verify the NSEC RR to prove"
5143 " the non-existence : FAILED\n\n");
5146 free_name(&rdata_name, mctx);
5147 if (result != ISC_R_SUCCESS) {
5148 printf("\n;; Impossible to verify the non-existence:"
5152 printf("\n;; OK the query doesn't have response but"
5153 " we have validate this fact : SUCCESS\n\n");
5159 printf(";; cleanandgo \n");
5160 if (dns_name_dynamic(&chase_current_name))
5161 free_name(&chase_current_name, mctx);
5162 if (dns_name_dynamic(&chase_authority_name))
5163 free_name(&chase_authority_name, mctx);
5168 result = advanced_rrsearch(&chase_rdataset, &chase_name,
5169 current_lookup->rdtype_sigchase,
5172 if (result == ISC_R_FAILURE) {
5173 printf("\n;; RRsig of RRset is missing to continue validation"
5174 " SHOULD NOT APPEND: FAILED\n\n");
5177 result = sigchase_verify_sig(&chase_name, chase_rdataset,
5179 chase_sigrdataset, mctx);
5180 if (result != ISC_R_SUCCESS) {
5181 printf("\n;; Impossible to verify the RRset : FAILED\n\n");
5184 print_rdataset(&chase_name , chase_rdataset, mctx);
5185 printf("DNSKEYset:\n");
5186 print_rdataset(&chase_name , chase_keyrdataset, mctx);
5187 printf("RRSIG of RRset:\n");
5188 print_rdataset(&chase_name , chase_sigrdataset, mctx);
5193 printf("\n;; The Answer:\n");
5194 print_rdataset(&chase_name , chase_rdataset, mctx);
5196 printf("\n;; FINISH : we have validate the DNSSEC chain"
5197 " of trust: SUCCESS\n\n");
5208 getneededrr(dns_message_t *msg)
5210 isc_result_t result;
5211 dns_name_t *name = NULL;
5212 dns_rdata_t sigrdata = DNS_RDATA_INIT;
5213 dns_rdata_sig_t siginfo;
5214 isc_boolean_t true = ISC_TRUE;
5216 if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
5218 printf(";; NO ANSWERS: %s\n", isc_result_totext(result));
5220 if (chase_name.ndata == NULL)
5221 return (ISC_R_ADDRNOTAVAIL);
5223 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
5226 /* What do we chase? */
5227 if (chase_rdataset == NULL) {
5228 result = advanced_rrsearch(&chase_rdataset, name,
5230 dns_rdatatype_any, &true);
5231 if (result != ISC_R_SUCCESS) {
5232 printf("\n;; No Answers: Validation FAILED\n\n");
5233 return (ISC_R_NOTFOUND);
5235 dup_name(name, &chase_name, mctx);
5236 printf(";; RRset to chase:\n");
5237 print_rdataset(&chase_name, chase_rdataset, mctx);
5239 INSIST(chase_rdataset != NULL);
5242 if (chase_sigrdataset == NULL) {
5243 result = advanced_rrsearch(&chase_sigrdataset, name,
5244 dns_rdatatype_rrsig,
5245 chase_rdataset->type,
5246 &chase_siglookedup);
5247 if (result == ISC_R_FAILURE) {
5248 printf("\n;; RRSIG is missing for continue validation:"
5250 if (dns_name_dynamic(&chase_name))
5251 free_name(&chase_name, mctx);
5252 return (ISC_R_NOTFOUND);
5254 if (result == ISC_R_NOTFOUND) {
5255 return (ISC_R_NOTFOUND);
5257 printf("\n;; RRSIG of the RRset to chase:\n");
5258 print_rdataset(&chase_name, chase_sigrdataset, mctx);
5260 INSIST(chase_sigrdataset != NULL);
5263 /* first find the DNSKEY name */
5264 result = dns_rdataset_first(chase_sigrdataset);
5265 check_result(result, "empty RRSIG dataset");
5266 dns_rdataset_current(chase_sigrdataset, &sigrdata);
5267 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
5268 check_result(result, "sigrdata tostruct siginfo");
5269 dup_name(&siginfo.signer, &chase_signame, mctx);
5270 dns_rdata_freestruct(&siginfo);
5271 dns_rdata_reset(&sigrdata);
5273 /* Do we have a key? */
5274 if (chase_keyrdataset == NULL) {
5275 result = advanced_rrsearch(&chase_keyrdataset,
5277 dns_rdatatype_dnskey,
5279 &chase_keylookedup);
5280 if (result == ISC_R_FAILURE) {
5281 printf("\n;; DNSKEY is missing to continue validation:"
5283 free_name(&chase_signame, mctx);
5284 if (dns_name_dynamic(&chase_name))
5285 free_name(&chase_name, mctx);
5286 return (ISC_R_NOTFOUND);
5288 if (result == ISC_R_NOTFOUND) {
5289 free_name(&chase_signame, mctx);
5290 return (ISC_R_NOTFOUND);
5292 printf("\n;; DNSKEYset that signs the RRset to chase:\n");
5293 print_rdataset(&chase_signame, chase_keyrdataset, mctx);
5295 INSIST(chase_keyrdataset != NULL);
5297 if (chase_sigkeyrdataset == NULL) {
5298 result = advanced_rrsearch(&chase_sigkeyrdataset,
5300 dns_rdatatype_rrsig,
5301 dns_rdatatype_dnskey,
5302 &chase_sigkeylookedup);
5303 if (result == ISC_R_FAILURE) {
5304 printf("\n;; RRSIG for DNSKEY is missing to continue"
5305 " validation : FAILED\n\n");
5306 free_name(&chase_signame, mctx);
5307 if (dns_name_dynamic(&chase_name))
5308 free_name(&chase_name, mctx);
5309 return (ISC_R_NOTFOUND);
5311 if (result == ISC_R_NOTFOUND) {
5312 free_name(&chase_signame, mctx);
5313 return (ISC_R_NOTFOUND);
5315 printf("\n;; RRSIG of the DNSKEYset that signs the "
5316 "RRset to chase:\n");
5317 print_rdataset(&chase_signame, chase_sigkeyrdataset, mctx);
5319 INSIST(chase_sigkeyrdataset != NULL);
5322 if (chase_dsrdataset == NULL) {
5323 result = advanced_rrsearch(&chase_dsrdataset, &chase_signame,
5327 if (result == ISC_R_FAILURE) {
5328 printf("\n;; WARNING There is no DS for the zone: ");
5329 dns_name_print(&chase_signame, stdout);
5332 if (result == ISC_R_NOTFOUND) {
5333 free_name(&chase_signame, mctx);
5334 return (ISC_R_NOTFOUND);
5336 if (chase_dsrdataset != NULL) {
5337 printf("\n;; DSset of the DNSKEYset\n");
5338 print_rdataset(&chase_signame, chase_dsrdataset, mctx);
5342 if (chase_dsrdataset != NULL) {
5344 * if there is no RRSIG of DS,
5345 * we don't want to search on the network
5347 result = advanced_rrsearch(&chase_sigdsrdataset,
5349 dns_rdatatype_rrsig,
5350 dns_rdatatype_ds, &true);
5351 if (result == ISC_R_FAILURE) {
5352 printf(";; WARNING : NO RRSIG DS : RRSIG DS"
5353 " should come with DS\n");
5355 * We continue even the DS couldn't be validated,
5356 * because the DNSKEY could be a Trusted Key.
5358 chase_dsrdataset = NULL;
5360 printf("\n;; RRSIG of the DSset of the DNSKEYset\n");
5361 print_rdataset(&chase_signame, chase_sigdsrdataset,
5371 sigchase_bu(dns_message_t *msg)
5373 isc_result_t result;
5376 if (tk_list.nb_tk == 0) {
5377 result = get_trusted_key(mctx);
5378 if (result != ISC_R_SUCCESS) {
5379 printf("No trusted keys present\n");
5385 ret = getneededrr(msg);
5386 if (ret == ISC_R_NOTFOUND)
5389 if (ret == ISC_R_ADDRNOTAVAIL) {
5390 /* We have no response */
5391 dns_rdataset_t *rdataset;
5392 dns_rdataset_t *sigrdataset;
5393 dns_name_t rdata_name;
5394 dns_name_t query_name;
5397 dns_name_init(&query_name, NULL);
5398 dns_name_init(&rdata_name, NULL);
5399 nameFromString(current_lookup->textname, &query_name);
5401 result = prove_nx(msg, &query_name, current_lookup->rdclass,
5402 current_lookup->rdtype, &rdata_name,
5403 &rdataset, &sigrdataset);
5404 free_name(&query_name, mctx);
5405 if (rdataset == NULL || sigrdataset == NULL ||
5406 dns_name_countlabels(&rdata_name) == 0) {
5407 printf("\n;; Impossible to verify the Non-existence,"
5408 " the NSEC RRset can't be validated: "
5414 if (result != ISC_R_SUCCESS) {
5415 printf("\n No Answers and impossible to prove the"
5416 " unsecurity : Validation FAILED\n\n");
5420 printf(";; An NSEC prove the non-existence of a answers,"
5421 " Now we want validate this NSEC\n");
5423 dup_name(&rdata_name, &chase_name, mctx);
5424 free_name(&rdata_name, mctx);
5425 chase_rdataset = rdataset;
5426 chase_sigrdataset = sigrdataset;
5427 chase_keyrdataset = NULL;
5428 chase_sigkeyrdataset = NULL;
5429 chase_dsrdataset = NULL;
5430 chase_sigdsrdataset = NULL;
5431 chase_siglookedup = ISC_FALSE;
5432 chase_keylookedup = ISC_FALSE;
5433 chase_dslookedup = ISC_FALSE;
5434 chase_sigdslookedup = ISC_FALSE;
5441 printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n");
5443 result = sigchase_verify_sig(&chase_name, chase_rdataset,
5445 chase_sigrdataset, mctx);
5446 if (result != ISC_R_SUCCESS) {
5447 free_name(&chase_name, mctx);
5448 free_name(&chase_signame, mctx);
5449 printf(";; No DNSKEY is valid to check the RRSIG"
5450 " of the RRset: FAILED\n");
5454 printf(";; OK We found DNSKEY (or more) to validate the RRset\n");
5456 result = contains_trusted_key(&chase_signame, chase_keyrdataset,
5457 chase_sigkeyrdataset, mctx);
5458 if (result == ISC_R_SUCCESS) {
5459 free_name(&chase_name, mctx);
5460 free_name(&chase_signame, mctx);
5461 printf("\n;; Ok this DNSKEY is a Trusted Key,"
5462 " DNSSEC validation is ok: SUCCESS\n\n");
5467 printf(";; Now, we are going to validate this DNSKEY by the DS\n");
5469 if (chase_dsrdataset == NULL) {
5470 free_name(&chase_name, mctx);
5471 free_name(&chase_signame, mctx);
5472 printf(";; the DNSKEY isn't trusted-key and there isn't"
5473 " DS to validate the DNSKEY: FAILED\n");
5478 result = sigchase_verify_ds(&chase_signame, chase_keyrdataset,
5479 chase_dsrdataset, mctx);
5480 if (result != ISC_R_SUCCESS) {
5481 free_name(&chase_signame, mctx);
5482 free_name(&chase_name, mctx);
5483 printf(";; ERROR no DS validates a DNSKEY in the"
5484 " DNSKEY RRset: FAILED\n");
5488 printf(";; OK this DNSKEY (validated by the DS) validates"
5489 " the RRset of the DNSKEYs, thus the DNSKEY validates"
5491 INSIST(chase_sigdsrdataset != NULL);
5493 dup_name(&chase_signame, &chase_name, mctx);
5494 free_name(&chase_signame, mctx);
5495 chase_rdataset = chase_dsrdataset;
5496 chase_sigrdataset = chase_sigdsrdataset;
5497 chase_keyrdataset = NULL;
5498 chase_sigkeyrdataset = NULL;
5499 chase_dsrdataset = NULL;
5500 chase_sigdsrdataset = NULL;
5501 chase_siglookedup = chase_keylookedup = ISC_FALSE;
5502 chase_dslookedup = chase_sigdslookedup = ISC_FALSE;
5504 printf(";; Now, we want to validate the DS : recursive call\n");
5511 sigchase(dns_message_t *msg) {
5513 if (current_lookup->do_topdown) {
5526 * return 1 if name1 < name2
5527 * 0 if name1 == name2
5528 * -1 if name1 > name2
5532 inf_name(dns_name_t *name1, dns_name_t *name2)
5536 unsigned int nblabel1;
5537 unsigned int nblabel2;
5542 nblabel1 = dns_name_countlabels(name1);
5543 nblabel2 = dns_name_countlabels(name2);
5545 if (nblabel1 >= nblabel2)
5546 min_lum_label = nblabel2;
5548 min_lum_label = nblabel1;
5551 for (i=1 ; i < min_lum_label; i++) {
5552 dns_name_getlabel(name1, nblabel1 -1 - i, &label1);
5553 dns_name_getlabel(name2, nblabel2 -1 - i, &label2);
5554 if ((ret = isc_region_compare(&label1, &label2)) != 0) {
5561 if (nblabel1 == nblabel2)
5564 if (nblabel1 < nblabel2)
5576 prove_nx_domain(dns_message_t *msg,
5578 dns_name_t *rdata_name,
5579 dns_rdataset_t **rdataset,
5580 dns_rdataset_t **sigrdataset)
5582 isc_result_t ret = ISC_R_FAILURE;
5583 isc_result_t result = ISC_R_NOTFOUND;
5584 dns_rdataset_t *nsecset = NULL;
5585 dns_rdataset_t *signsecset = NULL ;
5586 dns_rdata_t nsec = DNS_RDATA_INIT;
5587 dns_name_t *nsecname;
5588 dns_rdata_nsec_t nsecstruct;
5590 if ((result = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
5592 printf(";; nothing in authority section : impossible to"
5593 " validate the non-existence : FAILED\n");
5594 return (ISC_R_FAILURE);
5599 dns_message_currentname(msg, DNS_SECTION_AUTHORITY, &nsecname);
5600 nsecset = search_type(nsecname, dns_rdatatype_nsec,
5602 if (nsecset == NULL)
5605 printf("There is a NSEC for this zone in the"
5606 " AUTHORITY section:\n");
5607 print_rdataset(nsecname, nsecset, mctx);
5609 for (result = dns_rdataset_first(nsecset);
5610 result == ISC_R_SUCCESS;
5611 result = dns_rdataset_next(nsecset)) {
5612 dns_rdataset_current(nsecset, &nsec);
5616 = chase_scanname_section(msg, nsecname,
5617 dns_rdatatype_rrsig,
5619 DNS_SECTION_AUTHORITY);
5620 if (signsecset == NULL) {
5621 printf(";; no RRSIG NSEC in authority section:"
5622 " impossible to validate the "
5623 "non-existence: FAILED\n");
5624 return (ISC_R_FAILURE);
5627 ret = dns_rdata_tostruct(&nsec, &nsecstruct, NULL);
5628 check_result(ret,"dns_rdata_tostruct");
5630 if ((inf_name(nsecname, &nsecstruct.next) == 1 &&
5631 inf_name(name, &nsecstruct.next) == 1) ||
5632 (inf_name(name, nsecname) == 1 &&
5633 inf_name(&nsecstruct.next, name) == 1)) {
5634 dns_rdata_freestruct(&nsecstruct);
5635 *rdataset = nsecset;
5636 *sigrdataset = signsecset;
5637 dup_name(nsecname, rdata_name, mctx);
5639 return (ISC_R_SUCCESS);
5642 dns_rdata_freestruct(&nsecstruct);
5643 dns_rdata_reset(&nsec);
5645 } while (dns_message_nextname(msg, DNS_SECTION_AUTHORITY)
5649 *sigrdataset = NULL;
5651 return (ISC_R_FAILURE);
5662 prove_nx_type(dns_message_t *msg, dns_name_t *name, dns_rdataset_t *nsecset,
5663 dns_rdataclass_t class, dns_rdatatype_t type,
5664 dns_name_t *rdata_name, dns_rdataset_t **rdataset,
5665 dns_rdataset_t **sigrdataset)
5668 dns_rdataset_t *signsecset;
5669 dns_rdata_t nsec = DNS_RDATA_INIT;
5673 ret = dns_rdataset_first(nsecset);
5674 check_result(ret,"dns_rdataset_first");
5676 dns_rdataset_current(nsecset, &nsec);
5678 ret = dns_nsec_typepresent(&nsec, type);
5679 if (ret == ISC_R_SUCCESS)
5680 printf("OK the NSEC said that the type doesn't exist \n");
5682 signsecset = chase_scanname_section(msg, name,
5683 dns_rdatatype_rrsig,
5685 DNS_SECTION_AUTHORITY);
5686 if (signsecset == NULL) {
5687 printf("There isn't RRSIG NSEC for the zone \n");
5688 return (ISC_R_FAILURE);
5690 dup_name(name, rdata_name, mctx);
5691 *rdataset = nsecset;
5692 *sigrdataset = signsecset;
5704 prove_nx(dns_message_t *msg, dns_name_t *name, dns_rdataclass_t class,
5705 dns_rdatatype_t type, dns_name_t *rdata_name,
5706 dns_rdataset_t **rdataset, dns_rdataset_t **sigrdataset)
5709 dns_rdataset_t *nsecset = NULL;
5711 printf("We want to prove the non-existence of a type of rdata %d"
5712 " or of the zone: \n", type);
5714 if ((ret = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
5716 printf(";; nothing in authority section : impossible to"
5717 " validate the non-existence : FAILED\n");
5718 return (ISC_R_FAILURE);
5721 nsecset = chase_scanname_section(msg, name, dns_rdatatype_nsec,
5723 DNS_SECTION_AUTHORITY);
5724 if (nsecset != NULL) {
5725 printf("We have a NSEC for this zone :OK\n");
5726 ret = prove_nx_type(msg, name, nsecset, class,
5727 type, rdata_name, rdataset,
5729 if (ret != ISC_R_SUCCESS) {
5730 printf("prove_nx: ERROR type exist\n");
5733 printf("prove_nx: OK type does not exist\n");
5734 return (ISC_R_SUCCESS);
5737 printf("there is no NSEC for this zone: validating "
5738 "that the zone doesn't exist\n");
5739 ret = prove_nx_domain(msg, name, rdata_name,
5740 rdataset, sigrdataset);
5743 /* Never get here */