2 * Copyright (C) 2004-2014 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.9 2011/12/07 17:23:55 each 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/callbacks.h>
50 #include <dns/dnssec.h>
52 #include <dns/master.h>
54 #include <isc/random.h>
57 #include <dns/fixedname.h>
59 #include <dns/message.h>
61 #include <dns/rdata.h>
62 #include <dns/rdataclass.h>
63 #include <dns/rdatalist.h>
64 #include <dns/rdataset.h>
65 #include <dns/rdatastruct.h>
66 #include <dns/rdatatype.h>
67 #include <dns/result.h>
71 #include <dst/result.h>
74 #include <isc/base64.h>
75 #include <isc/entropy.h>
79 #include <isc/netaddr.h>
81 #include <isc/netdb.h>
83 #include <isc/parseint.h>
84 #include <isc/print.h>
85 #include <isc/random.h>
86 #include <isc/result.h>
87 #include <isc/serial.h>
88 #include <isc/string.h>
90 #include <isc/timer.h>
91 #include <isc/types.h>
94 #include <isccfg/namedconf.h>
96 #include <lwres/lwres.h>
97 #include <lwres/net.h>
99 #include <bind9/getaddresses.h>
103 #if ! defined(NS_INADDRSZ)
104 #define NS_INADDRSZ 4
107 #if ! defined(NS_IN6ADDRSZ)
108 #define NS_IN6ADDRSZ 16
111 static lwres_context_t *lwctx = NULL;
112 static lwres_conf_t *lwconf;
114 dig_lookuplist_t lookup_list;
115 dig_serverlist_t server_list;
116 dig_searchlistlist_t search_list;
119 check_ra = ISC_FALSE,
120 have_ipv4 = ISC_FALSE,
121 have_ipv6 = ISC_FALSE,
122 specified_source = ISC_FALSE,
123 free_now = ISC_FALSE,
124 cancel_now = ISC_FALSE,
125 usesearch = ISC_FALSE,
126 showsearch = ISC_FALSE,
128 is_dst_up = ISC_FALSE,
129 keep_open = ISC_FALSE;
131 unsigned int timeout = 0;
132 unsigned int extrabytes;
133 isc_mem_t *mctx = NULL;
134 isc_log_t *lctx = NULL;
135 isc_taskmgr_t *taskmgr = NULL;
136 isc_task_t *global_task = NULL;
137 isc_timermgr_t *timermgr = NULL;
138 isc_socketmgr_t *socketmgr = NULL;
139 isc_sockaddr_t bind_address;
140 isc_sockaddr_t bind_any;
146 int lookup_counter = 0;
149 static void initialize_idn(void);
150 static isc_result_t output_filter(isc_buffer_t *buffer,
151 unsigned int used_org,
152 isc_boolean_t absolute);
153 static idn_result_t append_textname(char *name, const char *origin,
155 static void idn_check_result(idn_result_t r, const char *msg);
161 isc_socket_t *keep = NULL;
162 isc_sockaddr_t keepaddr;
167 *\li 0 Everything went well, including things like NXDOMAIN
169 *\li 7 Got too many RR's or Names
170 *\li 8 Couldn't open batch file
171 *\li 9 No reply from server
172 *\li 10 Internal error
176 char keynametext[MXNAME];
177 char keyfile[MXNAME] = "";
178 char keysecret[MXNAME] = "";
179 dns_name_t *hmacname = NULL;
180 unsigned int digestbits = 0;
181 isc_buffer_t *namebuf = NULL;
182 dns_tsigkey_t *key = NULL;
183 isc_boolean_t validated = ISC_TRUE;
184 isc_entropy_t *entp = NULL;
185 isc_mempool_t *commctx = NULL;
186 isc_boolean_t debugging = ISC_FALSE;
187 isc_boolean_t debugtiming = ISC_FALSE;
188 isc_boolean_t memdebugging = ISC_FALSE;
189 char *progname = NULL;
190 isc_mutex_t lookup_lock;
191 dig_lookup_t *current_lookup = NULL;
195 isc_result_t get_trusted_key(isc_mem_t *mctx);
196 dns_rdataset_t * sigchase_scanname(dns_rdatatype_t type,
197 dns_rdatatype_t covers,
198 isc_boolean_t *lookedup,
199 dns_name_t *rdata_name);
200 dns_rdataset_t * chase_scanname_section(dns_message_t *msg,
202 dns_rdatatype_t type,
203 dns_rdatatype_t covers,
205 isc_result_t advanced_rrsearch(dns_rdataset_t **rdataset,
207 dns_rdatatype_t type,
208 dns_rdatatype_t covers,
209 isc_boolean_t *lookedup);
210 isc_result_t sigchase_verify_sig_key(dns_name_t *name,
211 dns_rdataset_t *rdataset,
212 dst_key_t* dnsseckey,
213 dns_rdataset_t *sigrdataset,
215 isc_result_t sigchase_verify_sig(dns_name_t *name,
216 dns_rdataset_t *rdataset,
217 dns_rdataset_t *keyrdataset,
218 dns_rdataset_t *sigrdataset,
220 isc_result_t sigchase_verify_ds(dns_name_t *name,
221 dns_rdataset_t *keyrdataset,
222 dns_rdataset_t *dsrdataset,
224 void sigchase(dns_message_t *msg);
225 void print_rdata(dns_rdata_t *rdata, isc_mem_t *mctx);
226 void print_rdataset(dns_name_t *name,
227 dns_rdataset_t *rdataset, isc_mem_t *mctx);
228 void dup_name(dns_name_t *source, dns_name_t* target,
230 void free_name(dns_name_t *name, isc_mem_t *mctx);
231 void dump_database(void);
232 void dump_database_section(dns_message_t *msg, int section);
233 dns_rdataset_t * search_type(dns_name_t *name, dns_rdatatype_t type,
234 dns_rdatatype_t covers);
235 isc_result_t contains_trusted_key(dns_name_t *name,
236 dns_rdataset_t *rdataset,
237 dns_rdataset_t *sigrdataset,
239 void print_type(dns_rdatatype_t type);
240 isc_result_t prove_nx_domain(dns_message_t * msg,
242 dns_name_t * rdata_name,
243 dns_rdataset_t ** rdataset,
244 dns_rdataset_t ** sigrdataset);
245 isc_result_t prove_nx_type(dns_message_t * msg, dns_name_t *name,
246 dns_rdataset_t *nsec,
247 dns_rdataclass_t class,
248 dns_rdatatype_t type,
249 dns_name_t * rdata_name,
250 dns_rdataset_t ** rdataset,
251 dns_rdataset_t ** sigrdataset);
252 isc_result_t prove_nx(dns_message_t * msg, dns_name_t * name,
253 dns_rdataclass_t class,
254 dns_rdatatype_t type,
255 dns_name_t * rdata_name,
256 dns_rdataset_t ** rdataset,
257 dns_rdataset_t ** sigrdataset);
258 static void nameFromString(const char *str, dns_name_t *p_ret);
259 int inf_name(dns_name_t * name1, dns_name_t * name2);
260 isc_result_t removetmpkey(isc_mem_t *mctx, const char *file);
261 void clean_trustedkey(void);
262 isc_result_t insert_trustedkey(void *arg, dns_name_t *name,
263 dns_rdataset_t *rdataset);
265 isc_result_t getneededrr(dns_message_t *msg);
266 void sigchase_bottom_up(dns_message_t *msg);
267 void sigchase_bu(dns_message_t *msg);
270 isc_result_t initialization(dns_name_t *name);
271 isc_result_t prepare_lookup(dns_name_t *name);
272 isc_result_t grandfather_pb_test(dns_name_t * zone_name,
273 dns_rdataset_t *sigrdataset);
274 isc_result_t child_of_zone(dns_name_t *name,
275 dns_name_t *zone_name,
276 dns_name_t *child_name);
277 void sigchase_td(dns_message_t *msg);
279 char trustedkey[MXNAME] = "";
281 dns_rdataset_t *chase_rdataset = NULL;
282 dns_rdataset_t *chase_sigrdataset = NULL;
283 dns_rdataset_t *chase_dsrdataset = NULL;
284 dns_rdataset_t *chase_sigdsrdataset = NULL;
285 dns_rdataset_t *chase_keyrdataset = NULL;
286 dns_rdataset_t *chase_sigkeyrdataset = NULL;
287 dns_rdataset_t *chase_nsrdataset = NULL;
289 dns_name_t chase_name; /* the query name */
292 * the current name is the parent name when we follow delegation
294 dns_name_t chase_current_name;
296 * the child name is used for delegation (NS DS responses in AUTHORITY section)
298 dns_name_t chase_authority_name;
301 dns_name_t chase_signame;
305 isc_boolean_t chase_siglookedup = ISC_FALSE;
306 isc_boolean_t chase_keylookedup = ISC_FALSE;
307 isc_boolean_t chase_sigkeylookedup = ISC_FALSE;
308 isc_boolean_t chase_dslookedup = ISC_FALSE;
309 isc_boolean_t chase_sigdslookedup = ISC_FALSE;
311 isc_boolean_t chase_nslookedup = ISC_FALSE;
312 isc_boolean_t chase_lookedup = ISC_FALSE;
315 isc_boolean_t delegation_follow = ISC_FALSE;
316 isc_boolean_t grandfather_pb = ISC_FALSE;
317 isc_boolean_t have_response = ISC_FALSE;
318 isc_boolean_t have_delegation_ns = ISC_FALSE;
319 dns_message_t * error_message = NULL;
322 isc_boolean_t dsvalidating = ISC_FALSE;
323 isc_boolean_t chase_name_dup = ISC_FALSE;
325 ISC_LIST(dig_message_t) chase_message_list;
326 ISC_LIST(dig_message_t) chase_message_list2;
329 #define MAX_TRUSTED_KEY 5
330 typedef struct struct_trusted_key_list {
331 dst_key_t * key[MAX_TRUSTED_KEY];
335 struct_tk_list tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0};
339 #define DIG_MAX_ADDRESSES 20
342 * Apply and clear locks at the event level in global task.
343 * Can I get rid of these using shutdown events? XXX
345 #define LOCK_LOOKUP {\
346 debug("lock_lookup %s:%d", __FILE__, __LINE__);\
347 check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\
350 #define UNLOCK_LOOKUP {\
351 debug("unlock_lookup %s:%d", __FILE__, __LINE__);\
352 check_result(isc_mutex_unlock((&lookup_lock)),\
353 "isc_mutex_unlock");\
357 cancel_lookup(dig_lookup_t *lookup);
360 recv_done(isc_task_t *task, isc_event_t *event);
363 send_udp(dig_query_t *query);
366 connect_timeout(isc_task_t *task, isc_event_t *event);
369 launch_next_query(dig_query_t *query, isc_boolean_t include_question);
372 send_tcp_connect(dig_query_t *query);
375 mem_alloc(void *arg, size_t size) {
376 return (isc_mem_get(arg, size));
380 mem_free(void *arg, void *mem, size_t size) {
381 isc_mem_put(arg, mem, size);
385 next_token(char **stringp, const char *delim) {
389 res = strsep(stringp, delim);
392 } while (*res == '\0');
397 count_dots(char *string) {
411 hex_dump(isc_buffer_t *b) {
415 isc_buffer_usedregion(b, &r);
417 printf("%d bytes\n", r.length);
418 for (len = 0; len < r.length; len++) {
419 printf("%02x ", r.base[len]);
420 if (len % 16 == 15) {
422 for (i = len - 15; i <= len; i++) {
423 if (r.base[i] >= '!' && r.base[i] <= '}')
432 for (i = len; (i % 16) != 0; i++)
435 for (i = ((len>>4)<<4); i < len; i++) {
436 if (r.base[i] >= '!' && r.base[i] <= '}')
446 * Append 'len' bytes of 'text' at '*p', failing with
447 * ISC_R_NOSPACE if that would advance p past 'end'.
450 append(const char *text, int len, char **p, char *end) {
452 return (ISC_R_NOSPACE);
453 memmove(*p, text, len);
455 return (ISC_R_SUCCESS);
459 reverse_octets(const char *in, char **p, char *end) {
460 char *dot = strchr(in, '.');
464 result = reverse_octets(dot + 1, p, end);
465 if (result != ISC_R_SUCCESS)
467 result = append(".", 1, p, end);
468 if (result != ISC_R_SUCCESS)
470 len = (int)(dot - in);
474 return (append(in, len, p, end));
478 get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int,
479 isc_boolean_t strict)
485 addr.family = AF_INET6;
486 r = inet_pton(AF_INET6, value, &addr.type.in6);
488 /* This is a valid IPv6 address. */
489 dns_fixedname_t fname;
491 unsigned int options = 0;
494 options |= DNS_BYADDROPT_IPV6INT;
495 dns_fixedname_init(&fname);
496 name = dns_fixedname_name(&fname);
497 result = dns_byaddr_createptrname2(&addr, options, name);
498 if (result != ISC_R_SUCCESS)
500 dns_name_format(name, reverse, (unsigned int)len);
501 return (ISC_R_SUCCESS);
504 * Not a valid IPv6 address. Assume IPv4.
505 * If 'strict' is not set, construct the
506 * in-addr.arpa name by blindly reversing
507 * octets whether or not they look like integers,
508 * so that this can be used for RFC2317 names
512 char *end = reverse + len;
513 if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1)
514 return (DNS_R_BADDOTTEDQUAD);
515 result = reverse_octets(value, &p, end);
516 if (result != ISC_R_SUCCESS)
518 /* Append .in-addr.arpa. and a terminating NUL. */
519 result = append(".in-addr.arpa.", 15, &p, end);
520 if (result != ISC_R_SUCCESS)
522 return (ISC_R_SUCCESS);
527 fatal(const char *format, ...) {
531 fprintf(stderr, "%s: ", progname);
532 va_start(args, format);
533 vfprintf(stderr, format, args);
535 fprintf(stderr, "\n");
539 exitcode = fatalexit;
544 debug(const char *format, ...) {
552 fprintf(stderr, "%d.%06d: ", isc_time_seconds(&t),
553 isc_time_nanoseconds(&t) / 1000);
555 va_start(args, format);
556 vfprintf(stderr, format, args);
558 fprintf(stderr, "\n");
563 check_result(isc_result_t result, const char *msg) {
564 if (result != ISC_R_SUCCESS) {
565 fatal("%s: %s", msg, isc_result_totext(result));
570 * Create a server structure, which is part of the lookup structure.
571 * This is little more than a linked list of servers to query in hopes
572 * of finding the answer the user is looking for
575 make_server(const char *servname, const char *userarg) {
578 REQUIRE(servname != NULL);
580 debug("make_server(%s)", servname);
581 srv = isc_mem_allocate(mctx, sizeof(struct dig_server));
583 fatal("memory allocation failure in %s:%d",
585 strlcpy(srv->servername, servname, MXNAME);
586 strlcpy(srv->userarg, userarg, MXNAME);
587 ISC_LINK_INIT(srv, link);
592 addr2af(int lwresaddrtype)
596 switch (lwresaddrtype) {
597 case LWRES_ADDRTYPE_V4:
601 case LWRES_ADDRTYPE_V6:
610 * Create a copy of the server list from the lwres configuration structure.
611 * The dest list must have already had ISC_LIST_INIT applied.
614 copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) {
615 dig_server_t *newsrv;
616 char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
620 debug("copy_server_list()");
621 for (i = 0; i < confdata->nsnext; i++) {
622 af = addr2af(confdata->nameservers[i].family);
624 if (af == AF_INET && !have_ipv4)
626 if (af == AF_INET6 && !have_ipv6)
629 lwres_net_ntop(af, confdata->nameservers[i].address,
631 newsrv = make_server(tmp, tmp);
632 ISC_LINK_INIT(newsrv, link);
633 ISC_LIST_ENQUEUE(*dest, newsrv, link);
638 flush_server_list(void) {
639 dig_server_t *s, *ps;
641 debug("flush_server_list()");
642 s = ISC_LIST_HEAD(server_list);
645 s = ISC_LIST_NEXT(s, link);
646 ISC_LIST_DEQUEUE(server_list, ps, link);
647 isc_mem_free(mctx, ps);
652 set_nameserver(char *opt) {
654 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
655 isc_netaddr_t netaddr;
658 char tmp[ISC_NETADDR_FORMATSIZE];
663 result = bind9_getaddresses(opt, 0, sockaddrs,
664 DIG_MAX_ADDRESSES, &count);
665 if (result != ISC_R_SUCCESS)
666 fatal("couldn't get address for '%s': %s",
667 opt, isc_result_totext(result));
671 for (i = 0; i < count; i++) {
672 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
673 isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
674 srv = make_server(tmp, opt);
676 fatal("memory allocation failure");
677 ISC_LIST_APPEND(server_list, srv, link);
682 add_nameserver(lwres_conf_t *confdata, const char *addr, int af) {
684 int i = confdata->nsnext;
686 if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS)
687 return (ISC_R_FAILURE);
691 confdata->nameservers[i].family = LWRES_ADDRTYPE_V4;
692 confdata->nameservers[i].length = NS_INADDRSZ;
695 confdata->nameservers[i].family = LWRES_ADDRTYPE_V6;
696 confdata->nameservers[i].length = NS_IN6ADDRSZ;
699 return (ISC_R_FAILURE);
702 if (lwres_net_pton(af, addr, &confdata->nameservers[i].address) == 1) {
704 return (ISC_R_SUCCESS);
706 return (ISC_R_FAILURE);
710 * Produce a cloned server list. The dest list must have already had
711 * ISC_LIST_INIT applied.
714 clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
715 dig_server_t *srv, *newsrv;
717 debug("clone_server_list()");
718 srv = ISC_LIST_HEAD(src);
719 while (srv != NULL) {
720 newsrv = make_server(srv->servername, srv->userarg);
721 ISC_LINK_INIT(newsrv, link);
722 ISC_LIST_ENQUEUE(*dest, newsrv, link);
723 srv = ISC_LIST_NEXT(srv, link);
728 * Create an empty lookup structure, which holds all the information needed
729 * to get an answer to a user's question. This structure contains two
730 * linked lists: the server list (servers to query) and the query list
731 * (outstanding queries which have been made to the listed servers).
734 make_empty_lookup(void) {
735 dig_lookup_t *looknew;
737 debug("make_empty_lookup()");
741 looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
743 fatal("memory allocation failure in %s:%d",
745 looknew->pending = ISC_TRUE;
746 looknew->textname[0] = 0;
747 looknew->cmdline[0] = 0;
748 looknew->rdtype = dns_rdatatype_a;
749 looknew->qrdtype = dns_rdatatype_a;
750 looknew->rdclass = dns_rdataclass_in;
751 looknew->rdtypeset = ISC_FALSE;
752 looknew->rdclassset = ISC_FALSE;
753 looknew->sendspace = NULL;
754 looknew->sendmsg = NULL;
755 looknew->name = NULL;
756 looknew->oname = NULL;
757 looknew->timer = NULL;
758 looknew->xfr_q = NULL;
759 looknew->current_query = NULL;
760 looknew->doing_xfr = ISC_FALSE;
761 looknew->ixfr_serial = 0;
762 looknew->trace = ISC_FALSE;
763 looknew->trace_root = ISC_FALSE;
764 looknew->identify = ISC_FALSE;
765 looknew->identify_previous_line = ISC_FALSE;
766 looknew->ignore = ISC_FALSE;
767 looknew->servfail_stops = ISC_TRUE;
768 looknew->besteffort = ISC_TRUE;
769 looknew->dnssec = ISC_FALSE;
770 looknew->nsid = ISC_FALSE;
772 looknew->sigchase = ISC_FALSE;
774 looknew->do_topdown = ISC_FALSE;
775 looknew->trace_root_sigchase = ISC_FALSE;
776 looknew->rdtype_sigchaseset = ISC_FALSE;
777 looknew->rdtype_sigchase = dns_rdatatype_any;
778 looknew->qrdtype_sigchase = dns_rdatatype_any;
779 looknew->rdclass_sigchase = dns_rdataclass_in;
780 looknew->rdclass_sigchaseset = ISC_FALSE;
783 looknew->udpsize = 0;
785 looknew->recurse = ISC_TRUE;
786 looknew->aaonly = ISC_FALSE;
787 looknew->adflag = ISC_FALSE;
788 looknew->cdflag = ISC_FALSE;
789 looknew->ns_search_only = ISC_FALSE;
790 looknew->origin = NULL;
791 looknew->tsigctx = NULL;
792 looknew->querysig = NULL;
793 looknew->retries = tries;
794 looknew->nsfound = 0;
795 looknew->tcp_mode = ISC_FALSE;
796 looknew->ip6_int = ISC_FALSE;
797 looknew->comments = ISC_TRUE;
798 looknew->stats = ISC_TRUE;
799 looknew->section_question = ISC_TRUE;
800 looknew->section_answer = ISC_TRUE;
801 looknew->section_authority = ISC_TRUE;
802 looknew->section_additional = ISC_TRUE;
803 looknew->new_search = ISC_FALSE;
804 looknew->done_as_is = ISC_FALSE;
805 looknew->need_search = ISC_FALSE;
806 dns_fixedname_init(&looknew->fdomain);
807 ISC_LINK_INIT(looknew, link);
808 ISC_LIST_INIT(looknew->q);
809 ISC_LIST_INIT(looknew->connecting);
810 ISC_LIST_INIT(looknew->my_server_list);
815 * Clone a lookup, perhaps copying the server list. This does not clone
816 * the query list, since it will be regenerated by the setup_lookup()
817 * function, nor does it queue up the new lookup for processing.
818 * Caution: If you don't clone the servers, you MUST clone the server
819 * list separately from somewhere else, or construct it by hand.
822 clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
823 dig_lookup_t *looknew;
825 debug("clone_lookup()");
829 looknew = make_empty_lookup();
830 INSIST(looknew != NULL);
831 strlcpy(looknew->textname, lookold->textname, MXNAME);
833 strlcpy(looknew->textnamesigchase, lookold->textnamesigchase, MXNAME);
835 strlcpy(looknew->cmdline, lookold->cmdline, MXNAME);
836 looknew->textname[MXNAME-1] = 0;
837 looknew->rdtype = lookold->rdtype;
838 looknew->qrdtype = lookold->qrdtype;
839 looknew->rdclass = lookold->rdclass;
840 looknew->rdtypeset = lookold->rdtypeset;
841 looknew->rdclassset = lookold->rdclassset;
842 looknew->doing_xfr = lookold->doing_xfr;
843 looknew->ixfr_serial = lookold->ixfr_serial;
844 looknew->trace = lookold->trace;
845 looknew->trace_root = lookold->trace_root;
846 looknew->identify = lookold->identify;
847 looknew->identify_previous_line = lookold->identify_previous_line;
848 looknew->ignore = lookold->ignore;
849 looknew->servfail_stops = lookold->servfail_stops;
850 looknew->besteffort = lookold->besteffort;
851 looknew->dnssec = lookold->dnssec;
852 looknew->nsid = lookold->nsid;
854 looknew->sigchase = lookold->sigchase;
856 looknew->do_topdown = lookold->do_topdown;
857 looknew->trace_root_sigchase = lookold->trace_root_sigchase;
858 looknew->rdtype_sigchaseset = lookold->rdtype_sigchaseset;
859 looknew->rdtype_sigchase = lookold->rdtype_sigchase;
860 looknew->qrdtype_sigchase = lookold->qrdtype_sigchase;
861 looknew->rdclass_sigchase = lookold->rdclass_sigchase;
862 looknew->rdclass_sigchaseset = lookold->rdclass_sigchaseset;
865 looknew->udpsize = lookold->udpsize;
866 looknew->edns = lookold->edns;
867 looknew->recurse = lookold->recurse;
868 looknew->aaonly = lookold->aaonly;
869 looknew->adflag = lookold->adflag;
870 looknew->cdflag = lookold->cdflag;
871 looknew->ns_search_only = lookold->ns_search_only;
872 looknew->tcp_mode = lookold->tcp_mode;
873 looknew->comments = lookold->comments;
874 looknew->stats = lookold->stats;
875 looknew->section_question = lookold->section_question;
876 looknew->section_answer = lookold->section_answer;
877 looknew->section_authority = lookold->section_authority;
878 looknew->section_additional = lookold->section_additional;
879 looknew->retries = lookold->retries;
880 looknew->tsigctx = NULL;
881 looknew->need_search = lookold->need_search;
882 looknew->done_as_is = lookold->done_as_is;
883 dns_name_copy(dns_fixedname_name(&lookold->fdomain),
884 dns_fixedname_name(&looknew->fdomain), NULL);
887 clone_server_list(lookold->my_server_list,
888 &looknew->my_server_list);
893 * Requeue a lookup for further processing, perhaps copying the server
894 * list. The new lookup structure is returned to the caller, and is
895 * queued for processing. If servers are not cloned in the requeue, they
896 * must be added before allowing the current event to complete, since the
897 * completion of the event may result in the next entry on the lookup
901 requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
902 dig_lookup_t *looknew;
904 debug("requeue_lookup()");
907 if (lookup_counter > LOOKUP_LIMIT)
908 fatal("too many lookups");
910 looknew = clone_lookup(lookold, servers);
911 INSIST(looknew != NULL);
913 debug("before insertion, init@%p -> %p, new@%p -> %p",
914 lookold, lookold->link.next, looknew, looknew->link.next);
915 ISC_LIST_PREPEND(lookup_list, looknew, link);
916 debug("after insertion, init -> %p, new = %p, new -> %p",
917 lookold, looknew, looknew->link.next);
923 setup_text_key(void) {
926 isc_buffer_t secretbuf;
928 unsigned char *secretstore;
930 debug("setup_text_key()");
931 result = isc_buffer_allocate(mctx, &namebuf, MXNAME);
932 check_result(result, "isc_buffer_allocate");
933 dns_name_init(&keyname, NULL);
934 check_result(result, "dns_name_init");
935 isc_buffer_putstr(namebuf, keynametext);
936 secretsize = strlen(keysecret) * 3 / 4;
937 secretstore = isc_mem_allocate(mctx, secretsize);
938 if (secretstore == NULL)
939 fatal("memory allocation failure in %s:%d",
941 isc_buffer_init(&secretbuf, secretstore, secretsize);
942 result = isc_base64_decodestring(keysecret, &secretbuf);
943 if (result != ISC_R_SUCCESS)
946 secretsize = isc_buffer_usedlength(&secretbuf);
948 if (hmacname == NULL) {
949 result = DST_R_UNSUPPORTEDALG;
953 result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf);
954 if (result != ISC_R_SUCCESS)
957 result = dns_tsigkey_create(&keyname, hmacname, secretstore,
958 secretsize, ISC_FALSE, NULL, 0, 0, mctx,
961 if (result != ISC_R_SUCCESS)
962 printf(";; Couldn't create key %s: %s\n",
963 keynametext, isc_result_totext(result));
965 dst_key_setbits(key->key, digestbits);
967 isc_mem_free(mctx, secretstore);
968 dns_name_invalidate(&keyname);
969 isc_buffer_free(&namebuf);
973 parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max,
976 isc_result_t result = isc_parse_uint32(&n, value, 10);
977 if (result == ISC_R_SUCCESS && n > max)
978 result = ISC_R_RANGE;
979 if (result != ISC_R_SUCCESS) {
980 printf("invalid %s '%s': %s\n", desc,
981 value, isc_result_totext(result));
985 return (ISC_R_SUCCESS);
989 parse_bits(char *arg, const char *desc, isc_uint32_t max) {
993 result = parse_uint(&tmp, arg, max, desc);
994 if (result != ISC_R_SUCCESS)
995 fatal("couldn't parse digest bits");
996 tmp = (tmp + 7) & ~0x7U;
1002 * Parse HMAC algorithm specification
1005 parse_hmac(const char *hmac) {
1009 REQUIRE(hmac != NULL);
1012 if (len >= (int) sizeof(buf))
1013 fatal("unknown key type '%.*s'", len, hmac);
1014 strlcpy(buf, hmac, sizeof(buf));
1018 if (strcasecmp(buf, "hmac-md5") == 0) {
1019 hmacname = DNS_TSIG_HMACMD5_NAME;
1020 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
1021 hmacname = DNS_TSIG_HMACMD5_NAME;
1022 digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128);
1023 } else if (strcasecmp(buf, "hmac-sha1") == 0) {
1024 hmacname = DNS_TSIG_HMACSHA1_NAME;
1026 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
1027 hmacname = DNS_TSIG_HMACSHA1_NAME;
1028 digestbits = parse_bits(&buf[10], "digest-bits [0..160]", 160);
1029 } else if (strcasecmp(buf, "hmac-sha224") == 0) {
1030 hmacname = DNS_TSIG_HMACSHA224_NAME;
1031 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
1032 hmacname = DNS_TSIG_HMACSHA224_NAME;
1033 digestbits = parse_bits(&buf[12], "digest-bits [0..224]", 224);
1034 } else if (strcasecmp(buf, "hmac-sha256") == 0) {
1035 hmacname = DNS_TSIG_HMACSHA256_NAME;
1036 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
1037 hmacname = DNS_TSIG_HMACSHA256_NAME;
1038 digestbits = parse_bits(&buf[12], "digest-bits [0..256]", 256);
1039 } else if (strcasecmp(buf, "hmac-sha384") == 0) {
1040 hmacname = DNS_TSIG_HMACSHA384_NAME;
1041 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
1042 hmacname = DNS_TSIG_HMACSHA384_NAME;
1043 digestbits = parse_bits(&buf[12], "digest-bits [0..384]", 384);
1044 } else if (strcasecmp(buf, "hmac-sha512") == 0) {
1045 hmacname = DNS_TSIG_HMACSHA512_NAME;
1046 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
1047 hmacname = DNS_TSIG_HMACSHA512_NAME;
1048 digestbits = parse_bits(&buf[12], "digest-bits [0..512]", 512);
1050 fprintf(stderr, ";; Warning, ignoring "
1051 "invalid TSIG algorithm %s\n", buf);
1056 * Get a key from a named.conf format keyfile
1059 read_confkey(void) {
1060 isc_log_t *lctx = NULL;
1061 cfg_parser_t *pctx = NULL;
1062 cfg_obj_t *file = NULL;
1063 const cfg_obj_t *key = NULL;
1064 const cfg_obj_t *secretobj = NULL;
1065 const cfg_obj_t *algorithmobj = NULL;
1066 const char *keyname;
1067 const char *secretstr;
1068 const char *algorithm;
1069 isc_result_t result;
1071 if (! isc_file_exists(keyfile))
1072 return (ISC_R_FILENOTFOUND);
1074 result = cfg_parser_create(mctx, lctx, &pctx);
1075 if (result != ISC_R_SUCCESS)
1078 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
1080 if (result != ISC_R_SUCCESS)
1083 result = cfg_map_get(file, "key", &key);
1084 if (result != ISC_R_SUCCESS)
1087 (void) cfg_map_get(key, "secret", &secretobj);
1088 (void) cfg_map_get(key, "algorithm", &algorithmobj);
1089 if (secretobj == NULL || algorithmobj == NULL)
1090 fatal("key must have algorithm and secret");
1092 keyname = cfg_obj_asstring(cfg_map_getname(key));
1093 secretstr = cfg_obj_asstring(secretobj);
1094 algorithm = cfg_obj_asstring(algorithmobj);
1096 strlcpy(keynametext, keyname, sizeof(keynametext));
1097 strlcpy(keysecret, secretstr, sizeof(keysecret));
1098 parse_hmac(algorithm);
1104 cfg_obj_destroy(pctx, &file);
1105 cfg_parser_destroy(&pctx);
1112 setup_file_key(void) {
1113 isc_result_t result;
1114 dst_key_t *dstkey = NULL;
1116 debug("setup_file_key()");
1118 /* Try reading the key from a K* pair */
1119 result = dst_key_fromnamedfile(keyfile, NULL,
1120 DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
1123 /* If that didn't work, try reading it as a session.key keyfile */
1124 if (result != ISC_R_SUCCESS) {
1125 result = read_confkey();
1126 if (result == ISC_R_SUCCESS)
1130 if (result != ISC_R_SUCCESS) {
1131 fprintf(stderr, "Couldn't read key from %s: %s\n",
1132 keyfile, isc_result_totext(result));
1136 switch (dst_key_alg(dstkey)) {
1137 case DST_ALG_HMACMD5:
1138 hmacname = DNS_TSIG_HMACMD5_NAME;
1140 case DST_ALG_HMACSHA1:
1141 hmacname = DNS_TSIG_HMACSHA1_NAME;
1143 case DST_ALG_HMACSHA224:
1144 hmacname = DNS_TSIG_HMACSHA224_NAME;
1146 case DST_ALG_HMACSHA256:
1147 hmacname = DNS_TSIG_HMACSHA256_NAME;
1149 case DST_ALG_HMACSHA384:
1150 hmacname = DNS_TSIG_HMACSHA384_NAME;
1152 case DST_ALG_HMACSHA512:
1153 hmacname = DNS_TSIG_HMACSHA512_NAME;
1156 printf(";; Couldn't create key %s: bad algorithm\n",
1160 result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmacname,
1161 dstkey, ISC_FALSE, NULL, 0, 0,
1163 if (result != ISC_R_SUCCESS) {
1164 printf(";; Couldn't create key %s: %s\n",
1165 keynametext, isc_result_totext(result));
1170 dst_key_free(&dstkey);
1173 static dig_searchlist_t *
1174 make_searchlist_entry(char *domain) {
1175 dig_searchlist_t *search;
1176 search = isc_mem_allocate(mctx, sizeof(*search));
1178 fatal("memory allocation failure in %s:%d",
1179 __FILE__, __LINE__);
1180 strlcpy(search->origin, domain, MXNAME);
1181 search->origin[MXNAME-1] = 0;
1182 ISC_LINK_INIT(search, link);
1187 clear_searchlist(void) {
1188 dig_searchlist_t *search;
1189 while ((search = ISC_LIST_HEAD(search_list)) != NULL) {
1190 ISC_LIST_UNLINK(search_list, search, link);
1191 isc_mem_free(mctx, search);
1196 create_search_list(lwres_conf_t *confdata) {
1198 dig_searchlist_t *search;
1200 debug("create_search_list()");
1203 for (i = 0; i < confdata->searchnxt; i++) {
1204 search = make_searchlist_entry(confdata->search[i]);
1205 ISC_LIST_APPEND(search_list, search, link);
1210 * Setup the system as a whole, reading key information and resolv.conf
1214 setup_system(void) {
1215 dig_searchlist_t *domain = NULL;
1216 lwres_result_t lwresult;
1217 unsigned int lwresflags;
1219 debug("setup_system()");
1221 lwresflags = LWRES_CONTEXT_SERVERMODE;
1223 lwresflags |= LWRES_CONTEXT_USEIPV4;
1225 lwresflags |= LWRES_CONTEXT_USEIPV6;
1227 lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free,
1229 if (lwresult != LWRES_R_SUCCESS)
1230 fatal("lwres_context_create failed");
1232 lwresult = lwres_conf_parse(lwctx, RESOLV_CONF);
1233 if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND)
1234 fatal("parse of %s failed", RESOLV_CONF);
1236 lwconf = lwres_conf_get(lwctx);
1238 /* Make the search list */
1239 if (lwconf->searchnxt > 0)
1240 create_search_list(lwconf);
1241 else { /* No search list. Use the domain name if any */
1242 if (lwconf->domainname != NULL) {
1243 domain = make_searchlist_entry(lwconf->domainname);
1244 ISC_LIST_APPEND(search_list, domain, link);
1250 ndots = lwconf->ndots;
1251 debug("ndots is %d.", ndots);
1254 /* If user doesn't specify server use nameservers from resolv.conf. */
1255 if (ISC_LIST_EMPTY(server_list))
1256 copy_server_list(lwconf, &server_list);
1258 /* If we don't find a nameserver fall back to localhost */
1259 if (ISC_LIST_EMPTY(server_list)) {
1261 lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET);
1262 if (lwresult != ISC_R_SUCCESS)
1263 fatal("add_nameserver failed");
1266 lwresult = add_nameserver(lwconf, "::1", AF_INET6);
1267 if (lwresult != ISC_R_SUCCESS)
1268 fatal("add_nameserver failed");
1271 copy_server_list(lwconf, &server_list);
1278 if (keyfile[0] != 0)
1280 else if (keysecret[0] != 0)
1283 /* Setup the list of messages for +sigchase */
1284 ISC_LIST_INIT(chase_message_list);
1285 ISC_LIST_INIT(chase_message_list2);
1286 dns_name_init(&chase_name, NULL);
1288 dns_name_init(&chase_current_name, NULL);
1289 dns_name_init(&chase_authority_name, NULL);
1292 dns_name_init(&chase_signame, NULL);
1300 * Override the search list derived from resolv.conf by 'domain'.
1303 set_search_domain(char *domain) {
1304 dig_searchlist_t *search;
1307 search = make_searchlist_entry(domain);
1308 ISC_LIST_APPEND(search_list, search, link);
1312 * Setup the ISC and DNS libraries for use by the system.
1316 isc_result_t result;
1317 isc_logconfig_t *logconfig = NULL;
1319 debug("setup_libs()");
1321 result = isc_net_probeipv4();
1322 if (result == ISC_R_SUCCESS)
1323 have_ipv4 = ISC_TRUE;
1325 result = isc_net_probeipv6();
1326 if (result == ISC_R_SUCCESS)
1327 have_ipv6 = ISC_TRUE;
1328 if (!have_ipv6 && !have_ipv4)
1329 fatal("can't find either v4 or v6 networking");
1331 result = isc_mem_create(0, 0, &mctx);
1332 check_result(result, "isc_mem_create");
1333 isc_mem_setname(mctx, "dig", NULL);
1335 result = isc_log_create(mctx, &lctx, &logconfig);
1336 check_result(result, "isc_log_create");
1338 isc_log_setcontext(lctx);
1340 dns_log_setcontext(lctx);
1342 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
1343 check_result(result, "isc_log_usechannel");
1345 isc_log_setdebuglevel(lctx, 0);
1347 result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
1348 check_result(result, "isc_taskmgr_create");
1350 result = isc_task_create(taskmgr, 0, &global_task);
1351 check_result(result, "isc_task_create");
1352 isc_task_setname(global_task, "dig", NULL);
1354 result = isc_timermgr_create(mctx, &timermgr);
1355 check_result(result, "isc_timermgr_create");
1357 result = isc_socketmgr_create(mctx, &socketmgr);
1358 check_result(result, "isc_socketmgr_create");
1360 result = isc_entropy_create(mctx, &entp);
1361 check_result(result, "isc_entropy_create");
1363 result = dst_lib_init(mctx, entp, 0);
1364 check_result(result, "dst_lib_init");
1365 is_dst_up = ISC_TRUE;
1367 result = isc_mempool_create(mctx, COMMSIZE, &commctx);
1368 check_result(result, "isc_mempool_create");
1369 isc_mempool_setname(commctx, "COMMPOOL");
1371 * 6 and 2 set as reasonable parameters for 3 or 4 nameserver
1374 isc_mempool_setfreemax(commctx, 6);
1375 isc_mempool_setfillcount(commctx, 2);
1377 result = isc_mutex_init(&lookup_lock);
1378 check_result(result, "isc_mutex_init");
1380 dns_result_register();
1384 * Add EDNS0 option record to a message. Currently, the only supported
1385 * options are UDP buffer size, the DO bit, and NSID request.
1388 add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns,
1389 isc_boolean_t dnssec, isc_boolean_t nsid)
1391 dns_rdataset_t *rdataset = NULL;
1392 dns_rdatalist_t *rdatalist = NULL;
1393 dns_rdata_t *rdata = NULL;
1394 isc_result_t result;
1397 result = dns_message_gettemprdataset(msg, &rdataset);
1398 check_result(result, "dns_message_gettemprdataset");
1399 dns_rdataset_init(rdataset);
1400 result = dns_message_gettemprdatalist(msg, &rdatalist);
1401 check_result(result, "dns_message_gettemprdatalist");
1402 result = dns_message_gettemprdata(msg, &rdata);
1403 check_result(result, "dns_message_gettemprdata");
1405 debug("setting udp size of %d", udpsize);
1406 rdatalist->type = dns_rdatatype_opt;
1407 rdatalist->covers = 0;
1408 rdatalist->rdclass = udpsize;
1409 rdatalist->ttl = edns << 16;
1411 rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
1413 isc_buffer_t *b = NULL;
1415 result = isc_buffer_allocate(mctx, &b, 4);
1416 check_result(result, "isc_buffer_allocate");
1417 isc_buffer_putuint16(b, DNS_OPT_NSID);
1418 isc_buffer_putuint16(b, 0);
1419 rdata->data = isc_buffer_base(b);
1420 rdata->length = isc_buffer_usedlength(b);
1421 dns_message_takebuffer(msg, &b);
1426 ISC_LIST_INIT(rdatalist->rdata);
1427 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1428 dns_rdatalist_tordataset(rdatalist, rdataset);
1429 result = dns_message_setopt(msg, rdataset);
1430 check_result(result, "dns_message_setopt");
1434 * Add a question section to a message, asking for the specified name,
1438 add_question(dns_message_t *message, dns_name_t *name,
1439 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype)
1441 dns_rdataset_t *rdataset;
1442 isc_result_t result;
1444 debug("add_question()");
1446 result = dns_message_gettemprdataset(message, &rdataset);
1447 check_result(result, "dns_message_gettemprdataset()");
1448 dns_rdataset_init(rdataset);
1449 dns_rdataset_makequestion(rdataset, rdclass, rdtype);
1450 ISC_LIST_APPEND(name->list, rdataset, link);
1454 * Check if we're done with all the queued lookups, which is true iff
1455 * all sockets, sends, and recvs are accounted for (counters == 0),
1456 * and the lookup list is empty.
1457 * If we are done, pass control back out to dighost_shutdown() (which is
1458 * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
1459 * a whole or reseed the lookup list.
1462 check_if_done(void) {
1463 debug("check_if_done()");
1464 debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
1465 if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
1467 INSIST(sockcount == 0);
1468 INSIST(recvcount == 0);
1469 debug("shutting down");
1475 * Clear out a query when we're done with it. WARNING: This routine
1476 * WILL invalidate the query pointer.
1479 clear_query(dig_query_t *query) {
1480 dig_lookup_t *lookup;
1482 REQUIRE(query != NULL);
1484 debug("clear_query(%p)", query);
1486 lookup = query->lookup;
1488 if (lookup->current_query == query)
1489 lookup->current_query = NULL;
1491 if (ISC_LINK_LINKED(query, link))
1492 ISC_LIST_UNLINK(lookup->q, query, link);
1493 if (ISC_LINK_LINKED(query, clink))
1494 ISC_LIST_UNLINK(lookup->connecting, query, clink);
1495 if (ISC_LINK_LINKED(&query->recvbuf, link))
1496 ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf,
1498 if (ISC_LINK_LINKED(&query->lengthbuf, link))
1499 ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf,
1501 INSIST(query->recvspace != NULL);
1503 if (query->sock != NULL) {
1504 isc_socket_detach(&query->sock);
1506 debug("sockcount=%d", sockcount);
1508 isc_mempool_put(commctx, query->recvspace);
1509 isc_buffer_invalidate(&query->recvbuf);
1510 isc_buffer_invalidate(&query->lengthbuf);
1511 if (query->waiting_senddone)
1512 query->pending_free = ISC_TRUE;
1514 isc_mem_free(mctx, query);
1518 * Try and clear out a lookup if we're done with it. Return ISC_TRUE if
1519 * the lookup was successfully cleared. If ISC_TRUE is returned, the
1520 * lookup pointer has been invalidated.
1522 static isc_boolean_t
1523 try_clear_lookup(dig_lookup_t *lookup) {
1526 REQUIRE(lookup != NULL);
1528 debug("try_clear_lookup(%p)", lookup);
1530 if (ISC_LIST_HEAD(lookup->q) != NULL ||
1531 ISC_LIST_HEAD(lookup->connecting) != NULL)
1534 q = ISC_LIST_HEAD(lookup->q);
1536 debug("query to %s still pending", q->servname);
1537 q = ISC_LIST_NEXT(q, link);
1540 q = ISC_LIST_HEAD(lookup->connecting);
1542 debug("query to %s still connecting",
1544 q = ISC_LIST_NEXT(q, clink);
1551 * At this point, we know there are no queries on the lookup,
1552 * so can make it go away also.
1554 destroy_lookup(lookup);
1559 destroy_lookup(dig_lookup_t *lookup) {
1564 s = ISC_LIST_HEAD(lookup->my_server_list);
1566 debug("freeing server %p belonging to %p", s, lookup);
1568 s = ISC_LIST_NEXT(s, link);
1569 ISC_LIST_DEQUEUE(lookup->my_server_list,
1570 (dig_server_t *)ptr, link);
1571 isc_mem_free(mctx, ptr);
1573 if (lookup->sendmsg != NULL)
1574 dns_message_destroy(&lookup->sendmsg);
1575 if (lookup->querysig != NULL) {
1576 debug("freeing buffer %p", lookup->querysig);
1577 isc_buffer_free(&lookup->querysig);
1579 if (lookup->timer != NULL)
1580 isc_timer_detach(&lookup->timer);
1581 if (lookup->sendspace != NULL)
1582 isc_mempool_put(commctx, lookup->sendspace);
1584 if (lookup->tsigctx != NULL)
1585 dst_context_destroy(&lookup->tsigctx);
1587 isc_mem_free(mctx, lookup);
1591 * If we can, start the next lookup in the queue running.
1592 * This assumes that the lookup on the head of the queue hasn't been
1593 * started yet. It also removes the lookup from the head of the queue,
1594 * setting the current_lookup pointer pointing to it.
1597 start_lookup(void) {
1598 debug("start_lookup()");
1603 * If there's a current lookup running, we really shouldn't get
1606 INSIST(current_lookup == NULL);
1608 current_lookup = ISC_LIST_HEAD(lookup_list);
1610 * Put the current lookup somewhere so cancel_all can find it
1612 if (current_lookup != NULL) {
1613 ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
1615 if (current_lookup->do_topdown &&
1616 !current_lookup->rdtype_sigchaseset) {
1617 dst_key_t *trustedkey = NULL;
1618 isc_buffer_t *b = NULL;
1620 isc_result_t result;
1621 dns_name_t query_name;
1622 dns_name_t *key_name;
1625 result = get_trusted_key(mctx);
1626 if (result != ISC_R_SUCCESS) {
1627 printf("\n;; No trusted key, "
1628 "+sigchase option is disabled\n");
1629 current_lookup->sigchase = ISC_FALSE;
1632 dns_name_init(&query_name, NULL);
1633 nameFromString(current_lookup->textname, &query_name);
1635 for (i = 0; i < tk_list.nb_tk; i++) {
1636 key_name = dst_key_name(tk_list.key[i]);
1638 if (dns_name_issubdomain(&query_name,
1639 key_name) == ISC_TRUE)
1640 trustedkey = tk_list.key[i];
1642 * Verify temp is really the lowest
1646 if (trustedkey == NULL) {
1647 printf("\n;; The queried zone: ");
1648 dns_name_print(&query_name, stdout);
1649 printf(" isn't a subdomain of any Trusted Keys"
1650 ": +sigchase option is disable\n");
1651 current_lookup->sigchase = ISC_FALSE;
1652 free_name(&query_name, mctx);
1655 free_name(&query_name, mctx);
1657 current_lookup->rdtype_sigchase
1658 = current_lookup->rdtype;
1659 current_lookup->rdtype_sigchaseset
1660 = current_lookup->rdtypeset;
1661 current_lookup->rdtype = dns_rdatatype_ns;
1663 current_lookup->qrdtype_sigchase
1664 = current_lookup->qrdtype;
1665 current_lookup->qrdtype = dns_rdatatype_ns;
1667 current_lookup->rdclass_sigchase
1668 = current_lookup->rdclass;
1669 current_lookup->rdclass_sigchaseset
1670 = current_lookup->rdclassset;
1671 current_lookup->rdclass = dns_rdataclass_in;
1673 strlcpy(current_lookup->textnamesigchase,
1674 current_lookup->textname, MXNAME);
1676 current_lookup->trace_root_sigchase = ISC_TRUE;
1678 result = isc_buffer_allocate(mctx, &b, BUFSIZE);
1679 check_result(result, "isc_buffer_allocate");
1680 result = dns_name_totext(dst_key_name(trustedkey),
1682 check_result(result, "dns_name_totext");
1683 isc_buffer_usedregion(b, &r);
1684 r.base[r.length] = '\0';
1685 strlcpy(current_lookup->textname, (char*)r.base,
1687 isc_buffer_free(&b);
1689 nameFromString(current_lookup->textnamesigchase,
1692 dns_name_init(&chase_authority_name, NULL);
1696 setup_lookup(current_lookup);
1697 do_lookup(current_lookup);
1704 * If we can, clear the current lookup and start the next one running.
1705 * This calls try_clear_lookup, so may invalidate the lookup pointer.
1708 check_next_lookup(dig_lookup_t *lookup) {
1712 debug("check_next_lookup(%p)", lookup);
1714 if (ISC_LIST_HEAD(lookup->q) != NULL) {
1715 debug("still have a worker");
1718 if (try_clear_lookup(lookup)) {
1719 current_lookup = NULL;
1725 * Create and queue a new lookup as a followup to the current lookup,
1726 * based on the supplied message and section. This is used in trace and
1727 * name server search modes to start a new lookup using servers from
1728 * NS records in a reply. Returns the number of followup lookups made.
1731 followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section)
1733 dig_lookup_t *lookup = NULL;
1734 dig_server_t *srv = NULL;
1735 dns_rdataset_t *rdataset = NULL;
1736 dns_rdata_t rdata = DNS_RDATA_INIT;
1737 dns_name_t *name = NULL;
1738 isc_result_t result;
1739 isc_boolean_t success = ISC_FALSE;
1742 isc_result_t lresult, addresses_result;
1743 char bad_namestr[DNS_NAME_FORMATSIZE];
1745 isc_boolean_t horizontal = ISC_FALSE, bad = ISC_FALSE;
1749 debug("following up %s", query->lookup->textname);
1751 addresses_result = ISC_R_SUCCESS;
1752 bad_namestr[0] = '\0';
1753 for (result = dns_message_firstname(msg, section);
1754 result == ISC_R_SUCCESS;
1755 result = dns_message_nextname(msg, section)) {
1757 dns_message_currentname(msg, section, &name);
1759 if (section == DNS_SECTION_AUTHORITY) {
1761 result = dns_message_findtype(name, dns_rdatatype_soa,
1763 if (result == ISC_R_SUCCESS)
1767 result = dns_message_findtype(name, dns_rdatatype_ns, 0,
1769 if (result != ISC_R_SUCCESS)
1772 debug("found NS set");
1774 if (query->lookup->trace && !query->lookup->trace_root) {
1775 dns_namereln_t namereln;
1776 unsigned int nlabels;
1779 domain = dns_fixedname_name(&query->lookup->fdomain);
1780 namereln = dns_name_fullcompare(name, domain,
1782 if (namereln == dns_namereln_equal) {
1784 printf(";; BAD (HORIZONTAL) REFERRAL\n");
1785 horizontal = ISC_TRUE;
1786 } else if (namereln != dns_namereln_subdomain) {
1788 printf(";; BAD REFERRAL\n");
1794 for (result = dns_rdataset_first(rdataset);
1795 result == ISC_R_SUCCESS;
1796 result = dns_rdataset_next(rdataset)) {
1797 char namestr[DNS_NAME_FORMATSIZE];
1800 if (query->lookup->trace_root &&
1801 query->lookup->nsfound >= MXSERV)
1804 dns_rdataset_current(rdataset, &rdata);
1806 query->lookup->nsfound++;
1807 result = dns_rdata_tostruct(&rdata, &ns, NULL);
1808 check_result(result, "dns_rdata_tostruct");
1809 dns_name_format(&ns.name, namestr, sizeof(namestr));
1810 dns_rdata_freestruct(&ns);
1812 /* Initialize lookup if we've not yet */
1813 debug("found NS %s", namestr);
1817 lookup = requeue_lookup(query->lookup,
1819 cancel_lookup(query->lookup);
1820 lookup->doing_xfr = ISC_FALSE;
1821 if (!lookup->trace_root &&
1822 section == DNS_SECTION_ANSWER)
1823 lookup->trace = ISC_FALSE;
1825 lookup->trace = query->lookup->trace;
1826 lookup->ns_search_only =
1827 query->lookup->ns_search_only;
1828 lookup->trace_root = ISC_FALSE;
1829 if (lookup->ns_search_only)
1830 lookup->recurse = ISC_FALSE;
1831 domain = dns_fixedname_name(&lookup->fdomain);
1832 dns_name_copy(name, domain, NULL);
1834 debug("adding server %s", namestr);
1835 num = getaddresses(lookup, namestr, &lresult);
1836 if (lresult != ISC_R_SUCCESS) {
1837 debug("couldn't get address for '%s': %s",
1838 namestr, isc_result_totext(lresult));
1839 if (addresses_result == ISC_R_SUCCESS) {
1840 addresses_result = lresult;
1841 strcpy(bad_namestr, namestr);
1845 dns_rdata_reset(&rdata);
1848 if (numLookups == 0 && addresses_result != ISC_R_SUCCESS) {
1849 fatal("couldn't get address for '%s': %s",
1850 bad_namestr, isc_result_totext(result));
1853 if (lookup == NULL &&
1854 section == DNS_SECTION_ANSWER &&
1855 (query->lookup->trace || query->lookup->ns_search_only))
1856 return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY));
1859 * Randomize the order the nameserver will be tried.
1861 if (numLookups > 1) {
1863 dig_serverlist_t my_server_list;
1866 ISC_LIST_INIT(my_server_list);
1869 for (srv = ISC_LIST_HEAD(lookup->my_server_list);
1871 srv = ISC_LIST_HEAD(lookup->my_server_list)) {
1875 next = ISC_LIST_NEXT(srv, link);
1876 while (j-- > 0 && next != NULL) {
1878 next = ISC_LIST_NEXT(srv, link);
1880 ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link);
1881 ISC_LIST_APPEND(my_server_list, srv, link);
1884 ISC_LIST_APPENDLIST(lookup->my_server_list,
1885 my_server_list, link);
1888 return (numLookups);
1892 * Create and queue a new lookup using the next origin from the search
1893 * list, read in setup_system().
1895 * Return ISC_TRUE iff there was another searchlist entry.
1897 static isc_boolean_t
1898 next_origin(dig_query_t *query) {
1899 dig_lookup_t *lookup;
1900 dig_searchlist_t *search;
1901 dns_fixedname_t fixed;
1903 isc_result_t result;
1907 debug("next_origin()");
1908 debug("following up %s", query->lookup->textname);
1912 * We're not using a search list, so don't even think
1913 * about finding the next entry.
1918 * Check for a absolute name or ndots being met.
1920 dns_fixedname_init(&fixed);
1921 name = dns_fixedname_name(&fixed);
1922 result = dns_name_fromstring2(name, query->lookup->textname, NULL,
1924 if (result == ISC_R_SUCCESS &&
1925 (dns_name_isabsolute(name) ||
1926 (int)dns_name_countlabels(name) > ndots))
1929 if (query->lookup->origin == NULL && !query->lookup->need_search)
1931 * Then we just did rootorg; there's nothing left.
1934 if (query->lookup->origin == NULL && query->lookup->need_search) {
1935 lookup = requeue_lookup(query->lookup, ISC_TRUE);
1936 lookup->origin = ISC_LIST_HEAD(search_list);
1937 lookup->need_search = ISC_FALSE;
1939 search = ISC_LIST_NEXT(query->lookup->origin, link);
1940 if (search == NULL && query->lookup->done_as_is)
1942 lookup = requeue_lookup(query->lookup, ISC_TRUE);
1943 lookup->origin = search;
1945 cancel_lookup(query->lookup);
1950 * Insert an SOA record into the sendmessage in a lookup. Used for
1951 * creating IXFR queries.
1954 insert_soa(dig_lookup_t *lookup) {
1955 isc_result_t result;
1956 dns_rdata_soa_t soa;
1957 dns_rdata_t *rdata = NULL;
1958 dns_rdatalist_t *rdatalist = NULL;
1959 dns_rdataset_t *rdataset = NULL;
1960 dns_name_t *soaname = NULL;
1962 debug("insert_soa()");
1964 soa.serial = lookup->ixfr_serial;
1969 soa.common.rdclass = lookup->rdclass;
1970 soa.common.rdtype = dns_rdatatype_soa;
1972 dns_name_init(&soa.origin, NULL);
1973 dns_name_init(&soa.contact, NULL);
1975 dns_name_clone(dns_rootname, &soa.origin);
1976 dns_name_clone(dns_rootname, &soa.contact);
1978 isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
1979 sizeof(lookup->rdatastore));
1981 result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
1982 check_result(result, "dns_message_gettemprdata");
1984 result = dns_rdata_fromstruct(rdata, lookup->rdclass,
1985 dns_rdatatype_soa, &soa,
1987 check_result(result, "isc_rdata_fromstruct");
1989 result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
1990 check_result(result, "dns_message_gettemprdatalist");
1992 result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
1993 check_result(result, "dns_message_gettemprdataset");
1995 dns_rdatalist_init(rdatalist);
1996 rdatalist->type = dns_rdatatype_soa;
1997 rdatalist->rdclass = lookup->rdclass;
1998 rdatalist->covers = 0;
2000 ISC_LIST_INIT(rdatalist->rdata);
2001 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
2003 dns_rdataset_init(rdataset);
2004 dns_rdatalist_tordataset(rdatalist, rdataset);
2006 result = dns_message_gettempname(lookup->sendmsg, &soaname);
2007 check_result(result, "dns_message_gettempname");
2008 dns_name_init(soaname, NULL);
2009 dns_name_clone(lookup->name, soaname);
2010 ISC_LIST_INIT(soaname->list);
2011 ISC_LIST_APPEND(soaname->list, rdataset, link);
2012 dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
2016 * Setup the supplied lookup structure, making it ready to start sending
2017 * queries to servers. Create and initialize the message to be sent as
2018 * well as the query structures and buffer space for the replies. If the
2019 * server list is empty, clone it from the system default list.
2022 setup_lookup(dig_lookup_t *lookup) {
2023 isc_result_t result;
2029 dns_compress_t cctx;
2033 char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME];
2037 result = dns_name_settotextfilter(output_filter);
2038 check_result(result, "dns_name_settotextfilter");
2041 REQUIRE(lookup != NULL);
2044 debug("setup_lookup(%p)", lookup);
2046 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
2048 check_result(result, "dns_message_create");
2050 if (lookup->new_search) {
2051 debug("resetting lookup counter.");
2055 if (ISC_LIST_EMPTY(lookup->my_server_list)) {
2056 debug("cloning server list");
2057 clone_server_list(server_list, &lookup->my_server_list);
2059 result = dns_message_gettempname(lookup->sendmsg, &lookup->name);
2060 check_result(result, "dns_message_gettempname");
2061 dns_name_init(lookup->name, NULL);
2063 isc_buffer_init(&lookup->namebuf, lookup->namespace,
2064 sizeof(lookup->namespace));
2065 isc_buffer_init(&lookup->onamebuf, lookup->onamespace,
2066 sizeof(lookup->onamespace));
2070 * We cannot convert `textname' and `origin' separately.
2071 * `textname' doesn't contain TLD, but local mapping needs
2074 mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname,
2075 utf8_textname, sizeof(utf8_textname));
2076 idn_check_result(mr, "convert textname to UTF-8");
2080 * If the name has too many dots, force the origin to be NULL
2081 * (which produces an absolute lookup). Otherwise, take the origin
2082 * we have if there's one in the struct already. If it's NULL,
2083 * take the first entry in the searchlist iff either usesearch
2084 * is TRUE or we got a domain line in the resolv.conf file.
2086 if (lookup->new_search) {
2088 if ((count_dots(utf8_textname) >= ndots) || !usesearch) {
2089 lookup->origin = NULL; /* Force abs lookup */
2090 lookup->done_as_is = ISC_TRUE;
2091 lookup->need_search = usesearch;
2092 } else if (lookup->origin == NULL && usesearch) {
2093 lookup->origin = ISC_LIST_HEAD(search_list);
2094 lookup->need_search = ISC_FALSE;
2097 if ((count_dots(lookup->textname) >= ndots) || !usesearch) {
2098 lookup->origin = NULL; /* Force abs lookup */
2099 lookup->done_as_is = ISC_TRUE;
2100 lookup->need_search = usesearch;
2101 } else if (lookup->origin == NULL && usesearch) {
2102 lookup->origin = ISC_LIST_HEAD(search_list);
2103 lookup->need_search = ISC_FALSE;
2109 if (lookup->origin != NULL) {
2110 mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP,
2111 lookup->origin->origin, utf8_origin,
2112 sizeof(utf8_origin));
2113 idn_check_result(mr, "convert origin to UTF-8");
2114 mr = append_textname(utf8_textname, utf8_origin,
2115 sizeof(utf8_textname));
2116 idn_check_result(mr, "append origin to textname");
2118 mr = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP |
2119 IDN_IDNCONV | IDN_LENCHECK, utf8_textname,
2120 idn_textname, sizeof(idn_textname));
2121 idn_check_result(mr, "convert UTF-8 textname to IDN encoding");
2123 if (lookup->origin != NULL) {
2124 debug("trying origin %s", lookup->origin->origin);
2125 result = dns_message_gettempname(lookup->sendmsg,
2127 check_result(result, "dns_message_gettempname");
2128 dns_name_init(lookup->oname, NULL);
2129 /* XXX Helper funct to conv char* to name? */
2130 len = strlen(lookup->origin->origin);
2131 isc_buffer_init(&b, lookup->origin->origin, len);
2132 isc_buffer_add(&b, len);
2133 result = dns_name_fromtext(lookup->oname, &b, dns_rootname,
2134 0, &lookup->onamebuf);
2135 if (result != ISC_R_SUCCESS) {
2136 dns_message_puttempname(lookup->sendmsg,
2138 dns_message_puttempname(lookup->sendmsg,
2140 fatal("'%s' is not in legal name syntax (%s)",
2141 lookup->origin->origin,
2142 isc_result_totext(result));
2144 if (lookup->trace && lookup->trace_root) {
2145 dns_name_clone(dns_rootname, lookup->name);
2147 len = strlen(lookup->textname);
2148 isc_buffer_init(&b, lookup->textname, len);
2149 isc_buffer_add(&b, len);
2150 result = dns_name_fromtext(lookup->name, &b,
2154 if (result != ISC_R_SUCCESS) {
2155 dns_message_puttempname(lookup->sendmsg,
2157 dns_message_puttempname(lookup->sendmsg,
2159 fatal("'%s' is not in legal name syntax (%s)",
2160 lookup->textname, isc_result_totext(result));
2162 dns_message_puttempname(lookup->sendmsg, &lookup->oname);
2166 debug("using root origin");
2167 if (lookup->trace && lookup->trace_root)
2168 dns_name_clone(dns_rootname, lookup->name);
2171 len = strlen(idn_textname);
2172 isc_buffer_init(&b, idn_textname, len);
2173 isc_buffer_add(&b, len);
2174 result = dns_name_fromtext(lookup->name, &b,
2178 len = strlen(lookup->textname);
2179 isc_buffer_init(&b, lookup->textname, len);
2180 isc_buffer_add(&b, len);
2181 result = dns_name_fromtext(lookup->name, &b,
2186 if (result != ISC_R_SUCCESS) {
2187 dns_message_puttempname(lookup->sendmsg,
2189 isc_buffer_init(&b, store, MXNAME);
2190 fatal("'%s' is not a legal name "
2191 "(%s)", lookup->textname,
2192 isc_result_totext(result));
2195 dns_name_format(lookup->name, store, sizeof(store));
2196 trying(store, lookup);
2197 INSIST(dns_name_isabsolute(lookup->name));
2199 isc_random_get(&id);
2200 lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
2201 lookup->sendmsg->opcode = dns_opcode_query;
2202 lookup->msgcounter = 0;
2204 * If this is a trace request, completely disallow recursion, since
2205 * it's meaningless for traces.
2207 if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root))
2208 lookup->recurse = ISC_FALSE;
2210 if (lookup->recurse &&
2211 lookup->rdtype != dns_rdatatype_axfr &&
2212 lookup->rdtype != dns_rdatatype_ixfr) {
2213 debug("recursive query");
2214 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD;
2218 if (lookup->aaonly) {
2220 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA;
2223 if (lookup->adflag) {
2225 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD;
2228 if (lookup->cdflag) {
2230 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD;
2233 dns_message_addname(lookup->sendmsg, lookup->name,
2234 DNS_SECTION_QUESTION);
2236 if (lookup->trace && lookup->trace_root) {
2237 lookup->qrdtype = lookup->rdtype;
2238 lookup->rdtype = dns_rdatatype_ns;
2241 if ((lookup->rdtype == dns_rdatatype_axfr) ||
2242 (lookup->rdtype == dns_rdatatype_ixfr)) {
2244 * Force TCP mode if we're doing an axfr.
2246 if (lookup->rdtype == dns_rdatatype_axfr) {
2247 lookup->doing_xfr = ISC_TRUE;
2248 lookup->tcp_mode = ISC_TRUE;
2249 } else if (lookup->tcp_mode) {
2250 lookup->doing_xfr = ISC_TRUE;
2254 add_question(lookup->sendmsg, lookup->name, lookup->rdclass,
2258 if (lookup->rdtype == dns_rdatatype_ixfr)
2261 /* XXX Insist this? */
2262 lookup->tsigctx = NULL;
2263 lookup->querysig = NULL;
2265 debug("initializing keys");
2266 result = dns_message_settsigkey(lookup->sendmsg, key);
2267 check_result(result, "dns_message_settsigkey");
2270 lookup->sendspace = isc_mempool_get(commctx);
2271 if (lookup->sendspace == NULL)
2272 fatal("memory allocation failure");
2274 result = dns_compress_init(&cctx, -1, mctx);
2275 check_result(result, "dns_compress_init");
2277 debug("starting to render the message");
2278 isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE);
2279 result = dns_message_renderbegin(lookup->sendmsg, &cctx,
2280 &lookup->renderbuf);
2281 check_result(result, "dns_message_renderbegin");
2282 if (lookup->udpsize > 0 || lookup->dnssec || lookup->edns > -1) {
2283 if (lookup->udpsize == 0)
2284 lookup->udpsize = 4096;
2285 if (lookup->edns < 0)
2287 add_opt(lookup->sendmsg, lookup->udpsize,
2288 lookup->edns, lookup->dnssec, lookup->nsid);
2291 result = dns_message_rendersection(lookup->sendmsg,
2292 DNS_SECTION_QUESTION, 0);
2293 check_result(result, "dns_message_rendersection");
2294 result = dns_message_rendersection(lookup->sendmsg,
2295 DNS_SECTION_AUTHORITY, 0);
2296 check_result(result, "dns_message_rendersection");
2297 result = dns_message_renderend(lookup->sendmsg);
2298 check_result(result, "dns_message_renderend");
2299 debug("done rendering");
2301 dns_compress_invalidate(&cctx);
2304 * Force TCP mode if the request is larger than 512 bytes.
2306 if (isc_buffer_usedlength(&lookup->renderbuf) > 512)
2307 lookup->tcp_mode = ISC_TRUE;
2309 lookup->pending = ISC_FALSE;
2311 for (serv = ISC_LIST_HEAD(lookup->my_server_list);
2313 serv = ISC_LIST_NEXT(serv, link)) {
2314 query = isc_mem_allocate(mctx, sizeof(dig_query_t));
2316 fatal("memory allocation failure in %s:%d",
2317 __FILE__, __LINE__);
2318 debug("create query %p linked to lookup %p",
2320 query->lookup = lookup;
2321 query->waiting_connect = ISC_FALSE;
2322 query->waiting_senddone = ISC_FALSE;
2323 query->pending_free = ISC_FALSE;
2324 query->recv_made = ISC_FALSE;
2325 query->first_pass = ISC_TRUE;
2326 query->first_soa_rcvd = ISC_FALSE;
2327 query->second_rr_rcvd = ISC_FALSE;
2328 query->first_repeat_rcvd = ISC_FALSE;
2329 query->warn_id = ISC_TRUE;
2330 query->first_rr_serial = 0;
2331 query->second_rr_serial = 0;
2332 query->servname = serv->servername;
2333 query->userarg = serv->userarg;
2334 query->rr_count = 0;
2335 query->msg_count = 0;
2336 query->byte_count = 0;
2337 query->ixfr_axfr = ISC_FALSE;
2338 ISC_LIST_INIT(query->recvlist);
2339 ISC_LIST_INIT(query->lengthlist);
2341 query->recvspace = isc_mempool_get(commctx);
2342 if (query->recvspace == NULL)
2343 fatal("memory allocation failure");
2345 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
2346 isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
2347 isc_buffer_init(&query->slbuf, query->slspace, 2);
2348 query->sendbuf = lookup->renderbuf;
2350 ISC_LINK_INIT(query, clink);
2351 ISC_LINK_INIT(query, link);
2352 ISC_LIST_ENQUEUE(lookup->q, query, link);
2354 /* XXX qrflag, print_query, etc... */
2355 if (!ISC_LIST_EMPTY(lookup->q) && qr) {
2357 printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg,
2363 * Event handler for send completion. Track send counter, and clear out
2364 * the query if the send was canceled.
2367 send_done(isc_task_t *_task, isc_event_t *event) {
2368 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
2369 isc_buffer_t *b = NULL;
2370 dig_query_t *query, *next;
2373 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
2379 debug("send_done()");
2381 debug("sendcount=%d", sendcount);
2382 INSIST(sendcount >= 0);
2384 for (b = ISC_LIST_HEAD(sevent->bufferlist);
2386 b = ISC_LIST_HEAD(sevent->bufferlist)) {
2387 ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2388 isc_mem_free(mctx, b);
2391 query = event->ev_arg;
2392 query->waiting_senddone = ISC_FALSE;
2395 if (l->ns_search_only && !l->trace_root && !l->tcp_mode) {
2396 debug("sending next, since searching");
2397 next = ISC_LIST_NEXT(query, link);
2402 isc_event_free(&event);
2404 if (query->pending_free)
2405 isc_mem_free(mctx, query);
2412 * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
2413 * IO sockets. The cancel handlers should take care of cleaning up the
2414 * query and lookup structures
2417 cancel_lookup(dig_lookup_t *lookup) {
2418 dig_query_t *query, *next;
2420 debug("cancel_lookup()");
2421 query = ISC_LIST_HEAD(lookup->q);
2422 while (query != NULL) {
2423 next = ISC_LIST_NEXT(query, link);
2424 if (query->sock != NULL) {
2425 isc_socket_cancel(query->sock, global_task,
2426 ISC_SOCKCANCEL_ALL);
2433 if (lookup->timer != NULL)
2434 isc_timer_detach(&lookup->timer);
2435 lookup->pending = ISC_FALSE;
2436 lookup->retries = 0;
2440 bringup_timer(dig_query_t *query, unsigned int default_timeout) {
2442 unsigned int local_timeout;
2443 isc_result_t result;
2445 debug("bringup_timer()");
2447 * If the timer already exists, that means we're calling this
2448 * a second time (for a retry). Don't need to recreate it,
2452 if (ISC_LIST_NEXT(query, link) != NULL)
2453 local_timeout = SERVER_TIMEOUT;
2456 local_timeout = default_timeout;
2458 local_timeout = timeout;
2460 debug("have local timeout of %d", local_timeout);
2461 isc_interval_set(&l->interval, local_timeout, 0);
2462 if (l->timer != NULL)
2463 isc_timer_detach(&l->timer);
2464 result = isc_timer_create(timermgr, isc_timertype_once, NULL,
2465 &l->interval, global_task, connect_timeout,
2467 check_result(result, "isc_timer_create");
2471 force_timeout(dig_lookup_t *l, dig_query_t *query) {
2474 debug("force_timeout ()");
2475 event = isc_event_allocate(mctx, query, ISC_TIMEREVENT_IDLE,
2477 sizeof(isc_event_t));
2478 if (event == NULL) {
2479 fatal("isc_event_allocate: %s",
2480 isc_result_totext(ISC_R_NOMEMORY));
2482 isc_task_send(global_task, &event);
2485 * The timer may have expired if, for example, get_address() takes
2486 * long time and the timer was running on a different thread.
2487 * We need to cancel the possible timeout event not to confuse
2488 * ourselves due to the duplicate events.
2490 if (l->timer != NULL)
2491 isc_timer_detach(&l->timer);
2496 connect_done(isc_task_t *task, isc_event_t *event);
2499 * Unlike send_udp, this can't be called multiple times with the same
2500 * query. When we retry TCP, we requeue the whole lookup, which should
2504 send_tcp_connect(dig_query_t *query) {
2505 isc_result_t result;
2509 debug("send_tcp_connect(%p)", query);
2512 query->waiting_connect = ISC_TRUE;
2513 query->lookup->current_query = query;
2514 result = get_address(query->servname, port, &query->sockaddr);
2515 if (result != ISC_R_SUCCESS) {
2517 * This servname doesn't have an address. Try the next server
2518 * by triggering an immediate 'timeout' (we lie, but the effect
2521 force_timeout(l, query);
2525 if (specified_source &&
2526 (isc_sockaddr_pf(&query->sockaddr) !=
2527 isc_sockaddr_pf(&bind_address))) {
2528 printf(";; Skipping server %s, incompatible "
2529 "address family\n", query->servname);
2530 query->waiting_connect = ISC_FALSE;
2531 next = ISC_LIST_NEXT(query, link);
2535 printf(";; No acceptable nameservers\n");
2536 check_next_lookup(l);
2539 send_tcp_connect(next);
2543 INSIST(query->sock == NULL);
2545 if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) {
2547 isc_socket_attach(keep, &query->sock);
2548 query->waiting_connect = ISC_FALSE;
2549 launch_next_query(query, ISC_TRUE);
2553 result = isc_socket_create(socketmgr,
2554 isc_sockaddr_pf(&query->sockaddr),
2555 isc_sockettype_tcp, &query->sock);
2556 check_result(result, "isc_socket_create");
2558 debug("sockcount=%d", sockcount);
2559 if (specified_source)
2560 result = isc_socket_bind(query->sock, &bind_address,
2561 ISC_SOCKET_REUSEADDRESS);
2563 if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
2565 isc_sockaddr_any(&bind_any);
2567 isc_sockaddr_any6(&bind_any);
2568 result = isc_socket_bind(query->sock, &bind_any, 0);
2570 check_result(result, "isc_socket_bind");
2571 bringup_timer(query, TCP_TIMEOUT);
2572 result = isc_socket_connect(query->sock, &query->sockaddr,
2573 global_task, connect_done, query);
2574 check_result(result, "isc_socket_connect");
2577 * If we're at the endgame of a nameserver search, we need to
2578 * immediately bring up all the queries. Do it here.
2580 if (l->ns_search_only && !l->trace_root) {
2581 debug("sending next, since searching");
2582 next = ISC_LIST_NEXT(query, link);
2583 if (ISC_LINK_LINKED(query, link))
2584 ISC_LIST_DEQUEUE(l->q, query, link);
2585 ISC_LIST_ENQUEUE(l->connecting, query, clink);
2587 send_tcp_connect(next);
2591 static isc_buffer_t *
2592 clone_buffer(isc_buffer_t *source) {
2593 isc_buffer_t *buffer;
2594 buffer = isc_mem_allocate(mctx, sizeof(*buffer));
2596 fatal("memory allocation failure in %s:%d",
2597 __FILE__, __LINE__);
2603 * Send a UDP packet to the remote nameserver, possible starting the
2604 * recv action as well. Also make sure that the timer is running and
2605 * is properly reset.
2608 send_udp(dig_query_t *query) {
2609 dig_lookup_t *l = NULL;
2610 isc_result_t result;
2611 isc_buffer_t *sendbuf;
2613 debug("send_udp(%p)", query);
2616 bringup_timer(query, UDP_TIMEOUT);
2617 l->current_query = query;
2618 debug("working on lookup %p, query %p", query->lookup, query);
2619 if (!query->recv_made) {
2620 /* XXX Check the sense of this, need assertion? */
2621 query->waiting_connect = ISC_FALSE;
2622 result = get_address(query->servname, port, &query->sockaddr);
2623 if (result != ISC_R_SUCCESS) {
2624 /* This servname doesn't have an address. */
2625 force_timeout(l, query);
2629 result = isc_socket_create(socketmgr,
2630 isc_sockaddr_pf(&query->sockaddr),
2631 isc_sockettype_udp, &query->sock);
2632 check_result(result, "isc_socket_create");
2634 debug("sockcount=%d", sockcount);
2635 if (specified_source) {
2636 result = isc_socket_bind(query->sock, &bind_address,
2637 ISC_SOCKET_REUSEADDRESS);
2639 isc_sockaddr_anyofpf(&bind_any,
2640 isc_sockaddr_pf(&query->sockaddr));
2641 result = isc_socket_bind(query->sock, &bind_any, 0);
2643 check_result(result, "isc_socket_bind");
2645 query->recv_made = ISC_TRUE;
2646 ISC_LINK_INIT(&query->recvbuf, link);
2647 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf,
2649 debug("recving with lookup=%p, query=%p, sock=%p",
2650 query->lookup, query, query->sock);
2651 result = isc_socket_recvv(query->sock, &query->recvlist, 1,
2652 global_task, recv_done, query);
2653 check_result(result, "isc_socket_recvv");
2655 debug("recvcount=%d", recvcount);
2657 ISC_LIST_INIT(query->sendlist);
2658 sendbuf = clone_buffer(&query->sendbuf);
2659 ISC_LIST_ENQUEUE(query->sendlist, sendbuf, link);
2660 debug("sending a request");
2661 TIME_NOW(&query->time_sent);
2662 INSIST(query->sock != NULL);
2663 query->waiting_senddone = ISC_TRUE;
2664 result = isc_socket_sendtov2(query->sock, &query->sendlist,
2665 global_task, send_done, query,
2666 &query->sockaddr, NULL,
2667 ISC_SOCKFLAG_NORETRY);
2668 check_result(result, "isc_socket_sendtov");
2673 * IO timeout handler, used for both connect and recv timeouts. If
2674 * retries are still allowed, either resend the UDP packet or queue a
2675 * new TCP lookup. Otherwise, cancel the lookup.
2678 connect_timeout(isc_task_t *task, isc_event_t *event) {
2679 dig_lookup_t *l = NULL;
2680 dig_query_t *query = NULL, *next, *cq;
2683 REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE);
2685 debug("connect_timeout()");
2689 query = l->current_query;
2690 isc_event_free(&event);
2694 if ((query != NULL) && (query->lookup->current_query != NULL) &&
2695 (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) {
2696 debug("trying next server...");
2697 cq = query->lookup->current_query;
2699 send_udp(ISC_LIST_NEXT(cq, link));
2701 if (query->sock != NULL)
2702 isc_socket_cancel(query->sock, NULL,
2703 ISC_SOCKCANCEL_ALL);
2704 next = ISC_LIST_NEXT(cq, link);
2706 send_tcp_connect(next);
2712 if (l->retries > 1) {
2715 debug("resending UDP request to first server");
2716 send_udp(ISC_LIST_HEAD(l->q));
2718 debug("making new TCP request, %d tries left",
2721 requeue_lookup(l, ISC_TRUE);
2723 check_next_lookup(l);
2726 fputs(l->cmdline, stdout);
2727 printf(";; connection timed out; no servers could be "
2730 check_next_lookup(l);
2738 * Event handler for the TCP recv which gets the length header of TCP
2739 * packets. Start the next recv of length bytes.
2742 tcp_length_done(isc_task_t *task, isc_event_t *event) {
2743 isc_socketevent_t *sevent;
2744 isc_buffer_t *b = NULL;
2745 isc_result_t result;
2746 dig_query_t *query = NULL;
2748 isc_uint16_t length;
2750 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
2755 debug("tcp_length_done()");
2758 sevent = (isc_socketevent_t *)event;
2759 query = event->ev_arg;
2762 INSIST(recvcount >= 0);
2764 b = ISC_LIST_HEAD(sevent->bufferlist);
2765 INSIST(b == &query->lengthbuf);
2766 ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2768 if (sevent->result == ISC_R_CANCELED) {
2769 isc_event_free(&event);
2772 check_next_lookup(l);
2776 if (sevent->result != ISC_R_SUCCESS) {
2777 char sockstr[ISC_SOCKADDR_FORMATSIZE];
2778 isc_sockaddr_format(&query->sockaddr, sockstr,
2780 printf(";; communications error to %s: %s\n",
2781 sockstr, isc_result_totext(sevent->result));
2783 isc_socket_detach(&query->sock);
2785 debug("sockcount=%d", sockcount);
2786 INSIST(sockcount >= 0);
2787 isc_event_free(&event);
2789 check_next_lookup(l);
2793 length = isc_buffer_getuint16(b);
2795 isc_event_free(&event);
2796 launch_next_query(query, ISC_FALSE);
2802 * Even though the buffer was already init'ed, we need
2803 * to redo it now, to force the length we want.
2805 isc_buffer_invalidate(&query->recvbuf);
2806 isc_buffer_init(&query->recvbuf, query->recvspace, length);
2807 ENSURE(ISC_LIST_EMPTY(query->recvlist));
2808 ISC_LINK_INIT(&query->recvbuf, link);
2809 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
2810 debug("recving with lookup=%p, query=%p", query->lookup, query);
2811 result = isc_socket_recvv(query->sock, &query->recvlist, length, task,
2813 check_result(result, "isc_socket_recvv");
2815 debug("resubmitted recv request with length %d, recvcount=%d",
2817 isc_event_free(&event);
2822 * For transfers that involve multiple recvs (XFR's in particular),
2823 * launch the next recv.
2826 launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
2827 isc_result_t result;
2829 isc_buffer_t *buffer;
2833 debug("launch_next_query()");
2835 if (!query->lookup->pending) {
2836 debug("ignoring launch_next_query because !pending");
2837 isc_socket_detach(&query->sock);
2839 debug("sockcount=%d", sockcount);
2840 INSIST(sockcount >= 0);
2841 query->waiting_connect = ISC_FALSE;
2844 check_next_lookup(l);
2848 isc_buffer_clear(&query->slbuf);
2849 isc_buffer_clear(&query->lengthbuf);
2850 isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->sendbuf.used);
2851 ISC_LIST_INIT(query->sendlist);
2852 ISC_LINK_INIT(&query->slbuf, link);
2853 if (!query->first_soa_rcvd) {
2854 buffer = clone_buffer(&query->slbuf);
2855 ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
2856 if (include_question) {
2857 buffer = clone_buffer(&query->sendbuf);
2858 ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
2862 ISC_LINK_INIT(&query->lengthbuf, link);
2863 ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
2865 result = isc_socket_recvv(query->sock, &query->lengthlist, 0,
2866 global_task, tcp_length_done, query);
2867 check_result(result, "isc_socket_recvv");
2869 debug("recvcount=%d", recvcount);
2870 if (!query->first_soa_rcvd) {
2871 debug("sending a request in launch_next_query");
2872 TIME_NOW(&query->time_sent);
2873 query->waiting_senddone = ISC_TRUE;
2874 result = isc_socket_sendv(query->sock, &query->sendlist,
2875 global_task, send_done, query);
2876 check_result(result, "isc_socket_sendv");
2878 debug("sendcount=%d", sendcount);
2880 query->waiting_connect = ISC_FALSE;
2882 check_next_lookup(query->lookup);
2888 * Event handler for TCP connect complete. Make sure the connection was
2889 * successful, then pass into launch_next_query to actually send the
2893 connect_done(isc_task_t *task, isc_event_t *event) {
2894 isc_socketevent_t *sevent = NULL;
2895 dig_query_t *query = NULL, *next;
2900 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
2903 debug("connect_done()");
2906 sevent = (isc_socketevent_t *)event;
2907 query = sevent->ev_arg;
2909 INSIST(query->waiting_connect);
2911 query->waiting_connect = ISC_FALSE;
2913 if (sevent->result == ISC_R_CANCELED) {
2914 debug("in cancel handler");
2915 isc_socket_detach(&query->sock);
2916 INSIST(sockcount > 0);
2918 debug("sockcount=%d", sockcount);
2919 query->waiting_connect = ISC_FALSE;
2920 isc_event_free(&event);
2923 check_next_lookup(l);
2927 if (sevent->result != ISC_R_SUCCESS) {
2928 char sockstr[ISC_SOCKADDR_FORMATSIZE];
2930 debug("unsuccessful connection: %s",
2931 isc_result_totext(sevent->result));
2932 isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
2933 if (sevent->result != ISC_R_CANCELED)
2934 printf(";; Connection to %s(%s) for %s failed: "
2936 query->servname, query->lookup->textname,
2937 isc_result_totext(sevent->result));
2938 isc_socket_detach(&query->sock);
2940 INSIST(sockcount >= 0);
2941 /* XXX Clean up exitcodes */
2944 debug("sockcount=%d", sockcount);
2945 query->waiting_connect = ISC_FALSE;
2946 isc_event_free(&event);
2948 if (l->current_query != NULL)
2949 next = ISC_LIST_NEXT(l->current_query, link);
2954 bringup_timer(next, TCP_TIMEOUT);
2955 send_tcp_connect(next);
2957 check_next_lookup(l);
2963 isc_socket_detach(&keep);
2964 isc_socket_attach(query->sock, &keep);
2965 keepaddr = query->sockaddr;
2967 launch_next_query(query, ISC_TRUE);
2968 isc_event_free(&event);
2973 * Check if the ongoing XFR needs more data before it's complete, using
2974 * the semantics of IXFR and AXFR protocols. Much of the complexity of
2975 * this routine comes from determining when an IXFR is complete.
2976 * ISC_FALSE means more data is on the way, and the recv has been issued.
2978 static isc_boolean_t
2979 check_for_more_data(dig_query_t *query, dns_message_t *msg,
2980 isc_socketevent_t *sevent)
2982 dns_rdataset_t *rdataset = NULL;
2983 dns_rdata_t rdata = DNS_RDATA_INIT;
2984 dns_rdata_soa_t soa;
2985 isc_uint32_t ixfr_serial = query->lookup->ixfr_serial, serial;
2986 isc_result_t result;
2987 isc_boolean_t ixfr = query->lookup->rdtype == dns_rdatatype_ixfr;
2988 isc_boolean_t axfr = query->lookup->rdtype == dns_rdatatype_axfr;
2991 axfr = query->ixfr_axfr;
2993 debug("check_for_more_data()");
2996 * By the time we're in this routine, we know we're doing
2997 * either an AXFR or IXFR. If there's no second_rr_type,
2998 * then we don't yet know which kind of answer we got back
2999 * from the server. Here, we're going to walk through the
3000 * rr's in the message, acting as necessary whenever we hit
3005 query->byte_count += sevent->n;
3006 result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
3007 if (result != ISC_R_SUCCESS) {
3008 puts("; Transfer failed.");
3014 dns_message_currentname(msg, DNS_SECTION_ANSWER,
3016 for (rdataset = ISC_LIST_HEAD(name->list);
3018 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3019 result = dns_rdataset_first(rdataset);
3020 if (result != ISC_R_SUCCESS)
3024 dns_rdata_reset(&rdata);
3025 dns_rdataset_current(rdataset, &rdata);
3027 * If this is the first rr, make sure
3030 if ((!query->first_soa_rcvd) &&
3031 (rdata.type != dns_rdatatype_soa)) {
3032 puts("; Transfer failed. "
3033 "Didn't start with SOA answer.");
3036 if ((!query->second_rr_rcvd) &&
3037 (rdata.type != dns_rdatatype_soa)) {
3038 query->second_rr_rcvd = ISC_TRUE;
3039 query->second_rr_serial = 0;
3040 debug("got the second rr as nonsoa");
3041 axfr = query->ixfr_axfr = ISC_TRUE;
3046 * If the record is anything except an SOA
3047 * now, just continue on...
3049 if (rdata.type != dns_rdatatype_soa)
3052 /* Now we have an SOA. Work with it. */
3053 debug("got an SOA");
3054 result = dns_rdata_tostruct(&rdata, &soa, NULL);
3055 check_result(result, "dns_rdata_tostruct");
3056 serial = soa.serial;
3057 dns_rdata_freestruct(&soa);
3058 if (!query->first_soa_rcvd) {
3059 query->first_soa_rcvd = ISC_TRUE;
3060 query->first_rr_serial = serial;
3061 debug("this is the first serial %u",
3063 if (ixfr && isc_serial_ge(ixfr_serial,
3065 debug("got up to date "
3072 debug("doing axfr, got second SOA");
3075 if (!query->second_rr_rcvd) {
3076 if (query->first_rr_serial == serial) {
3077 debug("doing ixfr, got "
3081 debug("this is the second serial %u",
3083 query->second_rr_rcvd = ISC_TRUE;
3084 query->second_rr_serial = serial;
3088 * If we get to this point, we're doing an
3089 * IXFR and have to start really looking
3090 * at serial numbers.
3092 if (query->first_rr_serial == serial) {
3093 debug("got a match for ixfr");
3094 if (!query->first_repeat_rcvd) {
3095 query->first_repeat_rcvd =
3099 debug("done with ixfr");
3102 debug("meaningless soa %u", serial);
3104 result = dns_rdataset_next(rdataset);
3105 } while (result == ISC_R_SUCCESS);
3107 result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
3108 } while (result == ISC_R_SUCCESS);
3109 launch_next_query(query, ISC_FALSE);
3112 received(sevent->n, &sevent->address, query);
3117 * Event handler for recv complete. Perform whatever actions are necessary,
3118 * based on the specifics of the user's request.
3121 recv_done(isc_task_t *task, isc_event_t *event) {
3122 isc_socketevent_t *sevent = NULL;
3123 dig_query_t *query = NULL;
3124 isc_buffer_t *b = NULL;
3125 dns_message_t *msg = NULL;
3127 dig_message_t *chase_msg = NULL;
3128 dig_message_t *chase_msg2 = NULL;
3130 isc_result_t result;
3131 dig_lookup_t *n, *l;
3132 isc_boolean_t docancel = ISC_FALSE;
3133 isc_boolean_t match = ISC_TRUE;
3134 unsigned int parseflags;
3136 unsigned int msgflags;
3138 isc_result_t do_sigchase = ISC_FALSE;
3140 dns_message_t *msg_temp = NULL;
3142 isc_buffer_t *buf = NULL;
3148 debug("recv_done()");
3152 debug("recvcount=%d", recvcount);
3153 INSIST(recvcount >= 0);
3155 query = event->ev_arg;
3156 debug("lookup=%p, query=%p", query->lookup, query);
3160 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
3161 sevent = (isc_socketevent_t *)event;
3163 b = ISC_LIST_HEAD(sevent->bufferlist);
3164 INSIST(b == &query->recvbuf);
3165 ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link);
3167 if ((l->tcp_mode) && (l->timer != NULL))
3168 isc_timer_touch(l->timer);
3169 if ((!l->pending && !l->ns_search_only) || cancel_now) {
3170 debug("no longer pending. Got %s",
3171 isc_result_totext(sevent->result));
3172 query->waiting_connect = ISC_FALSE;
3174 isc_event_free(&event);
3176 check_next_lookup(l);
3181 if (sevent->result != ISC_R_SUCCESS) {
3182 if (sevent->result == ISC_R_CANCELED) {
3183 debug("in recv cancel handler");
3184 query->waiting_connect = ISC_FALSE;
3186 printf(";; communications error: %s\n",
3187 isc_result_totext(sevent->result));
3188 isc_socket_detach(&query->sock);
3190 debug("sockcount=%d", sockcount);
3191 INSIST(sockcount >= 0);
3193 isc_event_free(&event);
3195 check_next_lookup(l);
3201 !isc_sockaddr_compare(&sevent->address, &query->sockaddr,
3202 ISC_SOCKADDR_CMPADDR|
3203 ISC_SOCKADDR_CMPPORT|
3204 ISC_SOCKADDR_CMPSCOPE|
3205 ISC_SOCKADDR_CMPSCOPEZERO)) {
3206 char buf1[ISC_SOCKADDR_FORMATSIZE];
3207 char buf2[ISC_SOCKADDR_FORMATSIZE];
3210 if (isc_sockaddr_pf(&query->sockaddr) == AF_INET)
3211 isc_sockaddr_any(&any);
3213 isc_sockaddr_any6(&any);
3216 * We don't expect a match when the packet is
3217 * sent to 0.0.0.0, :: or to a multicast addresses.
3218 * XXXMPA broadcast needs to be handled here as well.
3220 if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) &&
3221 !isc_sockaddr_ismulticast(&query->sockaddr)) ||
3222 isc_sockaddr_getport(&query->sockaddr) !=
3223 isc_sockaddr_getport(&sevent->address)) {
3224 isc_sockaddr_format(&sevent->address, buf1,
3226 isc_sockaddr_format(&query->sockaddr, buf2,
3228 printf(";; reply from unexpected source: %s,"
3229 " expected %s\n", buf1, buf2);
3234 result = dns_message_peekheader(b, &id, &msgflags);
3235 if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
3238 isc_boolean_t fail = ISC_TRUE;
3239 if (result == ISC_R_SUCCESS) {
3240 if (!query->first_soa_rcvd ||
3242 printf(";; %s: ID mismatch: "
3243 "expected ID %u, got %u\n",
3244 query->first_soa_rcvd ?
3245 "WARNING" : "ERROR",
3246 l->sendmsg->id, id);
3247 if (query->first_soa_rcvd)
3249 query->warn_id = ISC_FALSE;
3251 printf(";; ERROR: short "
3252 "(< header size) message\n");
3254 isc_event_free(&event);
3256 check_next_lookup(l);
3261 } else if (result == ISC_R_SUCCESS)
3262 printf(";; Warning: ID mismatch: "
3263 "expected ID %u, got %u\n", l->sendmsg->id, id);
3265 printf(";; Warning: short "
3266 "(< header size) message received\n");
3269 if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0)
3270 printf(";; Warning: query response not set\n");
3275 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
3276 check_result(result, "dns_message_create");
3279 if (l->querysig == NULL) {
3280 debug("getting initial querysig");
3281 result = dns_message_getquerytsig(l->sendmsg, mctx,
3283 check_result(result, "dns_message_getquerytsig");
3285 result = dns_message_setquerytsig(msg, l->querysig);
3286 check_result(result, "dns_message_setquerytsig");
3287 result = dns_message_settsigkey(msg, key);
3288 check_result(result, "dns_message_settsigkey");
3289 msg->tsigctx = l->tsigctx;
3291 if (l->msgcounter != 0)
3292 msg->tcp_continuation = 1;
3296 debug("before parse starts");
3297 parseflags = DNS_MESSAGEPARSE_PRESERVEORDER;
3300 do_sigchase = ISC_FALSE;
3303 do_sigchase = ISC_TRUE;
3306 if (l->besteffort) {
3307 parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
3308 parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
3310 result = dns_message_parse(msg, b, parseflags);
3311 if (result == DNS_R_RECOVERABLE) {
3312 printf(";; Warning: Message parser reports malformed "
3313 "message packet.\n");
3314 result = ISC_R_SUCCESS;
3316 if (result != ISC_R_SUCCESS) {
3317 printf(";; Got bad packet: %s\n", isc_result_totext(result));
3319 query->waiting_connect = ISC_FALSE;
3320 dns_message_destroy(&msg);
3321 isc_event_free(&event);
3324 check_next_lookup(l);
3328 if (msg->counts[DNS_SECTION_QUESTION] != 0) {
3330 for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
3331 result == ISC_R_SUCCESS && match;
3332 result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) {
3333 dns_name_t *name = NULL;
3334 dns_rdataset_t *rdataset;
3336 dns_message_currentname(msg, DNS_SECTION_QUESTION,
3338 for (rdataset = ISC_LIST_HEAD(name->list);
3340 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3341 if (l->rdtype != rdataset->type ||
3342 l->rdclass != rdataset->rdclass ||
3343 !dns_name_equal(l->name, name)) {
3344 char namestr[DNS_NAME_FORMATSIZE];
3345 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3346 char classbuf[DNS_RDATACLASS_FORMATSIZE];
3347 dns_name_format(name, namestr,
3349 dns_rdatatype_format(rdataset->type,
3352 dns_rdataclass_format(rdataset->rdclass,
3355 printf(";; Question section mismatch: "
3357 namestr, typebuf, classbuf);
3363 dns_message_destroy(&msg);
3365 isc_event_free(&event);
3367 check_next_lookup(l);
3374 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 &&
3375 !l->ignore && !l->tcp_mode) {
3376 printf(";; Truncated, retrying in TCP mode.\n");
3377 n = requeue_lookup(l, ISC_TRUE);
3378 n->tcp_mode = ISC_TRUE;
3379 n->origin = query->lookup->origin;
3380 dns_message_destroy(&msg);
3381 isc_event_free(&event);
3384 check_next_lookup(l);
3388 if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) ||
3389 (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse))
3391 dig_query_t *next = ISC_LIST_NEXT(query, link);
3392 if (l->current_query == query)
3393 l->current_query = NULL;
3395 debug("sending query %p\n", next);
3397 send_tcp_connect(next);
3402 * If our query is at the head of the list and there
3403 * is no next, we're the only one left, so fall
3404 * through to print the message.
3406 if ((ISC_LIST_HEAD(l->q) != query) ||
3407 (ISC_LIST_NEXT(query, link) != NULL)) {
3408 if( l->comments == ISC_TRUE )
3409 printf(";; Got %s from %s, "
3410 "trying next server\n",
3411 msg->rcode == dns_rcode_servfail ?
3413 "recursion not available",
3416 check_next_lookup(l);
3417 dns_message_destroy(&msg);
3418 isc_event_free(&event);
3425 result = dns_tsig_verify(&query->recvbuf, msg, NULL, NULL);
3426 if (result != ISC_R_SUCCESS) {
3427 printf(";; Couldn't verify signature: %s\n",
3428 isc_result_totext(result));
3429 validated = ISC_FALSE;
3431 l->tsigctx = msg->tsigctx;
3432 msg->tsigctx = NULL;
3433 if (l->querysig != NULL) {
3434 debug("freeing querysig buffer %p", l->querysig);
3435 isc_buffer_free(&l->querysig);
3437 result = dns_message_getquerytsig(msg, mctx, &l->querysig);
3438 check_result(result,"dns_message_getquerytsig");
3441 extrabytes = isc_buffer_remaininglength(b);
3443 debug("after parse");
3444 if (l->doing_xfr && l->xfr_q == NULL) {
3447 * Once we are in the XFR message, increase
3448 * the timeout to much longer, so brief network
3449 * outages won't cause the XFR to abort
3451 if (timeout != INT_MAX && l->timer != NULL) {
3452 unsigned int local_timeout;
3456 local_timeout = TCP_TIMEOUT * 4;
3458 local_timeout = UDP_TIMEOUT * 4;
3460 if (timeout < (INT_MAX / 4))
3461 local_timeout = timeout * 4;
3463 local_timeout = INT_MAX;
3465 debug("have local timeout of %d", local_timeout);
3466 isc_interval_set(&l->interval, local_timeout, 0);
3467 result = isc_timer_reset(l->timer,
3472 check_result(result, "isc_timer_reset");
3476 if (!l->doing_xfr || l->xfr_q == query) {
3477 if (msg->rcode == dns_rcode_nxdomain &&
3478 (l->origin != NULL || l->need_search)) {
3479 if (!next_origin(query) || showsearch) {
3480 printmessage(query, msg, ISC_TRUE);
3481 received(b->used, &sevent->address, query);
3483 } else if (!l->trace && !l->ns_search_only) {
3487 printmessage(query, msg, ISC_TRUE);
3488 } else if (l->trace) {
3490 int count = msg->counts[DNS_SECTION_ANSWER];
3492 debug("in TRACE code");
3493 if (!l->ns_search_only)
3494 printmessage(query, msg, ISC_TRUE);
3496 l->rdtype = l->qrdtype;
3497 if (l->trace_root || (l->ns_search_only && count > 0)) {
3499 l->rdtype = dns_rdatatype_soa;
3500 n = followup_lookup(msg, query,
3501 DNS_SECTION_ANSWER);
3502 l->trace_root = ISC_FALSE;
3503 } else if (count == 0)
3504 n = followup_lookup(msg, query,
3505 DNS_SECTION_AUTHORITY);
3507 docancel = ISC_TRUE;
3509 debug("in NSSEARCH code");
3511 if (l->trace_root) {
3513 * This is the initial NS query.
3517 l->rdtype = dns_rdatatype_soa;
3518 n = followup_lookup(msg, query,
3519 DNS_SECTION_ANSWER);
3521 docancel = ISC_TRUE;
3522 l->trace_root = ISC_FALSE;
3523 usesearch = ISC_FALSE;
3528 printmessage(query, msg, ISC_TRUE);
3532 chase_msg = isc_mem_allocate(mctx,
3533 sizeof(dig_message_t));
3534 if (chase_msg == NULL) {
3535 fatal("Memory allocation failure in %s:%d",
3536 __FILE__, __LINE__);
3538 ISC_LIST_INITANDAPPEND(chase_message_list, chase_msg,
3540 if (dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
3541 &msg_temp) != ISC_R_SUCCESS) {
3542 fatal("dns_message_create in %s:%d",
3543 __FILE__, __LINE__);
3546 isc_buffer_usedregion(b, &r);
3547 result = isc_buffer_allocate(mctx, &buf, r.length);
3549 check_result(result, "isc_buffer_allocate");
3550 result = isc_buffer_copyregion(buf, &r);
3551 check_result(result, "isc_buffer_copyregion");
3553 result = dns_message_parse(msg_temp, buf, 0);
3555 isc_buffer_free(&buf);
3556 chase_msg->msg = msg_temp;
3558 chase_msg2 = isc_mem_allocate(mctx,
3559 sizeof(dig_message_t));
3560 if (chase_msg2 == NULL) {
3561 fatal("Memory allocation failure in %s:%d",
3562 __FILE__, __LINE__);
3564 ISC_LIST_INITANDAPPEND(chase_message_list2, chase_msg2,
3566 chase_msg2->msg = msg;
3572 if (l->sigchase && ISC_LIST_EMPTY(lookup_list)) {
3578 debug("still pending.");
3580 if (query != l->xfr_q) {
3581 dns_message_destroy(&msg);
3582 isc_event_free(&event);
3583 query->waiting_connect = ISC_FALSE;
3588 docancel = check_for_more_data(query, msg, sevent);
3590 dns_message_destroy(&msg);
3593 check_next_lookup(l);
3597 if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
3602 received(b->used, &sevent->address, query);
3605 if (!query->lookup->ns_search_only)
3606 query->lookup->pending = ISC_FALSE;
3607 if (!query->lookup->ns_search_only ||
3608 query->lookup->trace_root || docancel) {
3612 dns_message_destroy(&msg);
3617 check_next_lookup(l);
3625 dns_message_destroy(&msg);
3627 isc_event_free(&event);
3632 isc_buffer_invalidate(&query->recvbuf);
3633 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
3634 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
3635 result = isc_socket_recvv(query->sock, &query->recvlist, 1,
3636 global_task, recv_done, query);
3637 check_result(result, "isc_socket_recvv");
3639 isc_event_free(&event);
3645 * Turn a name into an address, using system-supplied routines. This is
3646 * used in looking up server names, etc... and needs to use system-supplied
3647 * routines, since they may be using a non-DNS system for these lookups.
3650 get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
3652 isc_result_t result;
3655 result = bind9_getaddresses(host, port, sockaddr, 1, &count);
3657 if (result != ISC_R_SUCCESS)
3662 return (ISC_R_SUCCESS);
3666 getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) {
3667 isc_result_t result;
3668 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
3669 isc_netaddr_t netaddr;
3672 char tmp[ISC_NETADDR_FORMATSIZE];
3674 result = bind9_getaddresses(host, 0, sockaddrs,
3675 DIG_MAX_ADDRESSES, &count);
3676 if (resultp != NULL)
3678 if (result != ISC_R_SUCCESS) {
3679 if (resultp == NULL)
3680 fatal("couldn't get address for '%s': %s",
3681 host, isc_result_totext(result));
3685 for (i = 0; i < count; i++) {
3686 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
3687 isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
3688 srv = make_server(tmp, host);
3689 ISC_LIST_APPEND(lookup->my_server_list, srv, link);
3696 * Initiate either a TCP or UDP lookup
3699 do_lookup(dig_lookup_t *lookup) {
3702 REQUIRE(lookup != NULL);
3704 debug("do_lookup()");
3705 lookup->pending = ISC_TRUE;
3706 query = ISC_LIST_HEAD(lookup->q);
3707 if (query != NULL) {
3708 if (lookup->tcp_mode)
3709 send_tcp_connect(query);
3716 * Start everything in action upon task startup.
3719 onrun_callback(isc_task_t *task, isc_event_t *event) {
3722 isc_event_free(&event);
3729 * Make everything on the lookup queue go away. Mainly used by the
3734 dig_lookup_t *l, *n;
3735 dig_query_t *q, *nq;
3737 debug("cancel_all()");
3744 cancel_now = ISC_TRUE;
3745 if (current_lookup != NULL) {
3746 if (current_lookup->timer != NULL)
3747 isc_timer_detach(¤t_lookup->timer);
3748 for (q = ISC_LIST_HEAD(current_lookup->q);
3752 nq = ISC_LIST_NEXT(q, link);
3753 debug("canceling pending query %p, belonging to %p",
3755 if (q->sock != NULL)
3756 isc_socket_cancel(q->sock, NULL,
3757 ISC_SOCKCANCEL_ALL);
3761 for (q = ISC_LIST_HEAD(current_lookup->connecting);
3765 nq = ISC_LIST_NEXT(q, clink);
3766 debug("canceling connecting query %p, belonging to %p",
3768 if (q->sock != NULL)
3769 isc_socket_cancel(q->sock, NULL,
3770 ISC_SOCKCANCEL_ALL);
3775 l = ISC_LIST_HEAD(lookup_list);
3777 n = ISC_LIST_NEXT(l, link);
3778 ISC_LIST_DEQUEUE(lookup_list, l, link);
3779 try_clear_lookup(l);
3786 * Destroy all of the libs we are using, and get everything ready for a
3790 destroy_libs(void) {
3793 dig_message_t *chase_msg;
3796 isc_result_t result;
3800 isc_socket_detach(&keep);
3801 debug("destroy_libs()");
3802 if (global_task != NULL) {
3803 debug("freeing task");
3804 isc_task_detach(&global_task);
3807 * The taskmgr_destroy() call blocks until all events are cleared
3810 if (taskmgr != NULL) {
3811 debug("freeing taskmgr");
3812 isc_taskmgr_destroy(&taskmgr);
3815 REQUIRE(sockcount == 0);
3816 REQUIRE(recvcount == 0);
3817 REQUIRE(sendcount == 0);
3819 INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
3820 INSIST(current_lookup == NULL);
3823 free_now = ISC_TRUE;
3825 lwres_conf_clear(lwctx);
3826 lwres_context_destroy(&lwctx);
3828 flush_server_list();
3833 result = dns_name_settotextfilter(NULL);
3834 check_result(result, "dns_name_settotextfilter");
3838 if (commctx != NULL) {
3839 debug("freeing commctx");
3840 isc_mempool_destroy(&commctx);
3842 if (socketmgr != NULL) {
3843 debug("freeing socketmgr");
3844 isc_socketmgr_destroy(&socketmgr);
3846 if (timermgr != NULL) {
3847 debug("freeing timermgr");
3848 isc_timermgr_destroy(&timermgr);
3851 debug("freeing key %p", key);
3852 dns_tsigkey_detach(&key);
3854 if (namebuf != NULL)
3855 isc_buffer_free(&namebuf);
3858 debug("destroy DST lib");
3860 is_dst_up = ISC_FALSE;
3863 debug("detach from entropy");
3864 isc_entropy_detach(&entp);
3868 DESTROYLOCK(&lookup_lock);
3871 debug("Destroy the messages kept for sigchase");
3872 /* Destroy the messages kept for sigchase */
3873 chase_msg = ISC_LIST_HEAD(chase_message_list);
3875 while (chase_msg != NULL) {
3876 INSIST(chase_msg->msg != NULL);
3877 dns_message_destroy(&(chase_msg->msg));
3879 chase_msg = ISC_LIST_NEXT(chase_msg, link);
3880 isc_mem_free(mctx, ptr);
3883 chase_msg = ISC_LIST_HEAD(chase_message_list2);
3885 while (chase_msg != NULL) {
3886 INSIST(chase_msg->msg != NULL);
3887 dns_message_destroy(&(chase_msg->msg));
3889 chase_msg = ISC_LIST_NEXT(chase_msg, link);
3890 isc_mem_free(mctx, ptr);
3892 if (dns_name_dynamic(&chase_name))
3893 free_name(&chase_name, mctx);
3895 if (dns_name_dynamic(&chase_current_name))
3896 free_name(&chase_current_name, mctx);
3897 if (dns_name_dynamic(&chase_authority_name))
3898 free_name(&chase_authority_name, mctx);
3901 if (dns_name_dynamic(&chase_signame))
3902 free_name(&chase_signame, mctx);
3906 debug("Removing log context");
3907 isc_log_destroy(&lctx);
3909 debug("Destroy memory");
3910 if (memdebugging != 0)
3911 isc_mem_stats(mctx, stderr);
3913 isc_mem_destroy(&mctx);
3918 initialize_idn(void) {
3920 isc_result_t result;
3922 #ifdef HAVE_SETLOCALE
3924 (void)setlocale(LC_ALL, "");
3926 /* Create configuration context. */
3927 r = idn_nameinit(1);
3928 if (r != idn_success)
3929 fatal("idn api initialization failed: %s",
3930 idn_result_tostring(r));
3932 /* Set domain name -> text post-conversion filter. */
3933 result = dns_name_settotextfilter(output_filter);
3934 check_result(result, "dns_name_settotextfilter");
3938 output_filter(isc_buffer_t *buffer, unsigned int used_org,
3939 isc_boolean_t absolute)
3941 char tmp1[MAXDLEN], tmp2[MAXDLEN];
3942 size_t fromlen, tolen;
3943 isc_boolean_t end_with_dot;
3946 * Copy contents of 'buffer' to 'tmp1', supply trailing dot
3947 * if 'absolute' is true, and terminate with NUL.
3949 fromlen = isc_buffer_usedlength(buffer) - used_org;
3950 if (fromlen >= MAXDLEN)
3951 return (ISC_R_SUCCESS);
3952 memmove(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
3953 end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE;
3954 if (absolute && !end_with_dot) {
3956 if (fromlen >= MAXDLEN)
3957 return (ISC_R_SUCCESS);
3958 tmp1[fromlen - 1] = '.';
3960 tmp1[fromlen] = '\0';
3963 * Convert contents of 'tmp1' to local encoding.
3965 if (idn_decodename(IDN_DECODE_APP, tmp1, tmp2, MAXDLEN) != idn_success)
3966 return (ISC_R_SUCCESS);
3970 * Copy the converted contents in 'tmp1' back to 'buffer'.
3971 * If we have appended trailing dot, remove it.
3973 tolen = strlen(tmp1);
3974 if (absolute && !end_with_dot && tmp1[tolen - 1] == '.')
3977 if (isc_buffer_length(buffer) < used_org + tolen)
3978 return (ISC_R_NOSPACE);
3980 isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org);
3981 memmove(isc_buffer_used(buffer), tmp1, tolen);
3982 isc_buffer_add(buffer, (unsigned int)tolen);
3984 return (ISC_R_SUCCESS);
3988 append_textname(char *name, const char *origin, size_t namesize) {
3989 size_t namelen = strlen(name);
3990 size_t originlen = strlen(origin);
3992 /* Already absolute? */
3993 if (namelen > 0 && name[namelen - 1] == '.')
3996 /* Append dot and origin */
3998 if (namelen + 1 + originlen >= namesize)
3999 return idn_buffer_overflow;
4002 name[namelen++] = '.';
4003 (void)strcpy(name + namelen, origin);
4008 idn_check_result(idn_result_t r, const char *msg) {
4009 if (r != idn_success) {
4011 fatal("%s: %s", msg, idn_result_tostring(r));
4014 #endif /* WITH_IDN */
4018 print_type(dns_rdatatype_t type)
4020 isc_buffer_t * b = NULL;
4021 isc_result_t result;
4024 result = isc_buffer_allocate(mctx, &b, 4000);
4025 check_result(result, "isc_buffer_allocate");
4027 result = dns_rdatatype_totext(type, b);
4028 check_result(result, "print_type");
4030 isc_buffer_usedregion(b, &r);
4031 r.base[r.length] = '\0';
4033 printf("%s", r.base);
4035 isc_buffer_free(&b);
4039 dump_database_section(dns_message_t *msg, int section)
4041 dns_name_t *msg_name=NULL;
4043 dns_rdataset_t *rdataset;
4046 dns_message_currentname(msg, section, &msg_name);
4048 for (rdataset = ISC_LIST_HEAD(msg_name->list); rdataset != NULL;
4049 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4050 dns_name_print(msg_name, stdout);
4052 print_rdataset(msg_name, rdataset, mctx);
4056 } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
4060 dump_database(void) {
4061 dig_message_t * msg;
4063 for (msg = ISC_LIST_HEAD(chase_message_list); msg != NULL;
4064 msg = ISC_LIST_NEXT(msg, link)) {
4065 if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
4067 dump_database_section(msg->msg, DNS_SECTION_ANSWER);
4069 if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
4071 dump_database_section(msg->msg, DNS_SECTION_AUTHORITY);
4073 if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
4075 dump_database_section(msg->msg, DNS_SECTION_ADDITIONAL);
4081 search_type(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) {
4082 dns_rdataset_t *rdataset;
4083 dns_rdata_sig_t siginfo;
4084 dns_rdata_t sigrdata = DNS_RDATA_INIT;
4085 isc_result_t result;
4087 for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
4088 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4089 if (type == dns_rdatatype_any) {
4090 if (rdataset->type != dns_rdatatype_rrsig)
4092 } else if ((type == dns_rdatatype_rrsig) &&
4093 (rdataset->type == dns_rdatatype_rrsig)) {
4094 result = dns_rdataset_first(rdataset);
4095 check_result(result, "empty rdataset");
4096 dns_rdataset_current(rdataset, &sigrdata);
4097 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4098 check_result(result, "sigrdata tostruct siginfo");
4100 if ((siginfo.covered == covers) ||
4101 (covers == dns_rdatatype_any)) {
4102 dns_rdata_reset(&sigrdata);
4103 dns_rdata_freestruct(&siginfo);
4106 dns_rdata_reset(&sigrdata);
4107 dns_rdata_freestruct(&siginfo);
4108 } else if (rdataset->type == type)
4115 chase_scanname_section(dns_message_t *msg, dns_name_t *name,
4116 dns_rdatatype_t type, dns_rdatatype_t covers,
4119 dns_rdataset_t *rdataset;
4120 dns_name_t *msg_name = NULL;
4123 dns_message_currentname(msg, section, &msg_name);
4124 if (dns_name_compare(msg_name, name) == 0) {
4125 rdataset = search_type(msg_name, type, covers);
4126 if (rdataset != NULL)
4130 } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
4137 chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers)
4139 dns_rdataset_t *rdataset = NULL;
4140 dig_message_t * msg;
4142 for (msg = ISC_LIST_HEAD(chase_message_list2); msg != NULL;
4143 msg = ISC_LIST_NEXT(msg, link)) {
4144 if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
4146 rdataset = chase_scanname_section(msg->msg, name,
4148 DNS_SECTION_ANSWER);
4149 if (rdataset != NULL)
4151 if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
4154 chase_scanname_section(msg->msg, name,
4156 DNS_SECTION_AUTHORITY);
4157 if (rdataset != NULL)
4159 if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
4162 chase_scanname_section(msg->msg, name, type,
4164 DNS_SECTION_ADDITIONAL);
4165 if (rdataset != NULL)
4173 sigchase_scanname(dns_rdatatype_t type, dns_rdatatype_t covers,
4174 isc_boolean_t * lookedup, dns_name_t *rdata_name)
4176 dig_lookup_t *lookup;
4177 isc_buffer_t *b = NULL;
4179 isc_result_t result;
4180 dns_rdataset_t * temp;
4181 dns_rdatatype_t querytype;
4183 temp = chase_scanname(rdata_name, type, covers);
4187 if (*lookedup == ISC_TRUE)
4190 lookup = clone_lookup(current_lookup, ISC_TRUE);
4191 lookup->trace_root = ISC_FALSE;
4192 lookup->new_search = ISC_TRUE;
4194 result = isc_buffer_allocate(mctx, &b, BUFSIZE);
4195 check_result(result, "isc_buffer_allocate");
4196 result = dns_name_totext(rdata_name, ISC_FALSE, b);
4197 check_result(result, "dns_name_totext");
4198 isc_buffer_usedregion(b, &r);
4199 r.base[r.length] = '\0';
4200 strlcpy(lookup->textname, (char*)r.base, sizeof(lookup->textname));
4201 isc_buffer_free(&b);
4203 if (type == dns_rdatatype_rrsig)
4208 if (querytype == 0 || querytype == 255) {
4209 printf("Error in the queried type: %d\n", querytype);
4213 lookup->rdtype = querytype;
4214 lookup->rdtypeset = ISC_TRUE;
4215 lookup->qrdtype = querytype;
4216 *lookedup = ISC_TRUE;
4218 ISC_LIST_APPEND(lookup_list, lookup, link);
4219 printf("\n\nLaunch a query to find a RRset of type ");
4221 printf(" for zone: %s\n", lookup->textname);
4226 insert_trustedkey(void *arg, dns_name_t *name, dns_rdataset_t *rdataset)
4228 isc_result_t result;
4233 if (rdataset == NULL || rdataset->type != dns_rdatatype_dnskey)
4234 return (ISC_R_SUCCESS);
4236 for (result = dns_rdataset_first(rdataset);
4237 result == ISC_R_SUCCESS;
4238 result = dns_rdataset_next(rdataset)) {
4239 dns_rdata_t rdata = DNS_RDATA_INIT;
4242 dns_rdataset_current(rdataset, &rdata);
4243 isc_buffer_init(&b, rdata.data, rdata.length);
4244 isc_buffer_add(&b, rdata.length);
4245 if (tk_list.nb_tk >= MAX_TRUSTED_KEY)
4246 return (ISC_R_SUCCESS);
4248 result = dst_key_fromdns(name, rdata.rdclass, &b, mctx, &key);
4249 if (result != ISC_R_SUCCESS)
4251 tk_list.key[tk_list.nb_tk++] = key;
4253 return (ISC_R_SUCCESS);
4261 for (i= 0; i < MAX_TRUSTED_KEY; i++) {
4262 if (tk_list.key[i] != NULL) {
4263 dst_key_free(&tk_list.key[i]);
4264 tk_list.key[i] = NULL;
4273 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
4276 removetmpkey(isc_mem_t *mctx, const char *file)
4278 char *tempnamekey = NULL;
4280 isc_result_t result;
4282 tempnamekeylen = strlen(file)+10;
4284 tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
4285 if (tempnamekey == NULL)
4286 return (ISC_R_NOMEMORY);
4288 memset(tempnamekey, 0, tempnamekeylen);
4290 strcat(tempnamekey, file);
4291 strcat(tempnamekey,".key");
4292 isc_file_remove(tempnamekey);
4294 result = isc_file_remove(tempnamekey);
4295 isc_mem_free(mctx, tempnamekey);
4300 get_trusted_key(isc_mem_t *mctx)
4302 isc_result_t result;
4303 const char *filename = NULL;
4304 dns_rdatacallbacks_t callbacks;
4306 result = isc_file_exists(trustedkey);
4307 if (result != ISC_TRUE) {
4308 result = isc_file_exists("/etc/trusted-key.key");
4309 if (result != ISC_TRUE) {
4310 result = isc_file_exists("./trusted-key.key");
4311 if (result != ISC_TRUE)
4312 return (ISC_R_FAILURE);
4314 filename = "./trusted-key.key";
4316 filename = "/etc/trusted-key.key";
4318 filename = trustedkey;
4320 if (filename == NULL) {
4321 printf("No trusted key\n");
4322 return (ISC_R_FAILURE);
4325 dns_rdatacallbacks_init_stdio(&callbacks);
4326 callbacks.add = insert_trustedkey;
4327 return (dns_master_loadfile(filename, dns_rootname, dns_rootname,
4328 current_lookup->rdclass, 0, &callbacks,
4334 nameFromString(const char *str, dns_name_t *p_ret) {
4335 size_t len = strlen(str);
4336 isc_result_t result;
4337 isc_buffer_t buffer;
4338 dns_fixedname_t fixedname;
4340 REQUIRE(p_ret != NULL);
4341 REQUIRE(str != NULL);
4343 isc_buffer_constinit(&buffer, str, len);
4344 isc_buffer_add(&buffer, len);
4346 dns_fixedname_init(&fixedname);
4347 result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer,
4348 dns_rootname, DNS_NAME_DOWNCASE, NULL);
4349 check_result(result, "nameFromString");
4351 if (dns_name_dynamic(p_ret))
4352 free_name(p_ret, mctx);
4354 result = dns_name_dup(dns_fixedname_name(&fixedname), mctx, p_ret);
4355 check_result(result, "nameFromString");
4361 prepare_lookup(dns_name_t *name)
4363 isc_result_t result;
4364 dig_lookup_t *lookup = NULL;
4368 lookup = clone_lookup(current_lookup, ISC_TRUE);
4369 lookup->trace_root = ISC_FALSE;
4370 lookup->new_search = ISC_TRUE;
4371 lookup->trace_root_sigchase = ISC_FALSE;
4373 strlcpy(lookup->textname, lookup->textnamesigchase, MXNAME);
4375 lookup->rdtype = lookup->rdtype_sigchase;
4376 lookup->rdtypeset = ISC_TRUE;
4377 lookup->qrdtype = lookup->qrdtype_sigchase;
4379 s = ISC_LIST_HEAD(lookup->my_server_list);
4381 debug("freeing server %p belonging to %p",
4384 s = ISC_LIST_NEXT(s, link);
4385 ISC_LIST_DEQUEUE(lookup->my_server_list,
4386 (dig_server_t *)ptr, link);
4387 isc_mem_free(mctx, ptr);
4391 for (result = dns_rdataset_first(chase_nsrdataset);
4392 result == ISC_R_SUCCESS;
4393 result = dns_rdataset_next(chase_nsrdataset)) {
4394 char namestr[DNS_NAME_FORMATSIZE];
4396 dns_rdata_t rdata = DNS_RDATA_INIT;
4397 dig_server_t * srv = NULL;
4398 #define __FOLLOW_GLUE__
4399 #ifdef __FOLLOW_GLUE__
4400 isc_buffer_t *b = NULL;
4401 isc_result_t result;
4403 dns_rdataset_t *rdataset = NULL;
4404 isc_boolean_t true = ISC_TRUE;
4407 memset(namestr, 0, DNS_NAME_FORMATSIZE);
4409 dns_rdataset_current(chase_nsrdataset, &rdata);
4411 result = dns_rdata_tostruct(&rdata, &ns, NULL);
4412 check_result(result, "dns_rdata_tostruct");
4414 #ifdef __FOLLOW_GLUE__
4416 result = advanced_rrsearch(&rdataset, &ns.name,
4418 dns_rdatatype_any, &true);
4419 if (result == ISC_R_SUCCESS) {
4420 for (result = dns_rdataset_first(rdataset);
4421 result == ISC_R_SUCCESS;
4422 result = dns_rdataset_next(rdataset)) {
4423 dns_rdata_t aaaa = DNS_RDATA_INIT;
4424 dns_rdataset_current(rdataset, &aaaa);
4426 result = isc_buffer_allocate(mctx, &b, 80);
4427 check_result(result, "isc_buffer_allocate");
4429 dns_rdata_totext(&aaaa, &ns.name, b);
4430 isc_buffer_usedregion(b, &r);
4431 r.base[r.length] = '\0';
4432 strlcpy(namestr, (char*)r.base,
4433 DNS_NAME_FORMATSIZE);
4434 isc_buffer_free(&b);
4435 dns_rdata_reset(&aaaa);
4438 srv = make_server(namestr, namestr);
4440 ISC_LIST_APPEND(lookup->my_server_list,
4446 result = advanced_rrsearch(&rdataset, &ns.name, dns_rdatatype_a,
4447 dns_rdatatype_any, &true);
4448 if (result == ISC_R_SUCCESS) {
4449 for (result = dns_rdataset_first(rdataset);
4450 result == ISC_R_SUCCESS;
4451 result = dns_rdataset_next(rdataset)) {
4452 dns_rdata_t a = DNS_RDATA_INIT;
4453 dns_rdataset_current(rdataset, &a);
4455 result = isc_buffer_allocate(mctx, &b, 80);
4456 check_result(result, "isc_buffer_allocate");
4458 dns_rdata_totext(&a, &ns.name, b);
4459 isc_buffer_usedregion(b, &r);
4460 r.base[r.length] = '\0';
4461 strlcpy(namestr, (char*)r.base,
4462 DNS_NAME_FORMATSIZE);
4463 isc_buffer_free(&b);
4464 dns_rdata_reset(&a);
4465 printf("ns name: %s\n", namestr);
4468 srv = make_server(namestr, namestr);
4470 ISC_LIST_APPEND(lookup->my_server_list,
4476 dns_name_format(&ns.name, namestr, sizeof(namestr));
4477 printf("ns name: ");
4478 dns_name_print(&ns.name, stdout);
4480 srv = make_server(namestr, namestr);
4482 ISC_LIST_APPEND(lookup->my_server_list, srv, link);
4485 dns_rdata_freestruct(&ns);
4486 dns_rdata_reset(&rdata);
4490 ISC_LIST_APPEND(lookup_list, lookup, link);
4491 printf("\nLaunch a query to find a RRset of type ");
4492 print_type(lookup->rdtype);
4493 printf(" for zone: %s", lookup->textname);
4494 printf(" with nameservers:");
4496 print_rdataset(name, chase_nsrdataset, mctx);
4497 return (ISC_R_SUCCESS);
4502 child_of_zone(dns_name_t * name, dns_name_t * zone_name,
4503 dns_name_t * child_name)
4505 dns_namereln_t name_reln;
4507 unsigned int nlabelsp;
4509 name_reln = dns_name_fullcompare(name, zone_name, &orderp, &nlabelsp);
4510 if (name_reln != dns_namereln_subdomain ||
4511 dns_name_countlabels(name) <= dns_name_countlabels(zone_name) + 1) {
4512 printf("\n;; ERROR : ");
4513 dns_name_print(name, stdout);
4514 printf(" is not a subdomain of: ");
4515 dns_name_print(zone_name, stdout);
4516 printf(" FAILED\n\n");
4517 return (ISC_R_FAILURE);
4520 dns_name_getlabelsequence(name,
4521 dns_name_countlabels(name) -
4522 dns_name_countlabels(zone_name) -1,
4523 dns_name_countlabels(zone_name) +1,
4525 return (ISC_R_SUCCESS);
4529 grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t *sigrdataset)
4531 isc_result_t result;
4532 dns_rdata_t sigrdata = DNS_RDATA_INIT;
4533 dns_rdata_sig_t siginfo;
4535 result = dns_rdataset_first(sigrdataset);
4536 check_result(result, "empty RRSIG dataset");
4537 dns_rdata_init(&sigrdata);
4540 dns_rdataset_current(sigrdataset, &sigrdata);
4542 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4543 check_result(result, "sigrdata tostruct siginfo");
4545 if (dns_name_compare(&siginfo.signer, zone_name) == 0) {
4546 dns_rdata_freestruct(&siginfo);
4547 dns_rdata_reset(&sigrdata);
4548 return (ISC_R_SUCCESS);
4551 dns_rdata_freestruct(&siginfo);
4552 dns_rdata_reset(&sigrdata);
4554 } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
4556 dns_rdata_reset(&sigrdata);
4558 return (ISC_R_FAILURE);
4563 initialization(dns_name_t *name)
4565 isc_result_t result;
4566 isc_boolean_t true = ISC_TRUE;
4568 chase_nsrdataset = NULL;
4569 result = advanced_rrsearch(&chase_nsrdataset, name, dns_rdatatype_ns,
4570 dns_rdatatype_any, &true);
4571 if (result != ISC_R_SUCCESS) {
4572 printf("\n;; NS RRset is missing to continue validation:"
4574 return (ISC_R_FAILURE);
4576 INSIST(chase_nsrdataset != NULL);
4577 prepare_lookup(name);
4579 dup_name(name, &chase_current_name, mctx);
4581 return (ISC_R_SUCCESS);
4586 print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset, isc_mem_t *mctx)
4588 isc_buffer_t *b = NULL;
4589 isc_result_t result;
4592 result = isc_buffer_allocate(mctx, &b, 9000);
4593 check_result(result, "isc_buffer_allocate");
4595 printrdataset(name, rdataset, b);
4597 isc_buffer_usedregion(b, &r);
4598 r.base[r.length] = '\0';
4601 printf("%s\n", r.base);
4603 isc_buffer_free(&b);
4608 dup_name(dns_name_t *source, dns_name_t *target, isc_mem_t *mctx) {
4609 isc_result_t result;
4611 if (dns_name_dynamic(target))
4612 free_name(target, mctx);
4613 result = dns_name_dup(source, mctx, target);
4614 check_result(result, "dns_name_dup");
4618 free_name(dns_name_t *name, isc_mem_t *mctx) {
4619 dns_name_free(name, mctx);
4620 dns_name_init(name, NULL);
4625 * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter
4626 * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key
4627 * and the RRset is valid
4628 * return ISC_R_NOTFOUND if not contains trusted key
4629 or if the RRset isn't valid
4630 * return ISC_R_FAILURE if problem
4634 contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset,
4635 dns_rdataset_t *sigrdataset,
4638 isc_result_t result;
4639 dns_rdata_t rdata = DNS_RDATA_INIT;
4640 dst_key_t *dnsseckey = NULL;
4643 if (name == NULL || rdataset == NULL)
4644 return (ISC_R_FAILURE);
4646 result = dns_rdataset_first(rdataset);
4647 check_result(result, "empty rdataset");
4650 dns_rdataset_current(rdataset, &rdata);
4651 INSIST(rdata.type == dns_rdatatype_dnskey);
4653 result = dns_dnssec_keyfromrdata(name, &rdata,
4655 check_result(result, "dns_dnssec_keyfromrdata");
4658 for (i = 0; i < tk_list.nb_tk; i++) {
4659 if (dst_key_compare(tk_list.key[i], dnsseckey)
4661 dns_rdata_reset(&rdata);
4663 printf(";; Ok, find a Trusted Key in the "
4664 "DNSKEY RRset: %d\n",
4665 dst_key_id(dnsseckey));
4666 if (sigchase_verify_sig_key(name, rdataset,
4671 dst_key_free(&dnsseckey);
4673 return (ISC_R_SUCCESS);
4678 dns_rdata_reset(&rdata);
4679 if (dnsseckey != NULL)
4680 dst_key_free(&dnsseckey);
4681 } while (dns_rdataset_next(rdataset) == ISC_R_SUCCESS);
4683 return (ISC_R_NOTFOUND);
4687 sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset,
4688 dns_rdataset_t *keyrdataset,
4689 dns_rdataset_t *sigrdataset,
4692 isc_result_t result;
4693 dns_rdata_t keyrdata = DNS_RDATA_INIT;
4694 dst_key_t *dnsseckey = NULL;
4696 result = dns_rdataset_first(keyrdataset);
4697 check_result(result, "empty DNSKEY dataset");
4698 dns_rdata_init(&keyrdata);
4701 dns_rdataset_current(keyrdataset, &keyrdata);
4702 INSIST(keyrdata.type == dns_rdatatype_dnskey);
4704 result = dns_dnssec_keyfromrdata(name, &keyrdata,
4706 check_result(result, "dns_dnssec_keyfromrdata");
4708 result = sigchase_verify_sig_key(name, rdataset, dnsseckey,
4710 if (result == ISC_R_SUCCESS) {
4711 dns_rdata_reset(&keyrdata);
4712 dst_key_free(&dnsseckey);
4713 return (ISC_R_SUCCESS);
4715 dst_key_free(&dnsseckey);
4716 dns_rdata_reset(&keyrdata);
4717 } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
4719 dns_rdata_reset(&keyrdata);
4721 return (ISC_R_NOTFOUND);
4725 sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset,
4726 dst_key_t *dnsseckey, dns_rdataset_t *sigrdataset,
4729 isc_result_t result;
4730 dns_rdata_t sigrdata = DNS_RDATA_INIT;
4731 dns_rdata_sig_t siginfo;
4733 result = dns_rdataset_first(sigrdataset);
4734 check_result(result, "empty RRSIG dataset");
4735 dns_rdata_init(&sigrdata);
4738 dns_rdataset_current(sigrdataset, &sigrdata);
4740 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4741 check_result(result, "sigrdata tostruct siginfo");
4744 * Test if the id of the DNSKEY is
4745 * the id of the DNSKEY signer's
4747 if (siginfo.keyid == dst_key_id(dnsseckey)) {
4749 result = dns_rdataset_first(rdataset);
4750 check_result(result, "empty DS dataset");
4752 result = dns_dnssec_verify(name, rdataset, dnsseckey,
4753 ISC_FALSE, mctx, &sigrdata);
4755 printf(";; VERIFYING ");
4756 print_type(rdataset->type);
4757 printf(" RRset for ");
4758 dns_name_print(name, stdout);
4759 printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey),
4760 isc_result_totext(result));
4762 if (result == ISC_R_SUCCESS) {
4763 dns_rdata_reset(&sigrdata);
4767 dns_rdata_freestruct(&siginfo);
4768 dns_rdata_reset(&sigrdata);
4770 } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
4772 dns_rdata_reset(&sigrdata);
4774 return (ISC_R_NOTFOUND);
4779 sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset,
4780 dns_rdataset_t *dsrdataset, isc_mem_t *mctx)
4782 isc_result_t result;
4783 dns_rdata_t keyrdata = DNS_RDATA_INIT;
4784 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
4785 dns_rdata_t dsrdata = DNS_RDATA_INIT;
4786 dns_rdata_ds_t dsinfo;
4787 dst_key_t *dnsseckey = NULL;
4788 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
4790 result = dns_rdataset_first(dsrdataset);
4791 check_result(result, "empty DSset dataset");
4793 dns_rdataset_current(dsrdataset, &dsrdata);
4795 result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL);
4796 check_result(result, "dns_rdata_tostruct for DS");
4798 result = dns_rdataset_first(keyrdataset);
4799 check_result(result, "empty KEY dataset");
4802 dns_rdataset_current(keyrdataset, &keyrdata);
4803 INSIST(keyrdata.type == dns_rdatatype_dnskey);
4805 result = dns_dnssec_keyfromrdata(name, &keyrdata,
4807 check_result(result, "dns_dnssec_keyfromrdata");
4810 * Test if the id of the DNSKEY is the
4811 * id of DNSKEY referenced by the DS
4813 if (dsinfo.key_tag == dst_key_id(dnsseckey)) {
4815 result = dns_ds_buildrdata(name, &keyrdata,
4817 dsbuf, &newdsrdata);
4818 dns_rdata_freestruct(&dsinfo);
4820 if (result != ISC_R_SUCCESS) {
4821 dns_rdata_reset(&keyrdata);
4822 dns_rdata_reset(&newdsrdata);
4823 dns_rdata_reset(&dsrdata);
4824 dst_key_free(&dnsseckey);
4825 dns_rdata_freestruct(&dsinfo);
4826 printf("Oops: impossible to build"
4832 if (dns_rdata_compare(&dsrdata,
4833 &newdsrdata) == 0) {
4834 printf(";; OK a DS valids a DNSKEY"
4836 printf(";; Now verify that this"
4837 " DNSKEY validates the "
4840 result = sigchase_verify_sig_key(name,
4843 chase_sigkeyrdataset,
4845 if (result == ISC_R_SUCCESS) {
4846 dns_rdata_reset(&keyrdata);
4847 dns_rdata_reset(&newdsrdata);
4848 dns_rdata_reset(&dsrdata);
4849 dst_key_free(&dnsseckey);
4854 printf(";; This DS is NOT the DS for"
4855 " the chasing KEY: FAILED\n");
4858 dns_rdata_reset(&newdsrdata);
4860 dst_key_free(&dnsseckey);
4861 dns_rdata_reset(&keyrdata);
4863 } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
4864 dns_rdata_reset(&dsrdata);
4866 } while (dns_rdataset_next(chase_dsrdataset) == ISC_R_SUCCESS);
4868 dns_rdata_reset(&keyrdata);
4869 dns_rdata_reset(&newdsrdata);
4870 dns_rdata_reset(&dsrdata);
4872 return (ISC_R_NOTFOUND);
4877 * take a pointer on a rdataset in parameter and try to resolv it.
4878 * the searched rrset is a rrset on 'name' with type 'type'
4879 * (and if the type is a rrsig the signature cover 'covers').
4880 * the lookedup is to known if you have already done the query on the net.
4881 * ISC_R_SUCCESS: if we found the rrset
4882 * ISC_R_NOTFOUND: we do not found the rrset in cache
4883 * and we do a query on the net
4884 * ISC_R_FAILURE: rrset not found
4887 advanced_rrsearch(dns_rdataset_t **rdataset, dns_name_t *name,
4888 dns_rdatatype_t type, dns_rdatatype_t covers,
4889 isc_boolean_t *lookedup)
4891 isc_boolean_t tmplookedup;
4893 INSIST(rdataset != NULL);
4895 if (*rdataset != NULL)
4896 return (ISC_R_SUCCESS);
4898 tmplookedup = *lookedup;
4899 if ((*rdataset = sigchase_scanname(type, covers,
4900 lookedup, name)) == NULL) {
4902 return (ISC_R_FAILURE);
4903 return (ISC_R_NOTFOUND);
4905 *lookedup = ISC_FALSE;
4906 return (ISC_R_SUCCESS);
4913 sigchase_td(dns_message_t *msg)
4915 isc_result_t result;
4916 dns_name_t *name = NULL;
4917 isc_boolean_t have_answer = ISC_FALSE;
4918 isc_boolean_t true = ISC_TRUE;
4920 if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
4922 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
4923 if (current_lookup->trace_root_sigchase) {
4924 initialization(name);
4929 if (!current_lookup->trace_root_sigchase) {
4930 result = dns_message_firstname(msg,
4931 DNS_SECTION_AUTHORITY);
4932 if (result == ISC_R_SUCCESS)
4933 dns_message_currentname(msg,
4934 DNS_SECTION_AUTHORITY,
4937 = chase_scanname_section(msg, name,
4940 DNS_SECTION_AUTHORITY);
4941 dup_name(name, &chase_authority_name, mctx);
4942 if (chase_nsrdataset != NULL) {
4943 have_delegation_ns = ISC_TRUE;
4944 printf("no response but there is a delegation"
4945 " in authority section:");
4946 dns_name_print(name, stdout);
4949 printf("no response and no delegation in "
4950 "authority section but a reference"
4952 dns_name_print(name, stdout);
4954 error_message = msg;
4957 printf(";; NO ANSWERS: %s\n",
4958 isc_result_totext(result));
4959 free_name(&chase_name, mctx);
4968 = chase_scanname_section(msg, &chase_name,
4972 DNS_SECTION_ANSWER);
4973 if (chase_rdataset != NULL)
4974 have_response = ISC_TRUE;
4977 result = advanced_rrsearch(&chase_keyrdataset,
4978 &chase_current_name,
4979 dns_rdatatype_dnskey,
4981 &chase_keylookedup);
4982 if (result == ISC_R_FAILURE) {
4983 printf("\n;; DNSKEY is missing to continue validation:"
4987 if (result == ISC_R_NOTFOUND)
4989 INSIST(chase_keyrdataset != NULL);
4990 printf("\n;; DNSKEYset:\n");
4991 print_rdataset(&chase_current_name , chase_keyrdataset, mctx);
4994 result = advanced_rrsearch(&chase_sigkeyrdataset,
4995 &chase_current_name,
4996 dns_rdatatype_rrsig,
4997 dns_rdatatype_dnskey,
4998 &chase_sigkeylookedup);
4999 if (result == ISC_R_FAILURE) {
5000 printf("\n;; RRSIG of DNSKEY is missing to continue validation:"
5004 if (result == ISC_R_NOTFOUND)
5006 INSIST(chase_sigkeyrdataset != NULL);
5007 printf("\n;; RRSIG of the DNSKEYset:\n");
5008 print_rdataset(&chase_current_name , chase_sigkeyrdataset, mctx);
5011 if (!chase_dslookedup && !chase_nslookedup) {
5012 if (!delegation_follow) {
5013 result = contains_trusted_key(&chase_current_name,
5015 chase_sigkeyrdataset,
5018 INSIST(chase_dsrdataset != NULL);
5019 INSIST(chase_sigdsrdataset != NULL);
5020 result = sigchase_verify_ds(&chase_current_name,
5026 if (result != ISC_R_SUCCESS) {
5027 printf("\n;; chain of trust can't be validated:"
5031 chase_dsrdataset = NULL;
5032 chase_sigdsrdataset = NULL;
5036 if (have_response || (!have_delegation_ns && !have_response)) {
5037 /* test if it's a grand father case */
5039 if (have_response) {
5040 result = advanced_rrsearch(&chase_sigrdataset,
5042 dns_rdatatype_rrsig,
5046 if (result == ISC_R_FAILURE) {
5047 printf("\n;; RRset is missing to continue"
5048 " validation SHOULD NOT APPEND:"
5054 result = advanced_rrsearch(&chase_sigrdataset,
5055 &chase_authority_name,
5056 dns_rdatatype_rrsig,
5059 if (result == ISC_R_FAILURE) {
5060 printf("\n;; RRSIG is missing to continue"
5061 " validation SHOULD NOT APPEND:"
5066 result = grandfather_pb_test(&chase_current_name,
5068 if (result != ISC_R_SUCCESS) {
5069 dns_name_t tmp_name;
5071 printf("\n;; We are in a Grand Father Problem:"
5072 " See 2.2.1 in RFC 3568\n");
5073 chase_rdataset = NULL;
5074 chase_sigrdataset = NULL;
5075 have_response = ISC_FALSE;
5076 have_delegation_ns = ISC_FALSE;
5078 dns_name_init(&tmp_name, NULL);
5079 result = child_of_zone(&chase_name, &chase_current_name,
5081 if (dns_name_dynamic(&chase_authority_name))
5082 free_name(&chase_authority_name, mctx);
5083 dup_name(&tmp_name, &chase_authority_name, mctx);
5084 printf(";; and we try to continue chain of trust"
5085 " validation of the zone: ");
5086 dns_name_print(&chase_authority_name, stdout);
5088 have_delegation_ns = ISC_TRUE;
5093 chase_sigrdataset = NULL;
5097 if (have_delegation_ns) {
5098 chase_nsrdataset = NULL;
5099 result = advanced_rrsearch(&chase_nsrdataset,
5100 &chase_authority_name,
5104 if (result == ISC_R_FAILURE) {
5105 printf("\n;;NSset is missing to continue validation:"
5109 if (result == ISC_R_NOTFOUND) {
5112 INSIST(chase_nsrdataset != NULL);
5114 result = advanced_rrsearch(&chase_dsrdataset,
5115 &chase_authority_name,
5119 if (result == ISC_R_FAILURE) {
5120 printf("\n;; DSset is missing to continue validation:"
5124 if (result == ISC_R_NOTFOUND)
5126 INSIST(chase_dsrdataset != NULL);
5127 printf("\n;; DSset:\n");
5128 print_rdataset(&chase_authority_name , chase_dsrdataset, mctx);
5130 result = advanced_rrsearch(&chase_sigdsrdataset,
5131 &chase_authority_name,
5132 dns_rdatatype_rrsig,
5135 if (result != ISC_R_SUCCESS) {
5136 printf("\n;; DSset is missing to continue validation:"
5140 printf("\n;; RRSIGset of DSset\n");
5141 print_rdataset(&chase_authority_name,
5142 chase_sigdsrdataset, mctx);
5143 INSIST(chase_sigdsrdataset != NULL);
5145 result = sigchase_verify_sig(&chase_authority_name,
5148 chase_sigdsrdataset, mctx);
5149 if (result != ISC_R_SUCCESS) {
5150 printf("\n;; Impossible to verify the DSset:"
5154 chase_keyrdataset = NULL;
5155 chase_sigkeyrdataset = NULL;
5158 prepare_lookup(&chase_authority_name);
5160 have_response = ISC_FALSE;
5161 have_delegation_ns = ISC_FALSE;
5162 delegation_follow = ISC_TRUE;
5163 error_message = NULL;
5164 dup_name(&chase_authority_name, &chase_current_name, mctx);
5165 free_name(&chase_authority_name, mctx);
5170 if (error_message != NULL) {
5171 dns_rdataset_t *rdataset;
5172 dns_rdataset_t *sigrdataset;
5173 dns_name_t rdata_name;
5174 isc_result_t ret = ISC_R_FAILURE;
5176 dns_name_init(&rdata_name, NULL);
5177 result = prove_nx(error_message, &chase_name,
5178 current_lookup->rdclass_sigchase,
5179 current_lookup->rdtype_sigchase, &rdata_name,
5180 &rdataset, &sigrdataset);
5181 if (rdataset == NULL || sigrdataset == NULL ||
5182 dns_name_countlabels(&rdata_name) == 0) {
5183 printf("\n;; Impossible to verify the non-existence,"
5184 " the NSEC RRset can't be validated:"
5188 ret = sigchase_verify_sig(&rdata_name, rdataset,
5191 if (ret != ISC_R_SUCCESS) {
5192 free_name(&rdata_name, mctx);
5193 printf("\n;; Impossible to verify the NSEC RR to prove"
5194 " the non-existence : FAILED\n\n");
5197 free_name(&rdata_name, mctx);
5198 if (result != ISC_R_SUCCESS) {
5199 printf("\n;; Impossible to verify the non-existence:"
5203 printf("\n;; OK the query doesn't have response but"
5204 " we have validate this fact : SUCCESS\n\n");
5210 printf(";; cleanandgo \n");
5211 if (dns_name_dynamic(&chase_current_name))
5212 free_name(&chase_current_name, mctx);
5213 if (dns_name_dynamic(&chase_authority_name))
5214 free_name(&chase_authority_name, mctx);
5219 result = advanced_rrsearch(&chase_rdataset, &chase_name,
5220 current_lookup->rdtype_sigchase,
5223 if (result == ISC_R_FAILURE) {
5224 printf("\n;; RRsig of RRset is missing to continue validation"
5225 " SHOULD NOT APPEND: FAILED\n\n");
5228 result = sigchase_verify_sig(&chase_name, chase_rdataset,
5230 chase_sigrdataset, mctx);
5231 if (result != ISC_R_SUCCESS) {
5232 printf("\n;; Impossible to verify the RRset : FAILED\n\n");
5235 print_rdataset(&chase_name , chase_rdataset, mctx);
5236 printf("DNSKEYset:\n");
5237 print_rdataset(&chase_name , chase_keyrdataset, mctx);
5238 printf("RRSIG of RRset:\n");
5239 print_rdataset(&chase_name , chase_sigrdataset, mctx);
5244 printf("\n;; The Answer:\n");
5245 print_rdataset(&chase_name , chase_rdataset, mctx);
5247 printf("\n;; FINISH : we have validate the DNSSEC chain"
5248 " of trust: SUCCESS\n\n");
5259 getneededrr(dns_message_t *msg)
5261 isc_result_t result;
5262 dns_name_t *name = NULL;
5263 dns_rdata_t sigrdata = DNS_RDATA_INIT;
5264 dns_rdata_sig_t siginfo;
5265 isc_boolean_t true = ISC_TRUE;
5267 if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
5269 printf(";; NO ANSWERS: %s\n", isc_result_totext(result));
5271 if (chase_name.ndata == NULL)
5272 return (ISC_R_ADDRNOTAVAIL);
5274 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
5277 /* What do we chase? */
5278 if (chase_rdataset == NULL) {
5279 result = advanced_rrsearch(&chase_rdataset, name,
5281 dns_rdatatype_any, &true);
5282 if (result != ISC_R_SUCCESS) {
5283 printf("\n;; No Answers: Validation FAILED\n\n");
5284 return (ISC_R_NOTFOUND);
5286 dup_name(name, &chase_name, mctx);
5287 printf(";; RRset to chase:\n");
5288 print_rdataset(&chase_name, chase_rdataset, mctx);
5290 INSIST(chase_rdataset != NULL);
5293 if (chase_sigrdataset == NULL) {
5294 result = advanced_rrsearch(&chase_sigrdataset, name,
5295 dns_rdatatype_rrsig,
5296 chase_rdataset->type,
5297 &chase_siglookedup);
5298 if (result == ISC_R_FAILURE) {
5299 printf("\n;; RRSIG is missing for continue validation:"
5301 if (dns_name_dynamic(&chase_name))
5302 free_name(&chase_name, mctx);
5303 return (ISC_R_NOTFOUND);
5305 if (result == ISC_R_NOTFOUND) {
5306 return (ISC_R_NOTFOUND);
5308 printf("\n;; RRSIG of the RRset to chase:\n");
5309 print_rdataset(&chase_name, chase_sigrdataset, mctx);
5311 INSIST(chase_sigrdataset != NULL);
5314 /* first find the DNSKEY name */
5315 result = dns_rdataset_first(chase_sigrdataset);
5316 check_result(result, "empty RRSIG dataset");
5317 dns_rdataset_current(chase_sigrdataset, &sigrdata);
5318 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
5319 check_result(result, "sigrdata tostruct siginfo");
5320 dup_name(&siginfo.signer, &chase_signame, mctx);
5321 dns_rdata_freestruct(&siginfo);
5322 dns_rdata_reset(&sigrdata);
5324 /* Do we have a key? */
5325 if (chase_keyrdataset == NULL) {
5326 result = advanced_rrsearch(&chase_keyrdataset,
5328 dns_rdatatype_dnskey,
5330 &chase_keylookedup);
5331 if (result == ISC_R_FAILURE) {
5332 printf("\n;; DNSKEY is missing to continue validation:"
5334 free_name(&chase_signame, mctx);
5335 if (dns_name_dynamic(&chase_name))
5336 free_name(&chase_name, mctx);
5337 return (ISC_R_NOTFOUND);
5339 if (result == ISC_R_NOTFOUND) {
5340 free_name(&chase_signame, mctx);
5341 return (ISC_R_NOTFOUND);
5343 printf("\n;; DNSKEYset that signs the RRset to chase:\n");
5344 print_rdataset(&chase_signame, chase_keyrdataset, mctx);
5346 INSIST(chase_keyrdataset != NULL);
5348 if (chase_sigkeyrdataset == NULL) {
5349 result = advanced_rrsearch(&chase_sigkeyrdataset,
5351 dns_rdatatype_rrsig,
5352 dns_rdatatype_dnskey,
5353 &chase_sigkeylookedup);
5354 if (result == ISC_R_FAILURE) {
5355 printf("\n;; RRSIG for DNSKEY is missing to continue"
5356 " validation : FAILED\n\n");
5357 free_name(&chase_signame, mctx);
5358 if (dns_name_dynamic(&chase_name))
5359 free_name(&chase_name, mctx);
5360 return (ISC_R_NOTFOUND);
5362 if (result == ISC_R_NOTFOUND) {
5363 free_name(&chase_signame, mctx);
5364 return (ISC_R_NOTFOUND);
5366 printf("\n;; RRSIG of the DNSKEYset that signs the "
5367 "RRset to chase:\n");
5368 print_rdataset(&chase_signame, chase_sigkeyrdataset, mctx);
5370 INSIST(chase_sigkeyrdataset != NULL);
5373 if (chase_dsrdataset == NULL) {
5374 result = advanced_rrsearch(&chase_dsrdataset, &chase_signame,
5378 if (result == ISC_R_FAILURE) {
5379 printf("\n;; WARNING There is no DS for the zone: ");
5380 dns_name_print(&chase_signame, stdout);
5383 if (result == ISC_R_NOTFOUND) {
5384 free_name(&chase_signame, mctx);
5385 return (ISC_R_NOTFOUND);
5387 if (chase_dsrdataset != NULL) {
5388 printf("\n;; DSset of the DNSKEYset\n");
5389 print_rdataset(&chase_signame, chase_dsrdataset, mctx);
5393 if (chase_dsrdataset != NULL) {
5395 * if there is no RRSIG of DS,
5396 * we don't want to search on the network
5398 result = advanced_rrsearch(&chase_sigdsrdataset,
5400 dns_rdatatype_rrsig,
5401 dns_rdatatype_ds, &true);
5402 if (result == ISC_R_FAILURE) {
5403 printf(";; WARNING : NO RRSIG DS : RRSIG DS"
5404 " should come with DS\n");
5406 * We continue even the DS couldn't be validated,
5407 * because the DNSKEY could be a Trusted Key.
5409 chase_dsrdataset = NULL;
5411 printf("\n;; RRSIG of the DSset of the DNSKEYset\n");
5412 print_rdataset(&chase_signame, chase_sigdsrdataset,
5422 sigchase_bu(dns_message_t *msg)
5424 isc_result_t result;
5427 if (tk_list.nb_tk == 0) {
5428 result = get_trusted_key(mctx);
5429 if (result != ISC_R_SUCCESS) {
5430 printf("No trusted keys present\n");
5436 ret = getneededrr(msg);
5437 if (ret == ISC_R_NOTFOUND)
5440 if (ret == ISC_R_ADDRNOTAVAIL) {
5441 /* We have no response */
5442 dns_rdataset_t *rdataset;
5443 dns_rdataset_t *sigrdataset;
5444 dns_name_t rdata_name;
5445 dns_name_t query_name;
5448 dns_name_init(&query_name, NULL);
5449 dns_name_init(&rdata_name, NULL);
5450 nameFromString(current_lookup->textname, &query_name);
5452 result = prove_nx(msg, &query_name, current_lookup->rdclass,
5453 current_lookup->rdtype, &rdata_name,
5454 &rdataset, &sigrdataset);
5455 free_name(&query_name, mctx);
5456 if (rdataset == NULL || sigrdataset == NULL ||
5457 dns_name_countlabels(&rdata_name) == 0) {
5458 printf("\n;; Impossible to verify the Non-existence,"
5459 " the NSEC RRset can't be validated: "
5465 if (result != ISC_R_SUCCESS) {
5466 printf("\n No Answers and impossible to prove the"
5467 " unsecurity : Validation FAILED\n\n");
5471 printf(";; An NSEC prove the non-existence of a answers,"
5472 " Now we want validate this NSEC\n");
5474 dup_name(&rdata_name, &chase_name, mctx);
5475 free_name(&rdata_name, mctx);
5476 chase_rdataset = rdataset;
5477 chase_sigrdataset = sigrdataset;
5478 chase_keyrdataset = NULL;
5479 chase_sigkeyrdataset = NULL;
5480 chase_dsrdataset = NULL;
5481 chase_sigdsrdataset = NULL;
5482 chase_siglookedup = ISC_FALSE;
5483 chase_keylookedup = ISC_FALSE;
5484 chase_dslookedup = ISC_FALSE;
5485 chase_sigdslookedup = ISC_FALSE;
5492 printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n");
5494 result = sigchase_verify_sig(&chase_name, chase_rdataset,
5496 chase_sigrdataset, mctx);
5497 if (result != ISC_R_SUCCESS) {
5498 free_name(&chase_name, mctx);
5499 free_name(&chase_signame, mctx);
5500 printf(";; No DNSKEY is valid to check the RRSIG"
5501 " of the RRset: FAILED\n");
5505 printf(";; OK We found DNSKEY (or more) to validate the RRset\n");
5507 result = contains_trusted_key(&chase_signame, chase_keyrdataset,
5508 chase_sigkeyrdataset, mctx);
5509 if (result == ISC_R_SUCCESS) {
5510 free_name(&chase_name, mctx);
5511 free_name(&chase_signame, mctx);
5512 printf("\n;; Ok this DNSKEY is a Trusted Key,"
5513 " DNSSEC validation is ok: SUCCESS\n\n");
5518 printf(";; Now, we are going to validate this DNSKEY by the DS\n");
5520 if (chase_dsrdataset == NULL) {
5521 free_name(&chase_name, mctx);
5522 free_name(&chase_signame, mctx);
5523 printf(";; the DNSKEY isn't trusted-key and there isn't"
5524 " DS to validate the DNSKEY: FAILED\n");
5529 result = sigchase_verify_ds(&chase_signame, chase_keyrdataset,
5530 chase_dsrdataset, mctx);
5531 if (result != ISC_R_SUCCESS) {
5532 free_name(&chase_signame, mctx);
5533 free_name(&chase_name, mctx);
5534 printf(";; ERROR no DS validates a DNSKEY in the"
5535 " DNSKEY RRset: FAILED\n");
5539 printf(";; OK this DNSKEY (validated by the DS) validates"
5540 " the RRset of the DNSKEYs, thus the DNSKEY validates"
5542 INSIST(chase_sigdsrdataset != NULL);
5544 dup_name(&chase_signame, &chase_name, mctx);
5545 free_name(&chase_signame, mctx);
5546 chase_rdataset = chase_dsrdataset;
5547 chase_sigrdataset = chase_sigdsrdataset;
5548 chase_keyrdataset = NULL;
5549 chase_sigkeyrdataset = NULL;
5550 chase_dsrdataset = NULL;
5551 chase_sigdsrdataset = NULL;
5552 chase_siglookedup = chase_keylookedup = ISC_FALSE;
5553 chase_dslookedup = chase_sigdslookedup = ISC_FALSE;
5555 printf(";; Now, we want to validate the DS : recursive call\n");
5562 sigchase(dns_message_t *msg) {
5564 if (current_lookup->do_topdown) {
5577 * return 1 if name1 < name2
5578 * 0 if name1 == name2
5579 * -1 if name1 > name2
5583 inf_name(dns_name_t *name1, dns_name_t *name2)
5587 unsigned int nblabel1;
5588 unsigned int nblabel2;
5593 nblabel1 = dns_name_countlabels(name1);
5594 nblabel2 = dns_name_countlabels(name2);
5596 if (nblabel1 >= nblabel2)
5597 min_lum_label = nblabel2;
5599 min_lum_label = nblabel1;
5602 for (i=1 ; i < min_lum_label; i++) {
5603 dns_name_getlabel(name1, nblabel1 -1 - i, &label1);
5604 dns_name_getlabel(name2, nblabel2 -1 - i, &label2);
5605 if ((ret = isc_region_compare(&label1, &label2)) != 0) {
5612 if (nblabel1 == nblabel2)
5615 if (nblabel1 < nblabel2)
5627 prove_nx_domain(dns_message_t *msg,
5629 dns_name_t *rdata_name,
5630 dns_rdataset_t **rdataset,
5631 dns_rdataset_t **sigrdataset)
5633 isc_result_t ret = ISC_R_FAILURE;
5634 isc_result_t result = ISC_R_NOTFOUND;
5635 dns_rdataset_t *nsecset = NULL;
5636 dns_rdataset_t *signsecset = NULL ;
5637 dns_rdata_t nsec = DNS_RDATA_INIT;
5638 dns_name_t *nsecname;
5639 dns_rdata_nsec_t nsecstruct;
5641 if ((result = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
5643 printf(";; nothing in authority section : impossible to"
5644 " validate the non-existence : FAILED\n");
5645 return (ISC_R_FAILURE);
5650 dns_message_currentname(msg, DNS_SECTION_AUTHORITY, &nsecname);
5651 nsecset = search_type(nsecname, dns_rdatatype_nsec,
5653 if (nsecset == NULL)
5656 printf("There is a NSEC for this zone in the"
5657 " AUTHORITY section:\n");
5658 print_rdataset(nsecname, nsecset, mctx);
5660 for (result = dns_rdataset_first(nsecset);
5661 result == ISC_R_SUCCESS;
5662 result = dns_rdataset_next(nsecset)) {
5663 dns_rdataset_current(nsecset, &nsec);
5667 = chase_scanname_section(msg, nsecname,
5668 dns_rdatatype_rrsig,
5670 DNS_SECTION_AUTHORITY);
5671 if (signsecset == NULL) {
5672 printf(";; no RRSIG NSEC in authority section:"
5673 " impossible to validate the "
5674 "non-existence: FAILED\n");
5675 return (ISC_R_FAILURE);
5678 ret = dns_rdata_tostruct(&nsec, &nsecstruct, NULL);
5679 check_result(ret,"dns_rdata_tostruct");
5681 if ((inf_name(nsecname, &nsecstruct.next) == 1 &&
5682 inf_name(name, &nsecstruct.next) == 1) ||
5683 (inf_name(name, nsecname) == 1 &&
5684 inf_name(&nsecstruct.next, name) == 1)) {
5685 dns_rdata_freestruct(&nsecstruct);
5686 *rdataset = nsecset;
5687 *sigrdataset = signsecset;
5688 dup_name(nsecname, rdata_name, mctx);
5690 return (ISC_R_SUCCESS);
5693 dns_rdata_freestruct(&nsecstruct);
5694 dns_rdata_reset(&nsec);
5696 } while (dns_message_nextname(msg, DNS_SECTION_AUTHORITY)
5700 *sigrdataset = NULL;
5702 return (ISC_R_FAILURE);
5713 prove_nx_type(dns_message_t *msg, dns_name_t *name, dns_rdataset_t *nsecset,
5714 dns_rdataclass_t class, dns_rdatatype_t type,
5715 dns_name_t *rdata_name, dns_rdataset_t **rdataset,
5716 dns_rdataset_t **sigrdataset)
5719 dns_rdataset_t *signsecset;
5720 dns_rdata_t nsec = DNS_RDATA_INIT;
5724 ret = dns_rdataset_first(nsecset);
5725 check_result(ret,"dns_rdataset_first");
5727 dns_rdataset_current(nsecset, &nsec);
5729 ret = dns_nsec_typepresent(&nsec, type);
5730 if (ret == ISC_R_SUCCESS)
5731 printf("OK the NSEC said that the type doesn't exist \n");
5733 signsecset = chase_scanname_section(msg, name,
5734 dns_rdatatype_rrsig,
5736 DNS_SECTION_AUTHORITY);
5737 if (signsecset == NULL) {
5738 printf("There isn't RRSIG NSEC for the zone \n");
5739 return (ISC_R_FAILURE);
5741 dup_name(name, rdata_name, mctx);
5742 *rdataset = nsecset;
5743 *sigrdataset = signsecset;
5755 prove_nx(dns_message_t *msg, dns_name_t *name, dns_rdataclass_t class,
5756 dns_rdatatype_t type, dns_name_t *rdata_name,
5757 dns_rdataset_t **rdataset, dns_rdataset_t **sigrdataset)
5760 dns_rdataset_t *nsecset = NULL;
5762 printf("We want to prove the non-existence of a type of rdata %d"
5763 " or of the zone: \n", type);
5765 if ((ret = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
5767 printf(";; nothing in authority section : impossible to"
5768 " validate the non-existence : FAILED\n");
5769 return (ISC_R_FAILURE);
5772 nsecset = chase_scanname_section(msg, name, dns_rdatatype_nsec,
5774 DNS_SECTION_AUTHORITY);
5775 if (nsecset != NULL) {
5776 printf("We have a NSEC for this zone :OK\n");
5777 ret = prove_nx_type(msg, name, nsecset, class,
5778 type, rdata_name, rdataset,
5780 if (ret != ISC_R_SUCCESS) {
5781 printf("prove_nx: ERROR type exist\n");
5784 printf("prove_nx: OK type does not exist\n");
5785 return (ISC_R_SUCCESS);
5788 printf("there is no NSEC for this zone: validating "
5789 "that the zone doesn't exist\n");
5790 ret = prove_nx_domain(msg, name, rdata_name,
5791 rdataset, sigrdataset);
5794 /* Never get here */