2 * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: dighost.c,v 1.336.22.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/dnssec.h>
52 #include <isc/random.h>
55 #include <dns/fixedname.h>
57 #include <dns/message.h>
59 #include <dns/rdata.h>
60 #include <dns/rdataclass.h>
61 #include <dns/rdatalist.h>
62 #include <dns/rdataset.h>
63 #include <dns/rdatastruct.h>
64 #include <dns/rdatatype.h>
65 #include <dns/result.h>
69 #include <dst/result.h>
72 #include <isc/base64.h>
73 #include <isc/entropy.h>
77 #include <isc/netaddr.h>
79 #include <isc/netdb.h>
81 #include <isc/parseint.h>
82 #include <isc/print.h>
83 #include <isc/random.h>
84 #include <isc/result.h>
85 #include <isc/serial.h>
86 #include <isc/string.h>
88 #include <isc/timer.h>
89 #include <isc/types.h>
92 #include <isccfg/namedconf.h>
94 #include <lwres/lwres.h>
95 #include <lwres/net.h>
97 #include <bind9/getaddresses.h>
101 #if ! defined(NS_INADDRSZ)
102 #define NS_INADDRSZ 4
105 #if ! defined(NS_IN6ADDRSZ)
106 #define NS_IN6ADDRSZ 16
109 static lwres_context_t *lwctx = NULL;
110 static lwres_conf_t *lwconf;
112 dig_lookuplist_t lookup_list;
113 dig_serverlist_t server_list;
114 dig_searchlistlist_t search_list;
117 check_ra = ISC_FALSE,
118 have_ipv4 = ISC_FALSE,
119 have_ipv6 = ISC_FALSE,
120 specified_source = ISC_FALSE,
121 free_now = ISC_FALSE,
122 cancel_now = ISC_FALSE,
123 usesearch = ISC_FALSE,
124 showsearch = ISC_FALSE,
126 is_dst_up = ISC_FALSE;
128 unsigned int timeout = 0;
129 unsigned int extrabytes;
130 isc_mem_t *mctx = NULL;
131 isc_log_t *lctx = NULL;
132 isc_taskmgr_t *taskmgr = NULL;
133 isc_task_t *global_task = NULL;
134 isc_timermgr_t *timermgr = NULL;
135 isc_socketmgr_t *socketmgr = NULL;
136 isc_sockaddr_t bind_address;
137 isc_sockaddr_t bind_any;
143 int lookup_counter = 0;
146 static void initialize_idn(void);
147 static isc_result_t output_filter(isc_buffer_t *buffer,
148 unsigned int used_org,
149 isc_boolean_t absolute);
150 static idn_result_t append_textname(char *name, const char *origin,
152 static void idn_check_result(idn_result_t r, const char *msg);
161 *\li 0 Everything went well, including things like NXDOMAIN
163 *\li 7 Got too many RR's or Names
164 *\li 8 Couldn't open batch file
165 *\li 9 No reply from server
166 *\li 10 Internal error
170 char keynametext[MXNAME];
171 char keyfile[MXNAME] = "";
172 char keysecret[MXNAME] = "";
173 dns_name_t *hmacname = NULL;
174 unsigned int digestbits = 0;
175 isc_buffer_t *namebuf = NULL;
176 dns_tsigkey_t *key = NULL;
177 isc_boolean_t validated = ISC_TRUE;
178 isc_entropy_t *entp = NULL;
179 isc_mempool_t *commctx = NULL;
180 isc_boolean_t debugging = ISC_FALSE;
181 isc_boolean_t memdebugging = ISC_FALSE;
182 char *progname = NULL;
183 isc_mutex_t lookup_lock;
184 dig_lookup_t *current_lookup = NULL;
188 isc_result_t get_trusted_key(isc_mem_t *mctx);
189 dns_rdataset_t * sigchase_scanname(dns_rdatatype_t type,
190 dns_rdatatype_t covers,
191 isc_boolean_t *lookedup,
192 dns_name_t *rdata_name);
193 dns_rdataset_t * chase_scanname_section(dns_message_t *msg,
195 dns_rdatatype_t type,
196 dns_rdatatype_t covers,
198 isc_result_t advanced_rrsearch(dns_rdataset_t **rdataset,
200 dns_rdatatype_t type,
201 dns_rdatatype_t covers,
202 isc_boolean_t *lookedup);
203 isc_result_t sigchase_verify_sig_key(dns_name_t *name,
204 dns_rdataset_t *rdataset,
205 dst_key_t* dnsseckey,
206 dns_rdataset_t *sigrdataset,
208 isc_result_t sigchase_verify_sig(dns_name_t *name,
209 dns_rdataset_t *rdataset,
210 dns_rdataset_t *keyrdataset,
211 dns_rdataset_t *sigrdataset,
213 isc_result_t sigchase_verify_ds(dns_name_t *name,
214 dns_rdataset_t *keyrdataset,
215 dns_rdataset_t *dsrdataset,
217 void sigchase(dns_message_t *msg);
218 void print_rdata(dns_rdata_t *rdata, isc_mem_t *mctx);
219 void print_rdataset(dns_name_t *name,
220 dns_rdataset_t *rdataset, isc_mem_t *mctx);
221 void dup_name(dns_name_t *source, dns_name_t* target,
223 void free_name(dns_name_t *name, isc_mem_t *mctx);
224 void dump_database(void);
225 void dump_database_section(dns_message_t *msg, int section);
226 dns_rdataset_t * search_type(dns_name_t *name, dns_rdatatype_t type,
227 dns_rdatatype_t covers);
228 isc_result_t contains_trusted_key(dns_name_t *name,
229 dns_rdataset_t *rdataset,
230 dns_rdataset_t *sigrdataset,
232 void print_type(dns_rdatatype_t type);
233 isc_result_t prove_nx_domain(dns_message_t * msg,
235 dns_name_t * rdata_name,
236 dns_rdataset_t ** rdataset,
237 dns_rdataset_t ** sigrdataset);
238 isc_result_t prove_nx_type(dns_message_t * msg, dns_name_t *name,
239 dns_rdataset_t *nsec,
240 dns_rdataclass_t class,
241 dns_rdatatype_t type,
242 dns_name_t * rdata_name,
243 dns_rdataset_t ** rdataset,
244 dns_rdataset_t ** sigrdataset);
245 isc_result_t prove_nx(dns_message_t * msg, dns_name_t * name,
246 dns_rdataclass_t class,
247 dns_rdatatype_t type,
248 dns_name_t * rdata_name,
249 dns_rdataset_t ** rdataset,
250 dns_rdataset_t ** sigrdataset);
251 static void nameFromString(const char *str, dns_name_t *p_ret);
252 int inf_name(dns_name_t * name1, dns_name_t * name2);
253 isc_result_t opentmpkey(isc_mem_t *mctx, const char *file,
254 char **tempp, FILE **fp);
255 isc_result_t removetmpkey(isc_mem_t *mctx, const char *file);
256 void clean_trustedkey(void);
257 void insert_trustedkey(dst_key_t **key);
259 isc_result_t getneededrr(dns_message_t *msg);
260 void sigchase_bottom_up(dns_message_t *msg);
261 void sigchase_bu(dns_message_t *msg);
264 isc_result_t initialization(dns_name_t *name);
265 isc_result_t prepare_lookup(dns_name_t *name);
266 isc_result_t grandfather_pb_test(dns_name_t * zone_name,
267 dns_rdataset_t *sigrdataset);
268 isc_result_t child_of_zone(dns_name_t *name,
269 dns_name_t *zone_name,
270 dns_name_t *child_name);
271 void sigchase_td(dns_message_t *msg);
273 char trustedkey[MXNAME] = "";
275 dns_rdataset_t *chase_rdataset = NULL;
276 dns_rdataset_t *chase_sigrdataset = NULL;
277 dns_rdataset_t *chase_dsrdataset = NULL;
278 dns_rdataset_t *chase_sigdsrdataset = NULL;
279 dns_rdataset_t *chase_keyrdataset = NULL;
280 dns_rdataset_t *chase_sigkeyrdataset = NULL;
281 dns_rdataset_t *chase_nsrdataset = NULL;
283 dns_name_t chase_name; /* the query name */
286 * the current name is the parent name when we follow delegation
288 dns_name_t chase_current_name;
290 * the child name is used for delegation (NS DS responses in AUTHORITY section)
292 dns_name_t chase_authority_name;
295 dns_name_t chase_signame;
299 isc_boolean_t chase_siglookedup = ISC_FALSE;
300 isc_boolean_t chase_keylookedup = ISC_FALSE;
301 isc_boolean_t chase_sigkeylookedup = ISC_FALSE;
302 isc_boolean_t chase_dslookedup = ISC_FALSE;
303 isc_boolean_t chase_sigdslookedup = ISC_FALSE;
305 isc_boolean_t chase_nslookedup = ISC_FALSE;
306 isc_boolean_t chase_lookedup = ISC_FALSE;
309 isc_boolean_t delegation_follow = ISC_FALSE;
310 isc_boolean_t grandfather_pb = ISC_FALSE;
311 isc_boolean_t have_response = ISC_FALSE;
312 isc_boolean_t have_delegation_ns = ISC_FALSE;
313 dns_message_t * error_message = NULL;
316 isc_boolean_t dsvalidating = ISC_FALSE;
317 isc_boolean_t chase_name_dup = ISC_FALSE;
319 ISC_LIST(dig_message_t) chase_message_list;
320 ISC_LIST(dig_message_t) chase_message_list2;
323 #define MAX_TRUSTED_KEY 5
324 typedef struct struct_trusted_key_list {
325 dst_key_t * key[MAX_TRUSTED_KEY];
329 struct_tk_list tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0};
333 #define DIG_MAX_ADDRESSES 20
336 * Apply and clear locks at the event level in global task.
337 * Can I get rid of these using shutdown events? XXX
339 #define LOCK_LOOKUP {\
340 debug("lock_lookup %s:%d", __FILE__, __LINE__);\
341 check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\
344 #define UNLOCK_LOOKUP {\
345 debug("unlock_lookup %s:%d", __FILE__, __LINE__);\
346 check_result(isc_mutex_unlock((&lookup_lock)),\
347 "isc_mutex_unlock");\
351 cancel_lookup(dig_lookup_t *lookup);
354 recv_done(isc_task_t *task, isc_event_t *event);
357 send_udp(dig_query_t *query);
360 connect_timeout(isc_task_t *task, isc_event_t *event);
363 launch_next_query(dig_query_t *query, isc_boolean_t include_question);
366 send_tcp_connect(dig_query_t *query);
369 mem_alloc(void *arg, size_t size) {
370 return (isc_mem_get(arg, size));
374 mem_free(void *arg, void *mem, size_t size) {
375 isc_mem_put(arg, mem, size);
379 next_token(char **stringp, const char *delim) {
383 res = strsep(stringp, delim);
386 } while (*res == '\0');
391 count_dots(char *string) {
405 hex_dump(isc_buffer_t *b) {
409 isc_buffer_usedregion(b, &r);
411 printf("%d bytes\n", r.length);
412 for (len = 0; len < r.length; len++) {
413 printf("%02x ", r.base[len]);
414 if (len % 16 == 15) {
416 for (i = len - 15; i <= len; i++) {
417 if (r.base[i] >= '!' && r.base[i] <= '}')
426 for (i = len; (i % 16) != 0; i++)
429 for (i = ((len>>4)<<4); i < len; i++) {
430 if (r.base[i] >= '!' && r.base[i] <= '}')
440 * Append 'len' bytes of 'text' at '*p', failing with
441 * ISC_R_NOSPACE if that would advance p past 'end'.
444 append(const char *text, int len, char **p, char *end) {
446 return (ISC_R_NOSPACE);
447 memcpy(*p, text, len);
449 return (ISC_R_SUCCESS);
453 reverse_octets(const char *in, char **p, char *end) {
454 char *dot = strchr(in, '.');
458 result = reverse_octets(dot + 1, p, end);
459 if (result != ISC_R_SUCCESS)
461 result = append(".", 1, p, end);
462 if (result != ISC_R_SUCCESS)
468 return (append(in, len, p, end));
472 get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int,
473 isc_boolean_t strict)
479 addr.family = AF_INET6;
480 r = inet_pton(AF_INET6, value, &addr.type.in6);
482 /* This is a valid IPv6 address. */
483 dns_fixedname_t fname;
485 unsigned int options = 0;
488 options |= DNS_BYADDROPT_IPV6INT;
489 dns_fixedname_init(&fname);
490 name = dns_fixedname_name(&fname);
491 result = dns_byaddr_createptrname2(&addr, options, name);
492 if (result != ISC_R_SUCCESS)
494 dns_name_format(name, reverse, len);
495 return (ISC_R_SUCCESS);
498 * Not a valid IPv6 address. Assume IPv4.
499 * If 'strict' is not set, construct the
500 * in-addr.arpa name by blindly reversing
501 * octets whether or not they look like integers,
502 * so that this can be used for RFC2317 names
506 char *end = reverse + len;
507 if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1)
508 return (DNS_R_BADDOTTEDQUAD);
509 result = reverse_octets(value, &p, end);
510 if (result != ISC_R_SUCCESS)
512 /* Append .in-addr.arpa. and a terminating NUL. */
513 result = append(".in-addr.arpa.", 15, &p, end);
514 if (result != ISC_R_SUCCESS)
516 return (ISC_R_SUCCESS);
521 fatal(const char *format, ...) {
525 fprintf(stderr, "%s: ", progname);
526 va_start(args, format);
527 vfprintf(stderr, format, args);
529 fprintf(stderr, "\n");
533 exitcode = fatalexit;
538 debug(const char *format, ...) {
543 va_start(args, format);
544 vfprintf(stderr, format, args);
546 fprintf(stderr, "\n");
551 check_result(isc_result_t result, const char *msg) {
552 if (result != ISC_R_SUCCESS) {
553 fatal("%s: %s", msg, isc_result_totext(result));
558 * Create a server structure, which is part of the lookup structure.
559 * This is little more than a linked list of servers to query in hopes
560 * of finding the answer the user is looking for
563 make_server(const char *servname, const char *userarg) {
566 REQUIRE(servname != NULL);
568 debug("make_server(%s)", servname);
569 srv = isc_mem_allocate(mctx, sizeof(struct dig_server));
571 fatal("memory allocation failure in %s:%d",
573 strlcpy(srv->servername, servname, MXNAME);
574 strlcpy(srv->userarg, userarg, MXNAME);
575 ISC_LINK_INIT(srv, link);
580 addr2af(int lwresaddrtype)
584 switch (lwresaddrtype) {
585 case LWRES_ADDRTYPE_V4:
589 case LWRES_ADDRTYPE_V6:
598 * Create a copy of the server list from the lwres configuration structure.
599 * The dest list must have already had ISC_LIST_INIT applied.
602 copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) {
603 dig_server_t *newsrv;
604 char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
608 debug("copy_server_list()");
609 for (i = 0; i < confdata->nsnext; i++) {
610 af = addr2af(confdata->nameservers[i].family);
612 if (af == AF_INET && !have_ipv4)
614 if (af == AF_INET6 && !have_ipv6)
617 lwres_net_ntop(af, confdata->nameservers[i].address,
619 newsrv = make_server(tmp, tmp);
620 ISC_LINK_INIT(newsrv, link);
621 ISC_LIST_ENQUEUE(*dest, newsrv, link);
626 flush_server_list(void) {
627 dig_server_t *s, *ps;
629 debug("flush_server_list()");
630 s = ISC_LIST_HEAD(server_list);
633 s = ISC_LIST_NEXT(s, link);
634 ISC_LIST_DEQUEUE(server_list, ps, link);
635 isc_mem_free(mctx, ps);
640 set_nameserver(char *opt) {
642 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
643 isc_netaddr_t netaddr;
646 char tmp[ISC_NETADDR_FORMATSIZE];
651 result = bind9_getaddresses(opt, 0, sockaddrs,
652 DIG_MAX_ADDRESSES, &count);
653 if (result != ISC_R_SUCCESS)
654 fatal("couldn't get address for '%s': %s",
655 opt, isc_result_totext(result));
659 for (i = 0; i < count; i++) {
660 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
661 isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
662 srv = make_server(tmp, opt);
664 fatal("memory allocation failure");
665 ISC_LIST_APPEND(server_list, srv, link);
670 add_nameserver(lwres_conf_t *confdata, const char *addr, int af) {
672 int i = confdata->nsnext;
674 if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS)
675 return (ISC_R_FAILURE);
679 confdata->nameservers[i].family = LWRES_ADDRTYPE_V4;
680 confdata->nameservers[i].length = NS_INADDRSZ;
683 confdata->nameservers[i].family = LWRES_ADDRTYPE_V6;
684 confdata->nameservers[i].length = NS_IN6ADDRSZ;
687 return (ISC_R_FAILURE);
690 if (lwres_net_pton(af, addr, &confdata->nameservers[i].address) == 1) {
692 return (ISC_R_SUCCESS);
694 return (ISC_R_FAILURE);
698 * Produce a cloned server list. The dest list must have already had
699 * ISC_LIST_INIT applied.
702 clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
703 dig_server_t *srv, *newsrv;
705 debug("clone_server_list()");
706 srv = ISC_LIST_HEAD(src);
707 while (srv != NULL) {
708 newsrv = make_server(srv->servername, srv->userarg);
709 ISC_LINK_INIT(newsrv, link);
710 ISC_LIST_ENQUEUE(*dest, newsrv, link);
711 srv = ISC_LIST_NEXT(srv, link);
716 * Create an empty lookup structure, which holds all the information needed
717 * to get an answer to a user's question. This structure contains two
718 * linked lists: the server list (servers to query) and the query list
719 * (outstanding queries which have been made to the listed servers).
722 make_empty_lookup(void) {
723 dig_lookup_t *looknew;
725 debug("make_empty_lookup()");
729 looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
731 fatal("memory allocation failure in %s:%d",
733 looknew->pending = ISC_TRUE;
734 looknew->textname[0] = 0;
735 looknew->cmdline[0] = 0;
736 looknew->rdtype = dns_rdatatype_a;
737 looknew->qrdtype = dns_rdatatype_a;
738 looknew->rdclass = dns_rdataclass_in;
739 looknew->rdtypeset = ISC_FALSE;
740 looknew->rdclassset = ISC_FALSE;
741 looknew->sendspace = NULL;
742 looknew->sendmsg = NULL;
743 looknew->name = NULL;
744 looknew->oname = NULL;
745 looknew->timer = NULL;
746 looknew->xfr_q = NULL;
747 looknew->current_query = NULL;
748 looknew->doing_xfr = ISC_FALSE;
749 looknew->ixfr_serial = 0;
750 looknew->trace = ISC_FALSE;
751 looknew->trace_root = ISC_FALSE;
752 looknew->identify = ISC_FALSE;
753 looknew->identify_previous_line = ISC_FALSE;
754 looknew->ignore = ISC_FALSE;
755 looknew->servfail_stops = ISC_TRUE;
756 looknew->besteffort = ISC_TRUE;
757 looknew->dnssec = ISC_FALSE;
758 looknew->nsid = ISC_FALSE;
760 looknew->sigchase = ISC_FALSE;
762 looknew->do_topdown = ISC_FALSE;
763 looknew->trace_root_sigchase = ISC_FALSE;
764 looknew->rdtype_sigchaseset = ISC_FALSE;
765 looknew->rdtype_sigchase = dns_rdatatype_any;
766 looknew->qrdtype_sigchase = dns_rdatatype_any;
767 looknew->rdclass_sigchase = dns_rdataclass_in;
768 looknew->rdclass_sigchaseset = ISC_FALSE;
771 looknew->udpsize = 0;
773 looknew->recurse = ISC_TRUE;
774 looknew->aaonly = ISC_FALSE;
775 looknew->adflag = ISC_FALSE;
776 looknew->cdflag = ISC_FALSE;
777 looknew->ns_search_only = ISC_FALSE;
778 looknew->origin = NULL;
779 looknew->tsigctx = NULL;
780 looknew->querysig = NULL;
781 looknew->retries = tries;
782 looknew->nsfound = 0;
783 looknew->tcp_mode = ISC_FALSE;
784 looknew->ip6_int = ISC_FALSE;
785 looknew->comments = ISC_TRUE;
786 looknew->stats = ISC_TRUE;
787 looknew->section_question = ISC_TRUE;
788 looknew->section_answer = ISC_TRUE;
789 looknew->section_authority = ISC_TRUE;
790 looknew->section_additional = ISC_TRUE;
791 looknew->new_search = ISC_FALSE;
792 looknew->done_as_is = ISC_FALSE;
793 looknew->need_search = ISC_FALSE;
794 dns_fixedname_init(&looknew->fdomain);
795 ISC_LINK_INIT(looknew, link);
796 ISC_LIST_INIT(looknew->q);
797 ISC_LIST_INIT(looknew->my_server_list);
802 * Clone a lookup, perhaps copying the server list. This does not clone
803 * the query list, since it will be regenerated by the setup_lookup()
804 * function, nor does it queue up the new lookup for processing.
805 * Caution: If you don't clone the servers, you MUST clone the server
806 * list separately from somewhere else, or construct it by hand.
809 clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
810 dig_lookup_t *looknew;
812 debug("clone_lookup()");
816 looknew = make_empty_lookup();
817 INSIST(looknew != NULL);
818 strncpy(looknew->textname, lookold->textname, MXNAME);
820 strncpy(looknew->textnamesigchase, lookold->textnamesigchase, MXNAME);
822 strncpy(looknew->cmdline, lookold->cmdline, MXNAME);
823 looknew->textname[MXNAME-1] = 0;
824 looknew->rdtype = lookold->rdtype;
825 looknew->qrdtype = lookold->qrdtype;
826 looknew->rdclass = lookold->rdclass;
827 looknew->rdtypeset = lookold->rdtypeset;
828 looknew->rdclassset = lookold->rdclassset;
829 looknew->doing_xfr = lookold->doing_xfr;
830 looknew->ixfr_serial = lookold->ixfr_serial;
831 looknew->trace = lookold->trace;
832 looknew->trace_root = lookold->trace_root;
833 looknew->identify = lookold->identify;
834 looknew->identify_previous_line = lookold->identify_previous_line;
835 looknew->ignore = lookold->ignore;
836 looknew->servfail_stops = lookold->servfail_stops;
837 looknew->besteffort = lookold->besteffort;
838 looknew->dnssec = lookold->dnssec;
839 looknew->nsid = lookold->nsid;
841 looknew->sigchase = lookold->sigchase;
843 looknew->do_topdown = lookold->do_topdown;
844 looknew->trace_root_sigchase = lookold->trace_root_sigchase;
845 looknew->rdtype_sigchaseset = lookold->rdtype_sigchaseset;
846 looknew->rdtype_sigchase = lookold->rdtype_sigchase;
847 looknew->qrdtype_sigchase = lookold->qrdtype_sigchase;
848 looknew->rdclass_sigchase = lookold->rdclass_sigchase;
849 looknew->rdclass_sigchaseset = lookold->rdclass_sigchaseset;
852 looknew->udpsize = lookold->udpsize;
853 looknew->edns = lookold->edns;
854 looknew->recurse = lookold->recurse;
855 looknew->aaonly = lookold->aaonly;
856 looknew->adflag = lookold->adflag;
857 looknew->cdflag = lookold->cdflag;
858 looknew->ns_search_only = lookold->ns_search_only;
859 looknew->tcp_mode = lookold->tcp_mode;
860 looknew->comments = lookold->comments;
861 looknew->stats = lookold->stats;
862 looknew->section_question = lookold->section_question;
863 looknew->section_answer = lookold->section_answer;
864 looknew->section_authority = lookold->section_authority;
865 looknew->section_additional = lookold->section_additional;
866 looknew->retries = lookold->retries;
867 looknew->tsigctx = NULL;
868 looknew->need_search = lookold->need_search;
869 looknew->done_as_is = lookold->done_as_is;
870 dns_name_copy(dns_fixedname_name(&lookold->fdomain),
871 dns_fixedname_name(&looknew->fdomain), NULL);
874 clone_server_list(lookold->my_server_list,
875 &looknew->my_server_list);
880 * Requeue a lookup for further processing, perhaps copying the server
881 * list. The new lookup structure is returned to the caller, and is
882 * queued for processing. If servers are not cloned in the requeue, they
883 * must be added before allowing the current event to complete, since the
884 * completion of the event may result in the next entry on the lookup
888 requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
889 dig_lookup_t *looknew;
891 debug("requeue_lookup()");
894 if (lookup_counter > LOOKUP_LIMIT)
895 fatal("too many lookups");
897 looknew = clone_lookup(lookold, servers);
898 INSIST(looknew != NULL);
900 debug("before insertion, init@%p -> %p, new@%p -> %p",
901 lookold, lookold->link.next, looknew, looknew->link.next);
902 ISC_LIST_PREPEND(lookup_list, looknew, link);
903 debug("after insertion, init -> %p, new = %p, new -> %p",
904 lookold, looknew, looknew->link.next);
910 setup_text_key(void) {
913 isc_buffer_t secretbuf;
915 unsigned char *secretstore;
917 debug("setup_text_key()");
918 result = isc_buffer_allocate(mctx, &namebuf, MXNAME);
919 check_result(result, "isc_buffer_allocate");
920 dns_name_init(&keyname, NULL);
921 check_result(result, "dns_name_init");
922 isc_buffer_putstr(namebuf, keynametext);
923 secretsize = strlen(keysecret) * 3 / 4;
924 secretstore = isc_mem_allocate(mctx, secretsize);
925 if (secretstore == NULL)
926 fatal("memory allocation failure in %s:%d",
928 isc_buffer_init(&secretbuf, secretstore, secretsize);
929 result = isc_base64_decodestring(keysecret, &secretbuf);
930 if (result != ISC_R_SUCCESS)
933 secretsize = isc_buffer_usedlength(&secretbuf);
935 if (hmacname == NULL) {
936 result = DST_R_UNSUPPORTEDALG;
940 result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf);
941 if (result != ISC_R_SUCCESS)
944 result = dns_tsigkey_create(&keyname, hmacname, secretstore,
945 secretsize, ISC_FALSE, NULL, 0, 0, mctx,
948 if (result != ISC_R_SUCCESS)
949 printf(";; Couldn't create key %s: %s\n",
950 keynametext, isc_result_totext(result));
952 dst_key_setbits(key->key, digestbits);
954 isc_mem_free(mctx, secretstore);
955 dns_name_invalidate(&keyname);
956 isc_buffer_free(&namebuf);
960 parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max,
963 isc_result_t result = isc_parse_uint32(&n, value, 10);
964 if (result == ISC_R_SUCCESS && n > max)
965 result = ISC_R_RANGE;
966 if (result != ISC_R_SUCCESS) {
967 printf("invalid %s '%s': %s\n", desc,
968 value, isc_result_totext(result));
972 return (ISC_R_SUCCESS);
976 parse_bits(char *arg, const char *desc, isc_uint32_t max) {
980 result = parse_uint(&tmp, arg, max, desc);
981 if (result != ISC_R_SUCCESS)
982 fatal("couldn't parse digest bits");
983 tmp = (tmp + 7) & ~0x7U;
989 * Parse HMAC algorithm specification
992 parse_hmac(const char *hmac) {
996 REQUIRE(hmac != NULL);
999 if (len >= (int) sizeof(buf))
1000 fatal("unknown key type '%.*s'", len, hmac);
1001 strncpy(buf, hmac, sizeof(buf));
1005 if (strcasecmp(buf, "hmac-md5") == 0) {
1006 hmacname = DNS_TSIG_HMACMD5_NAME;
1007 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
1008 hmacname = DNS_TSIG_HMACMD5_NAME;
1009 digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128);
1010 } else if (strcasecmp(buf, "hmac-sha1") == 0) {
1011 hmacname = DNS_TSIG_HMACSHA1_NAME;
1013 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
1014 hmacname = DNS_TSIG_HMACSHA1_NAME;
1015 digestbits = parse_bits(&buf[10], "digest-bits [0..160]", 160);
1016 } else if (strcasecmp(buf, "hmac-sha224") == 0) {
1017 hmacname = DNS_TSIG_HMACSHA224_NAME;
1018 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
1019 hmacname = DNS_TSIG_HMACSHA224_NAME;
1020 digestbits = parse_bits(&buf[12], "digest-bits [0..224]", 224);
1021 } else if (strcasecmp(buf, "hmac-sha256") == 0) {
1022 hmacname = DNS_TSIG_HMACSHA256_NAME;
1023 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
1024 hmacname = DNS_TSIG_HMACSHA256_NAME;
1025 digestbits = parse_bits(&buf[12], "digest-bits [0..256]", 256);
1026 } else if (strcasecmp(buf, "hmac-sha384") == 0) {
1027 hmacname = DNS_TSIG_HMACSHA384_NAME;
1028 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
1029 hmacname = DNS_TSIG_HMACSHA384_NAME;
1030 digestbits = parse_bits(&buf[12], "digest-bits [0..384]", 384);
1031 } else if (strcasecmp(buf, "hmac-sha512") == 0) {
1032 hmacname = DNS_TSIG_HMACSHA512_NAME;
1033 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
1034 hmacname = DNS_TSIG_HMACSHA512_NAME;
1035 digestbits = parse_bits(&buf[12], "digest-bits [0..512]", 512);
1037 fprintf(stderr, ";; Warning, ignoring "
1038 "invalid TSIG algorithm %s\n", buf);
1043 * Get a key from a named.conf format keyfile
1046 read_confkey(void) {
1047 isc_log_t *lctx = NULL;
1048 cfg_parser_t *pctx = NULL;
1049 cfg_obj_t *file = NULL;
1050 const cfg_obj_t *key = NULL;
1051 const cfg_obj_t *secretobj = NULL;
1052 const cfg_obj_t *algorithmobj = NULL;
1053 const char *keyname;
1054 const char *secretstr;
1055 const char *algorithm;
1056 isc_result_t result;
1058 if (! isc_file_exists(keyfile))
1059 return (ISC_R_FILENOTFOUND);
1061 result = cfg_parser_create(mctx, lctx, &pctx);
1062 if (result != ISC_R_SUCCESS)
1065 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
1067 if (result != ISC_R_SUCCESS)
1070 result = cfg_map_get(file, "key", &key);
1071 if (result != ISC_R_SUCCESS)
1074 (void) cfg_map_get(key, "secret", &secretobj);
1075 (void) cfg_map_get(key, "algorithm", &algorithmobj);
1076 if (secretobj == NULL || algorithmobj == NULL)
1077 fatal("key must have algorithm and secret");
1079 keyname = cfg_obj_asstring(cfg_map_getname(key));
1080 secretstr = cfg_obj_asstring(secretobj);
1081 algorithm = cfg_obj_asstring(algorithmobj);
1083 strncpy(keynametext, keyname, sizeof(keynametext));
1084 strncpy(keysecret, secretstr, sizeof(keysecret));
1085 parse_hmac(algorithm);
1091 cfg_obj_destroy(pctx, &file);
1092 cfg_parser_destroy(&pctx);
1099 setup_file_key(void) {
1100 isc_result_t result;
1101 dst_key_t *dstkey = NULL;
1103 debug("setup_file_key()");
1105 /* Try reading the key from a K* pair */
1106 result = dst_key_fromnamedfile(keyfile, NULL,
1107 DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
1110 /* If that didn't work, try reading it as a session.key keyfile */
1111 if (result != ISC_R_SUCCESS) {
1112 result = read_confkey();
1113 if (result == ISC_R_SUCCESS)
1117 if (result != ISC_R_SUCCESS) {
1118 fprintf(stderr, "Couldn't read key from %s: %s\n",
1119 keyfile, isc_result_totext(result));
1123 switch (dst_key_alg(dstkey)) {
1124 case DST_ALG_HMACMD5:
1125 hmacname = DNS_TSIG_HMACMD5_NAME;
1127 case DST_ALG_HMACSHA1:
1128 hmacname = DNS_TSIG_HMACSHA1_NAME;
1130 case DST_ALG_HMACSHA224:
1131 hmacname = DNS_TSIG_HMACSHA224_NAME;
1133 case DST_ALG_HMACSHA256:
1134 hmacname = DNS_TSIG_HMACSHA256_NAME;
1136 case DST_ALG_HMACSHA384:
1137 hmacname = DNS_TSIG_HMACSHA384_NAME;
1139 case DST_ALG_HMACSHA512:
1140 hmacname = DNS_TSIG_HMACSHA512_NAME;
1143 printf(";; Couldn't create key %s: bad algorithm\n",
1147 result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmacname,
1148 dstkey, ISC_FALSE, NULL, 0, 0,
1150 if (result != ISC_R_SUCCESS) {
1151 printf(";; Couldn't create key %s: %s\n",
1152 keynametext, isc_result_totext(result));
1157 dst_key_free(&dstkey);
1160 static dig_searchlist_t *
1161 make_searchlist_entry(char *domain) {
1162 dig_searchlist_t *search;
1163 search = isc_mem_allocate(mctx, sizeof(*search));
1165 fatal("memory allocation failure in %s:%d",
1166 __FILE__, __LINE__);
1167 strncpy(search->origin, domain, MXNAME);
1168 search->origin[MXNAME-1] = 0;
1169 ISC_LINK_INIT(search, link);
1174 clear_searchlist(void) {
1175 dig_searchlist_t *search;
1176 while ((search = ISC_LIST_HEAD(search_list)) != NULL) {
1177 ISC_LIST_UNLINK(search_list, search, link);
1178 isc_mem_free(mctx, search);
1183 create_search_list(lwres_conf_t *confdata) {
1185 dig_searchlist_t *search;
1187 debug("create_search_list()");
1190 for (i = 0; i < confdata->searchnxt; i++) {
1191 search = make_searchlist_entry(confdata->search[i]);
1192 ISC_LIST_APPEND(search_list, search, link);
1197 * Setup the system as a whole, reading key information and resolv.conf
1201 setup_system(void) {
1202 dig_searchlist_t *domain = NULL;
1203 lwres_result_t lwresult;
1204 unsigned int lwresflags;
1206 debug("setup_system()");
1208 lwresflags = LWRES_CONTEXT_SERVERMODE;
1210 lwresflags |= LWRES_CONTEXT_USEIPV4;
1212 lwresflags |= LWRES_CONTEXT_USEIPV6;
1214 lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free,
1216 if (lwresult != LWRES_R_SUCCESS)
1217 fatal("lwres_context_create failed");
1219 lwresult = lwres_conf_parse(lwctx, RESOLV_CONF);
1220 if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND)
1221 fatal("parse of %s failed", RESOLV_CONF);
1223 lwconf = lwres_conf_get(lwctx);
1225 /* Make the search list */
1226 if (lwconf->searchnxt > 0)
1227 create_search_list(lwconf);
1228 else { /* No search list. Use the domain name if any */
1229 if (lwconf->domainname != NULL) {
1230 domain = make_searchlist_entry(lwconf->domainname);
1231 ISC_LIST_APPEND(search_list, domain, link);
1237 ndots = lwconf->ndots;
1238 debug("ndots is %d.", ndots);
1241 /* If user doesn't specify server use nameservers from resolv.conf. */
1242 if (ISC_LIST_EMPTY(server_list))
1243 copy_server_list(lwconf, &server_list);
1245 /* If we don't find a nameserver fall back to localhost */
1246 if (ISC_LIST_EMPTY(server_list)) {
1248 lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET);
1249 if (lwresult != ISC_R_SUCCESS)
1250 fatal("add_nameserver failed");
1253 lwresult = add_nameserver(lwconf, "::1", AF_INET6);
1254 if (lwresult != ISC_R_SUCCESS)
1255 fatal("add_nameserver failed");
1258 copy_server_list(lwconf, &server_list);
1265 if (keyfile[0] != 0)
1267 else if (keysecret[0] != 0)
1270 /* Setup the list of messages for +sigchase */
1271 ISC_LIST_INIT(chase_message_list);
1272 ISC_LIST_INIT(chase_message_list2);
1273 dns_name_init(&chase_name, NULL);
1275 dns_name_init(&chase_current_name, NULL);
1276 dns_name_init(&chase_authority_name, NULL);
1279 dns_name_init(&chase_signame, NULL);
1287 * Override the search list derived from resolv.conf by 'domain'.
1290 set_search_domain(char *domain) {
1291 dig_searchlist_t *search;
1294 search = make_searchlist_entry(domain);
1295 ISC_LIST_APPEND(search_list, search, link);
1299 * Setup the ISC and DNS libraries for use by the system.
1303 isc_result_t result;
1304 isc_logconfig_t *logconfig = NULL;
1306 debug("setup_libs()");
1308 result = isc_net_probeipv4();
1309 if (result == ISC_R_SUCCESS)
1310 have_ipv4 = ISC_TRUE;
1312 result = isc_net_probeipv6();
1313 if (result == ISC_R_SUCCESS)
1314 have_ipv6 = ISC_TRUE;
1315 if (!have_ipv6 && !have_ipv4)
1316 fatal("can't find either v4 or v6 networking");
1318 result = isc_mem_create(0, 0, &mctx);
1319 check_result(result, "isc_mem_create");
1321 result = isc_log_create(mctx, &lctx, &logconfig);
1322 check_result(result, "isc_log_create");
1324 isc_log_setcontext(lctx);
1326 dns_log_setcontext(lctx);
1328 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
1329 check_result(result, "isc_log_usechannel");
1331 isc_log_setdebuglevel(lctx, 0);
1333 result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
1334 check_result(result, "isc_taskmgr_create");
1336 result = isc_task_create(taskmgr, 0, &global_task);
1337 check_result(result, "isc_task_create");
1339 result = isc_timermgr_create(mctx, &timermgr);
1340 check_result(result, "isc_timermgr_create");
1342 result = isc_socketmgr_create(mctx, &socketmgr);
1343 check_result(result, "isc_socketmgr_create");
1345 result = isc_entropy_create(mctx, &entp);
1346 check_result(result, "isc_entropy_create");
1348 result = dst_lib_init(mctx, entp, 0);
1349 check_result(result, "dst_lib_init");
1350 is_dst_up = ISC_TRUE;
1352 result = isc_mempool_create(mctx, COMMSIZE, &commctx);
1353 check_result(result, "isc_mempool_create");
1354 isc_mempool_setname(commctx, "COMMPOOL");
1356 * 6 and 2 set as reasonable parameters for 3 or 4 nameserver
1359 isc_mempool_setfreemax(commctx, 6);
1360 isc_mempool_setfillcount(commctx, 2);
1362 result = isc_mutex_init(&lookup_lock);
1363 check_result(result, "isc_mutex_init");
1365 dns_result_register();
1369 * Add EDNS0 option record to a message. Currently, the only supported
1370 * options are UDP buffer size, the DO bit, and NSID request.
1373 add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns,
1374 isc_boolean_t dnssec, isc_boolean_t nsid)
1376 dns_rdataset_t *rdataset = NULL;
1377 dns_rdatalist_t *rdatalist = NULL;
1378 dns_rdata_t *rdata = NULL;
1379 isc_result_t result;
1382 result = dns_message_gettemprdataset(msg, &rdataset);
1383 check_result(result, "dns_message_gettemprdataset");
1384 dns_rdataset_init(rdataset);
1385 result = dns_message_gettemprdatalist(msg, &rdatalist);
1386 check_result(result, "dns_message_gettemprdatalist");
1387 result = dns_message_gettemprdata(msg, &rdata);
1388 check_result(result, "dns_message_gettemprdata");
1390 debug("setting udp size of %d", udpsize);
1391 rdatalist->type = dns_rdatatype_opt;
1392 rdatalist->covers = 0;
1393 rdatalist->rdclass = udpsize;
1394 rdatalist->ttl = edns << 16;
1396 rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
1398 isc_buffer_t *b = NULL;
1400 result = isc_buffer_allocate(mctx, &b, 4);
1401 check_result(result, "isc_buffer_allocate");
1402 isc_buffer_putuint16(b, DNS_OPT_NSID);
1403 isc_buffer_putuint16(b, 0);
1404 rdata->data = isc_buffer_base(b);
1405 rdata->length = isc_buffer_usedlength(b);
1406 dns_message_takebuffer(msg, &b);
1411 ISC_LIST_INIT(rdatalist->rdata);
1412 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1413 dns_rdatalist_tordataset(rdatalist, rdataset);
1414 result = dns_message_setopt(msg, rdataset);
1415 check_result(result, "dns_message_setopt");
1419 * Add a question section to a message, asking for the specified name,
1423 add_question(dns_message_t *message, dns_name_t *name,
1424 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype)
1426 dns_rdataset_t *rdataset;
1427 isc_result_t result;
1429 debug("add_question()");
1431 result = dns_message_gettemprdataset(message, &rdataset);
1432 check_result(result, "dns_message_gettemprdataset()");
1433 dns_rdataset_init(rdataset);
1434 dns_rdataset_makequestion(rdataset, rdclass, rdtype);
1435 ISC_LIST_APPEND(name->list, rdataset, link);
1439 * Check if we're done with all the queued lookups, which is true iff
1440 * all sockets, sends, and recvs are accounted for (counters == 0),
1441 * and the lookup list is empty.
1442 * If we are done, pass control back out to dighost_shutdown() (which is
1443 * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
1444 * a whole or reseed the lookup list.
1447 check_if_done(void) {
1448 debug("check_if_done()");
1449 debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
1450 if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
1452 INSIST(sockcount == 0);
1453 INSIST(recvcount == 0);
1454 debug("shutting down");
1460 * Clear out a query when we're done with it. WARNING: This routine
1461 * WILL invalidate the query pointer.
1464 clear_query(dig_query_t *query) {
1465 dig_lookup_t *lookup;
1467 REQUIRE(query != NULL);
1469 debug("clear_query(%p)", query);
1471 lookup = query->lookup;
1473 if (lookup->current_query == query)
1474 lookup->current_query = NULL;
1476 ISC_LIST_UNLINK(lookup->q, query, link);
1477 if (ISC_LINK_LINKED(&query->recvbuf, link))
1478 ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf,
1480 if (ISC_LINK_LINKED(&query->lengthbuf, link))
1481 ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf,
1483 INSIST(query->recvspace != NULL);
1484 if (query->sock != NULL) {
1485 isc_socket_detach(&query->sock);
1487 debug("sockcount=%d", sockcount);
1489 isc_mempool_put(commctx, query->recvspace);
1490 isc_buffer_invalidate(&query->recvbuf);
1491 isc_buffer_invalidate(&query->lengthbuf);
1492 if (query->waiting_senddone)
1493 query->pending_free = ISC_TRUE;
1495 isc_mem_free(mctx, query);
1499 * Try and clear out a lookup if we're done with it. Return ISC_TRUE if
1500 * the lookup was successfully cleared. If ISC_TRUE is returned, the
1501 * lookup pointer has been invalidated.
1503 static isc_boolean_t
1504 try_clear_lookup(dig_lookup_t *lookup) {
1507 REQUIRE(lookup != NULL);
1509 debug("try_clear_lookup(%p)", lookup);
1511 if (ISC_LIST_HEAD(lookup->q) != NULL) {
1513 q = ISC_LIST_HEAD(lookup->q);
1515 debug("query to %s still pending", q->servname);
1516 q = ISC_LIST_NEXT(q, link);
1523 * At this point, we know there are no queries on the lookup,
1524 * so can make it go away also.
1526 destroy_lookup(lookup);
1531 destroy_lookup(dig_lookup_t *lookup) {
1536 s = ISC_LIST_HEAD(lookup->my_server_list);
1538 debug("freeing server %p belonging to %p", s, lookup);
1540 s = ISC_LIST_NEXT(s, link);
1541 ISC_LIST_DEQUEUE(lookup->my_server_list,
1542 (dig_server_t *)ptr, link);
1543 isc_mem_free(mctx, ptr);
1545 if (lookup->sendmsg != NULL)
1546 dns_message_destroy(&lookup->sendmsg);
1547 if (lookup->querysig != NULL) {
1548 debug("freeing buffer %p", lookup->querysig);
1549 isc_buffer_free(&lookup->querysig);
1551 if (lookup->timer != NULL)
1552 isc_timer_detach(&lookup->timer);
1553 if (lookup->sendspace != NULL)
1554 isc_mempool_put(commctx, lookup->sendspace);
1556 if (lookup->tsigctx != NULL)
1557 dst_context_destroy(&lookup->tsigctx);
1559 isc_mem_free(mctx, lookup);
1563 * If we can, start the next lookup in the queue running.
1564 * This assumes that the lookup on the head of the queue hasn't been
1565 * started yet. It also removes the lookup from the head of the queue,
1566 * setting the current_lookup pointer pointing to it.
1569 start_lookup(void) {
1570 debug("start_lookup()");
1575 * If there's a current lookup running, we really shouldn't get
1578 INSIST(current_lookup == NULL);
1580 current_lookup = ISC_LIST_HEAD(lookup_list);
1582 * Put the current lookup somewhere so cancel_all can find it
1584 if (current_lookup != NULL) {
1585 ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
1587 if (current_lookup->do_topdown &&
1588 !current_lookup->rdtype_sigchaseset) {
1589 dst_key_t *trustedkey = NULL;
1590 isc_buffer_t *b = NULL;
1592 isc_result_t result;
1593 dns_name_t query_name;
1594 dns_name_t *key_name;
1597 result = get_trusted_key(mctx);
1598 if (result != ISC_R_SUCCESS) {
1599 printf("\n;; No trusted key, "
1600 "+sigchase option is disabled\n");
1601 current_lookup->sigchase = ISC_FALSE;
1604 dns_name_init(&query_name, NULL);
1605 nameFromString(current_lookup->textname, &query_name);
1607 for (i = 0; i < tk_list.nb_tk; i++) {
1608 key_name = dst_key_name(tk_list.key[i]);
1610 if (dns_name_issubdomain(&query_name,
1611 key_name) == ISC_TRUE)
1612 trustedkey = tk_list.key[i];
1614 * Verify temp is really the lowest
1618 if (trustedkey == NULL) {
1619 printf("\n;; The queried zone: ");
1620 dns_name_print(&query_name, stdout);
1621 printf(" isn't a subdomain of any Trusted Keys"
1622 ": +sigchase option is disable\n");
1623 current_lookup->sigchase = ISC_FALSE;
1624 free_name(&query_name, mctx);
1627 free_name(&query_name, mctx);
1629 current_lookup->rdtype_sigchase
1630 = current_lookup->rdtype;
1631 current_lookup->rdtype_sigchaseset
1632 = current_lookup->rdtypeset;
1633 current_lookup->rdtype = dns_rdatatype_ns;
1635 current_lookup->qrdtype_sigchase
1636 = current_lookup->qrdtype;
1637 current_lookup->qrdtype = dns_rdatatype_ns;
1639 current_lookup->rdclass_sigchase
1640 = current_lookup->rdclass;
1641 current_lookup->rdclass_sigchaseset
1642 = current_lookup->rdclassset;
1643 current_lookup->rdclass = dns_rdataclass_in;
1645 strncpy(current_lookup->textnamesigchase,
1646 current_lookup->textname, MXNAME);
1648 current_lookup->trace_root_sigchase = ISC_TRUE;
1650 result = isc_buffer_allocate(mctx, &b, BUFSIZE);
1651 check_result(result, "isc_buffer_allocate");
1652 result = dns_name_totext(dst_key_name(trustedkey),
1654 check_result(result, "dns_name_totext");
1655 isc_buffer_usedregion(b, &r);
1656 r.base[r.length] = '\0';
1657 strncpy(current_lookup->textname, (char*)r.base,
1659 isc_buffer_free(&b);
1661 nameFromString(current_lookup->textnamesigchase,
1664 dns_name_init(&chase_authority_name, NULL);
1668 setup_lookup(current_lookup);
1669 do_lookup(current_lookup);
1676 * If we can, clear the current lookup and start the next one running.
1677 * This calls try_clear_lookup, so may invalidate the lookup pointer.
1680 check_next_lookup(dig_lookup_t *lookup) {
1684 debug("check_next_lookup(%p)", lookup);
1686 if (ISC_LIST_HEAD(lookup->q) != NULL) {
1687 debug("still have a worker");
1690 if (try_clear_lookup(lookup)) {
1691 current_lookup = NULL;
1697 * Create and queue a new lookup as a followup to the current lookup,
1698 * based on the supplied message and section. This is used in trace and
1699 * name server search modes to start a new lookup using servers from
1700 * NS records in a reply. Returns the number of followup lookups made.
1703 followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section)
1705 dig_lookup_t *lookup = NULL;
1706 dig_server_t *srv = NULL;
1707 dns_rdataset_t *rdataset = NULL;
1708 dns_rdata_t rdata = DNS_RDATA_INIT;
1709 dns_name_t *name = NULL;
1710 isc_result_t result;
1711 isc_boolean_t success = ISC_FALSE;
1714 isc_result_t lresult, addresses_result;
1715 char bad_namestr[DNS_NAME_FORMATSIZE];
1717 isc_boolean_t horizontal = ISC_FALSE, bad = ISC_FALSE;
1721 debug("following up %s", query->lookup->textname);
1723 addresses_result = ISC_R_SUCCESS;
1724 bad_namestr[0] = '\0';
1725 for (result = dns_message_firstname(msg, section);
1726 result == ISC_R_SUCCESS;
1727 result = dns_message_nextname(msg, section)) {
1729 dns_message_currentname(msg, section, &name);
1731 if (section == DNS_SECTION_AUTHORITY) {
1733 result = dns_message_findtype(name, dns_rdatatype_soa,
1735 if (result == ISC_R_SUCCESS)
1739 result = dns_message_findtype(name, dns_rdatatype_ns, 0,
1741 if (result != ISC_R_SUCCESS)
1744 debug("found NS set");
1746 if (query->lookup->trace && !query->lookup->trace_root) {
1747 dns_namereln_t namereln;
1748 unsigned int nlabels;
1751 domain = dns_fixedname_name(&query->lookup->fdomain);
1752 namereln = dns_name_fullcompare(name, domain,
1754 if (namereln == dns_namereln_equal) {
1756 printf(";; BAD (HORIZONTAL) REFERRAL\n");
1757 horizontal = ISC_TRUE;
1758 } else if (namereln != dns_namereln_subdomain) {
1760 printf(";; BAD REFERRAL\n");
1766 for (result = dns_rdataset_first(rdataset);
1767 result == ISC_R_SUCCESS;
1768 result = dns_rdataset_next(rdataset)) {
1769 char namestr[DNS_NAME_FORMATSIZE];
1772 if (query->lookup->trace_root &&
1773 query->lookup->nsfound >= MXSERV)
1776 dns_rdataset_current(rdataset, &rdata);
1778 query->lookup->nsfound++;
1779 result = dns_rdata_tostruct(&rdata, &ns, NULL);
1780 check_result(result, "dns_rdata_tostruct");
1781 dns_name_format(&ns.name, namestr, sizeof(namestr));
1782 dns_rdata_freestruct(&ns);
1784 /* Initialize lookup if we've not yet */
1785 debug("found NS %s", namestr);
1789 lookup = requeue_lookup(query->lookup,
1791 cancel_lookup(query->lookup);
1792 lookup->doing_xfr = ISC_FALSE;
1793 if (!lookup->trace_root &&
1794 section == DNS_SECTION_ANSWER)
1795 lookup->trace = ISC_FALSE;
1797 lookup->trace = query->lookup->trace;
1798 lookup->ns_search_only =
1799 query->lookup->ns_search_only;
1800 lookup->trace_root = ISC_FALSE;
1801 if (lookup->ns_search_only)
1802 lookup->recurse = ISC_FALSE;
1803 domain = dns_fixedname_name(&lookup->fdomain);
1804 dns_name_copy(name, domain, NULL);
1806 debug("adding server %s", namestr);
1807 num = getaddresses(lookup, namestr, &lresult);
1808 if (lresult != ISC_R_SUCCESS) {
1809 debug("couldn't get address for '%s': %s",
1810 namestr, isc_result_totext(lresult));
1811 if (addresses_result == ISC_R_SUCCESS) {
1812 addresses_result = lresult;
1813 strcpy(bad_namestr, namestr);
1817 dns_rdata_reset(&rdata);
1820 if (numLookups == 0 && addresses_result != ISC_R_SUCCESS) {
1821 fatal("couldn't get address for '%s': %s",
1822 bad_namestr, isc_result_totext(result));
1825 if (lookup == NULL &&
1826 section == DNS_SECTION_ANSWER &&
1827 (query->lookup->trace || query->lookup->ns_search_only))
1828 return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY));
1831 * Randomize the order the nameserver will be tried.
1833 if (numLookups > 1) {
1835 dig_serverlist_t my_server_list;
1838 ISC_LIST_INIT(my_server_list);
1841 for (srv = ISC_LIST_HEAD(lookup->my_server_list);
1843 srv = ISC_LIST_HEAD(lookup->my_server_list)) {
1847 next = ISC_LIST_NEXT(srv, link);
1848 while (j-- > 0 && next != NULL) {
1850 next = ISC_LIST_NEXT(srv, link);
1852 ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link);
1853 ISC_LIST_APPEND(my_server_list, srv, link);
1856 ISC_LIST_APPENDLIST(lookup->my_server_list,
1857 my_server_list, link);
1860 return (numLookups);
1864 * Create and queue a new lookup using the next origin from the search
1865 * list, read in setup_system().
1867 * Return ISC_TRUE iff there was another searchlist entry.
1869 static isc_boolean_t
1870 next_origin(dig_query_t *query) {
1871 dig_lookup_t *lookup;
1872 dig_searchlist_t *search;
1876 debug("next_origin()");
1877 debug("following up %s", query->lookup->textname);
1881 * We're not using a search list, so don't even think
1882 * about finding the next entry.
1885 if (query->lookup->origin == NULL && !query->lookup->need_search)
1887 * Then we just did rootorg; there's nothing left.
1890 if (query->lookup->origin == NULL && query->lookup->need_search) {
1891 lookup = requeue_lookup(query->lookup, ISC_TRUE);
1892 lookup->origin = ISC_LIST_HEAD(search_list);
1893 lookup->need_search = ISC_FALSE;
1895 search = ISC_LIST_NEXT(query->lookup->origin, link);
1896 if (search == NULL && query->lookup->done_as_is)
1898 lookup = requeue_lookup(query->lookup, ISC_TRUE);
1899 lookup->origin = search;
1901 cancel_lookup(query->lookup);
1906 * Insert an SOA record into the sendmessage in a lookup. Used for
1907 * creating IXFR queries.
1910 insert_soa(dig_lookup_t *lookup) {
1911 isc_result_t result;
1912 dns_rdata_soa_t soa;
1913 dns_rdata_t *rdata = NULL;
1914 dns_rdatalist_t *rdatalist = NULL;
1915 dns_rdataset_t *rdataset = NULL;
1916 dns_name_t *soaname = NULL;
1918 debug("insert_soa()");
1920 soa.serial = lookup->ixfr_serial;
1925 soa.common.rdclass = lookup->rdclass;
1926 soa.common.rdtype = dns_rdatatype_soa;
1928 dns_name_init(&soa.origin, NULL);
1929 dns_name_init(&soa.contact, NULL);
1931 dns_name_clone(dns_rootname, &soa.origin);
1932 dns_name_clone(dns_rootname, &soa.contact);
1934 isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
1935 sizeof(lookup->rdatastore));
1937 result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
1938 check_result(result, "dns_message_gettemprdata");
1940 result = dns_rdata_fromstruct(rdata, lookup->rdclass,
1941 dns_rdatatype_soa, &soa,
1943 check_result(result, "isc_rdata_fromstruct");
1945 result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
1946 check_result(result, "dns_message_gettemprdatalist");
1948 result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
1949 check_result(result, "dns_message_gettemprdataset");
1951 dns_rdatalist_init(rdatalist);
1952 rdatalist->type = dns_rdatatype_soa;
1953 rdatalist->rdclass = lookup->rdclass;
1954 rdatalist->covers = 0;
1956 ISC_LIST_INIT(rdatalist->rdata);
1957 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1959 dns_rdataset_init(rdataset);
1960 dns_rdatalist_tordataset(rdatalist, rdataset);
1962 result = dns_message_gettempname(lookup->sendmsg, &soaname);
1963 check_result(result, "dns_message_gettempname");
1964 dns_name_init(soaname, NULL);
1965 dns_name_clone(lookup->name, soaname);
1966 ISC_LIST_INIT(soaname->list);
1967 ISC_LIST_APPEND(soaname->list, rdataset, link);
1968 dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
1972 * Setup the supplied lookup structure, making it ready to start sending
1973 * queries to servers. Create and initialize the message to be sent as
1974 * well as the query structures and buffer space for the replies. If the
1975 * server list is empty, clone it from the system default list.
1978 setup_lookup(dig_lookup_t *lookup) {
1979 isc_result_t result;
1985 dns_compress_t cctx;
1989 char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME];
1993 result = dns_name_settotextfilter(output_filter);
1994 check_result(result, "dns_name_settotextfilter");
1997 REQUIRE(lookup != NULL);
2000 debug("setup_lookup(%p)", lookup);
2002 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
2004 check_result(result, "dns_message_create");
2006 if (lookup->new_search) {
2007 debug("resetting lookup counter.");
2011 if (ISC_LIST_EMPTY(lookup->my_server_list)) {
2012 debug("cloning server list");
2013 clone_server_list(server_list, &lookup->my_server_list);
2015 result = dns_message_gettempname(lookup->sendmsg, &lookup->name);
2016 check_result(result, "dns_message_gettempname");
2017 dns_name_init(lookup->name, NULL);
2019 isc_buffer_init(&lookup->namebuf, lookup->namespace,
2020 sizeof(lookup->namespace));
2021 isc_buffer_init(&lookup->onamebuf, lookup->onamespace,
2022 sizeof(lookup->onamespace));
2026 * We cannot convert `textname' and `origin' separately.
2027 * `textname' doesn't contain TLD, but local mapping needs
2030 mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname,
2031 utf8_textname, sizeof(utf8_textname));
2032 idn_check_result(mr, "convert textname to UTF-8");
2036 * If the name has too many dots, force the origin to be NULL
2037 * (which produces an absolute lookup). Otherwise, take the origin
2038 * we have if there's one in the struct already. If it's NULL,
2039 * take the first entry in the searchlist iff either usesearch
2040 * is TRUE or we got a domain line in the resolv.conf file.
2042 if (lookup->new_search) {
2044 if ((count_dots(utf8_textname) >= ndots) || !usesearch) {
2045 lookup->origin = NULL; /* Force abs lookup */
2046 lookup->done_as_is = ISC_TRUE;
2047 lookup->need_search = usesearch;
2048 } else if (lookup->origin == NULL && usesearch) {
2049 lookup->origin = ISC_LIST_HEAD(search_list);
2050 lookup->need_search = ISC_FALSE;
2053 if ((count_dots(lookup->textname) >= ndots) || !usesearch) {
2054 lookup->origin = NULL; /* Force abs lookup */
2055 lookup->done_as_is = ISC_TRUE;
2056 lookup->need_search = usesearch;
2057 } else if (lookup->origin == NULL && usesearch) {
2058 lookup->origin = ISC_LIST_HEAD(search_list);
2059 lookup->need_search = ISC_FALSE;
2065 if (lookup->origin != NULL) {
2066 mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP,
2067 lookup->origin->origin, utf8_origin,
2068 sizeof(utf8_origin));
2069 idn_check_result(mr, "convert origin to UTF-8");
2070 mr = append_textname(utf8_textname, utf8_origin,
2071 sizeof(utf8_textname));
2072 idn_check_result(mr, "append origin to textname");
2074 mr = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP |
2075 IDN_IDNCONV | IDN_LENCHECK, utf8_textname,
2076 idn_textname, sizeof(idn_textname));
2077 idn_check_result(mr, "convert UTF-8 textname to IDN encoding");
2079 if (lookup->origin != NULL) {
2080 debug("trying origin %s", lookup->origin->origin);
2081 result = dns_message_gettempname(lookup->sendmsg,
2083 check_result(result, "dns_message_gettempname");
2084 dns_name_init(lookup->oname, NULL);
2085 /* XXX Helper funct to conv char* to name? */
2086 len = strlen(lookup->origin->origin);
2087 isc_buffer_init(&b, lookup->origin->origin, len);
2088 isc_buffer_add(&b, len);
2089 result = dns_name_fromtext(lookup->oname, &b, dns_rootname,
2090 0, &lookup->onamebuf);
2091 if (result != ISC_R_SUCCESS) {
2092 dns_message_puttempname(lookup->sendmsg,
2094 dns_message_puttempname(lookup->sendmsg,
2096 fatal("'%s' is not in legal name syntax (%s)",
2097 lookup->origin->origin,
2098 isc_result_totext(result));
2100 if (lookup->trace && lookup->trace_root) {
2101 dns_name_clone(dns_rootname, lookup->name);
2103 len = strlen(lookup->textname);
2104 isc_buffer_init(&b, lookup->textname, len);
2105 isc_buffer_add(&b, len);
2106 result = dns_name_fromtext(lookup->name, &b,
2110 if (result != ISC_R_SUCCESS) {
2111 dns_message_puttempname(lookup->sendmsg,
2113 dns_message_puttempname(lookup->sendmsg,
2115 fatal("'%s' is not in legal name syntax (%s)",
2116 lookup->textname, isc_result_totext(result));
2118 dns_message_puttempname(lookup->sendmsg, &lookup->oname);
2122 debug("using root origin");
2123 if (lookup->trace && lookup->trace_root)
2124 dns_name_clone(dns_rootname, lookup->name);
2127 len = strlen(idn_textname);
2128 isc_buffer_init(&b, idn_textname, len);
2129 isc_buffer_add(&b, len);
2130 result = dns_name_fromtext(lookup->name, &b,
2134 len = strlen(lookup->textname);
2135 isc_buffer_init(&b, lookup->textname, len);
2136 isc_buffer_add(&b, len);
2137 result = dns_name_fromtext(lookup->name, &b,
2142 if (result != ISC_R_SUCCESS) {
2143 dns_message_puttempname(lookup->sendmsg,
2145 isc_buffer_init(&b, store, MXNAME);
2146 fatal("'%s' is not a legal name "
2147 "(%s)", lookup->textname,
2148 isc_result_totext(result));
2151 dns_name_format(lookup->name, store, sizeof(store));
2152 trying(store, lookup);
2153 INSIST(dns_name_isabsolute(lookup->name));
2155 isc_random_get(&id);
2156 lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
2157 lookup->sendmsg->opcode = dns_opcode_query;
2158 lookup->msgcounter = 0;
2160 * If this is a trace request, completely disallow recursion, since
2161 * it's meaningless for traces.
2163 if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root))
2164 lookup->recurse = ISC_FALSE;
2166 if (lookup->recurse &&
2167 lookup->rdtype != dns_rdatatype_axfr &&
2168 lookup->rdtype != dns_rdatatype_ixfr) {
2169 debug("recursive query");
2170 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD;
2174 if (lookup->aaonly) {
2176 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA;
2179 if (lookup->adflag) {
2181 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD;
2184 if (lookup->cdflag) {
2186 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD;
2189 dns_message_addname(lookup->sendmsg, lookup->name,
2190 DNS_SECTION_QUESTION);
2192 if (lookup->trace && lookup->trace_root) {
2193 lookup->qrdtype = lookup->rdtype;
2194 lookup->rdtype = dns_rdatatype_ns;
2197 if ((lookup->rdtype == dns_rdatatype_axfr) ||
2198 (lookup->rdtype == dns_rdatatype_ixfr)) {
2200 * Force TCP mode if we're doing an axfr.
2202 if (lookup->rdtype == dns_rdatatype_axfr) {
2203 lookup->doing_xfr = ISC_TRUE;
2204 lookup->tcp_mode = ISC_TRUE;
2205 } else if (lookup->tcp_mode) {
2206 lookup->doing_xfr = ISC_TRUE;
2210 add_question(lookup->sendmsg, lookup->name, lookup->rdclass,
2214 if (lookup->rdtype == dns_rdatatype_ixfr)
2217 /* XXX Insist this? */
2218 lookup->tsigctx = NULL;
2219 lookup->querysig = NULL;
2221 debug("initializing keys");
2222 result = dns_message_settsigkey(lookup->sendmsg, key);
2223 check_result(result, "dns_message_settsigkey");
2226 lookup->sendspace = isc_mempool_get(commctx);
2227 if (lookup->sendspace == NULL)
2228 fatal("memory allocation failure");
2230 result = dns_compress_init(&cctx, -1, mctx);
2231 check_result(result, "dns_compress_init");
2233 debug("starting to render the message");
2234 isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE);
2235 result = dns_message_renderbegin(lookup->sendmsg, &cctx,
2236 &lookup->renderbuf);
2237 check_result(result, "dns_message_renderbegin");
2238 if (lookup->udpsize > 0 || lookup->dnssec || lookup->edns > -1) {
2239 if (lookup->udpsize == 0)
2240 lookup->udpsize = 4096;
2241 if (lookup->edns < 0)
2243 add_opt(lookup->sendmsg, lookup->udpsize,
2244 lookup->edns, lookup->dnssec, lookup->nsid);
2247 result = dns_message_rendersection(lookup->sendmsg,
2248 DNS_SECTION_QUESTION, 0);
2249 check_result(result, "dns_message_rendersection");
2250 result = dns_message_rendersection(lookup->sendmsg,
2251 DNS_SECTION_AUTHORITY, 0);
2252 check_result(result, "dns_message_rendersection");
2253 result = dns_message_renderend(lookup->sendmsg);
2254 check_result(result, "dns_message_renderend");
2255 debug("done rendering");
2257 dns_compress_invalidate(&cctx);
2260 * Force TCP mode if the request is larger than 512 bytes.
2262 if (isc_buffer_usedlength(&lookup->renderbuf) > 512)
2263 lookup->tcp_mode = ISC_TRUE;
2265 lookup->pending = ISC_FALSE;
2267 for (serv = ISC_LIST_HEAD(lookup->my_server_list);
2269 serv = ISC_LIST_NEXT(serv, link)) {
2270 query = isc_mem_allocate(mctx, sizeof(dig_query_t));
2272 fatal("memory allocation failure in %s:%d",
2273 __FILE__, __LINE__);
2274 debug("create query %p linked to lookup %p",
2276 query->lookup = lookup;
2277 query->waiting_connect = ISC_FALSE;
2278 query->waiting_senddone = ISC_FALSE;
2279 query->pending_free = ISC_FALSE;
2280 query->recv_made = ISC_FALSE;
2281 query->first_pass = ISC_TRUE;
2282 query->first_soa_rcvd = ISC_FALSE;
2283 query->second_rr_rcvd = ISC_FALSE;
2284 query->first_repeat_rcvd = ISC_FALSE;
2285 query->warn_id = ISC_TRUE;
2286 query->first_rr_serial = 0;
2287 query->second_rr_serial = 0;
2288 query->servname = serv->servername;
2289 query->userarg = serv->userarg;
2290 query->rr_count = 0;
2291 query->msg_count = 0;
2292 query->byte_count = 0;
2293 ISC_LINK_INIT(query, link);
2294 ISC_LIST_INIT(query->recvlist);
2295 ISC_LIST_INIT(query->lengthlist);
2297 query->recvspace = isc_mempool_get(commctx);
2298 if (query->recvspace == NULL)
2299 fatal("memory allocation failure");
2301 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
2302 isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
2303 isc_buffer_init(&query->slbuf, query->slspace, 2);
2304 query->sendbuf = lookup->renderbuf;
2306 ISC_LINK_INIT(query, link);
2307 ISC_LIST_ENQUEUE(lookup->q, query, link);
2309 /* XXX qrflag, print_query, etc... */
2310 if (!ISC_LIST_EMPTY(lookup->q) && qr) {
2312 printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg,
2318 * Event handler for send completion. Track send counter, and clear out
2319 * the query if the send was canceled.
2322 send_done(isc_task_t *_task, isc_event_t *event) {
2323 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
2324 isc_buffer_t *b = NULL;
2325 dig_query_t *query, *next;
2328 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
2334 debug("send_done()");
2336 debug("sendcount=%d", sendcount);
2337 INSIST(sendcount >= 0);
2339 for (b = ISC_LIST_HEAD(sevent->bufferlist);
2341 b = ISC_LIST_HEAD(sevent->bufferlist))
2342 ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2344 query = event->ev_arg;
2345 query->waiting_senddone = ISC_FALSE;
2348 if (l->ns_search_only && !l->trace_root && !l->tcp_mode) {
2349 debug("sending next, since searching");
2350 next = ISC_LIST_NEXT(query, link);
2355 isc_event_free(&event);
2357 if (query->pending_free)
2358 isc_mem_free(mctx, query);
2365 * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
2366 * IO sockets. The cancel handlers should take care of cleaning up the
2367 * query and lookup structures
2370 cancel_lookup(dig_lookup_t *lookup) {
2371 dig_query_t *query, *next;
2373 debug("cancel_lookup()");
2374 query = ISC_LIST_HEAD(lookup->q);
2375 while (query != NULL) {
2376 next = ISC_LIST_NEXT(query, link);
2377 if (query->sock != NULL) {
2378 isc_socket_cancel(query->sock, global_task,
2379 ISC_SOCKCANCEL_ALL);
2386 if (lookup->timer != NULL)
2387 isc_timer_detach(&lookup->timer);
2388 lookup->pending = ISC_FALSE;
2389 lookup->retries = 0;
2393 bringup_timer(dig_query_t *query, unsigned int default_timeout) {
2395 unsigned int local_timeout;
2396 isc_result_t result;
2398 debug("bringup_timer()");
2400 * If the timer already exists, that means we're calling this
2401 * a second time (for a retry). Don't need to recreate it,
2405 if (ISC_LIST_NEXT(query, link) != NULL)
2406 local_timeout = SERVER_TIMEOUT;
2409 local_timeout = default_timeout;
2411 local_timeout = timeout;
2413 debug("have local timeout of %d", local_timeout);
2414 isc_interval_set(&l->interval, local_timeout, 0);
2415 if (l->timer != NULL)
2416 isc_timer_detach(&l->timer);
2417 result = isc_timer_create(timermgr, isc_timertype_once, NULL,
2418 &l->interval, global_task, connect_timeout,
2420 check_result(result, "isc_timer_create");
2424 force_timeout(dig_lookup_t *l, dig_query_t *query) {
2427 event = isc_event_allocate(mctx, query, ISC_TIMEREVENT_IDLE,
2429 sizeof(isc_event_t));
2430 if (event == NULL) {
2431 fatal("isc_event_allocate: %s",
2432 isc_result_totext(ISC_R_NOMEMORY));
2434 isc_task_send(global_task, &event);
2437 * The timer may have expired if, for example, get_address() takes
2438 * long time and the timer was running on a different thread.
2439 * We need to cancel the possible timeout event not to confuse
2440 * ourselves due to the duplicate events.
2442 if (l->timer != NULL)
2443 isc_timer_detach(&l->timer);
2448 connect_done(isc_task_t *task, isc_event_t *event);
2451 * Unlike send_udp, this can't be called multiple times with the same
2452 * query. When we retry TCP, we requeue the whole lookup, which should
2456 send_tcp_connect(dig_query_t *query) {
2457 isc_result_t result;
2461 debug("send_tcp_connect(%p)", query);
2464 query->waiting_connect = ISC_TRUE;
2465 query->lookup->current_query = query;
2466 result = get_address(query->servname, port, &query->sockaddr);
2467 if (result != ISC_R_SUCCESS) {
2469 * This servname doesn't have an address. Try the next server
2470 * by triggering an immediate 'timeout' (we lie, but the effect
2473 force_timeout(l, query);
2477 if (specified_source &&
2478 (isc_sockaddr_pf(&query->sockaddr) !=
2479 isc_sockaddr_pf(&bind_address))) {
2480 printf(";; Skipping server %s, incompatible "
2481 "address family\n", query->servname);
2482 query->waiting_connect = ISC_FALSE;
2483 next = ISC_LIST_NEXT(query, link);
2487 printf(";; No acceptable nameservers\n");
2488 check_next_lookup(l);
2491 send_tcp_connect(next);
2494 INSIST(query->sock == NULL);
2495 result = isc_socket_create(socketmgr,
2496 isc_sockaddr_pf(&query->sockaddr),
2497 isc_sockettype_tcp, &query->sock);
2498 check_result(result, "isc_socket_create");
2500 debug("sockcount=%d", sockcount);
2501 if (specified_source)
2502 result = isc_socket_bind(query->sock, &bind_address,
2503 ISC_SOCKET_REUSEADDRESS);
2505 if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
2507 isc_sockaddr_any(&bind_any);
2509 isc_sockaddr_any6(&bind_any);
2510 result = isc_socket_bind(query->sock, &bind_any, 0);
2512 check_result(result, "isc_socket_bind");
2513 bringup_timer(query, TCP_TIMEOUT);
2514 result = isc_socket_connect(query->sock, &query->sockaddr,
2515 global_task, connect_done, query);
2516 check_result(result, "isc_socket_connect");
2518 * If we're at the endgame of a nameserver search, we need to
2519 * immediately bring up all the queries. Do it here.
2521 if (l->ns_search_only && !l->trace_root) {
2522 debug("sending next, since searching");
2523 next = ISC_LIST_NEXT(query, link);
2525 send_tcp_connect(next);
2530 * Send a UDP packet to the remote nameserver, possible starting the
2531 * recv action as well. Also make sure that the timer is running and
2532 * is properly reset.
2535 send_udp(dig_query_t *query) {
2536 dig_lookup_t *l = NULL;
2537 isc_result_t result;
2539 debug("send_udp(%p)", query);
2542 bringup_timer(query, UDP_TIMEOUT);
2543 l->current_query = query;
2544 debug("working on lookup %p, query %p", query->lookup, query);
2545 if (!query->recv_made) {
2546 /* XXX Check the sense of this, need assertion? */
2547 query->waiting_connect = ISC_FALSE;
2548 result = get_address(query->servname, port, &query->sockaddr);
2549 if (result != ISC_R_SUCCESS) {
2550 /* This servname doesn't have an address. */
2551 force_timeout(l, query);
2555 result = isc_socket_create(socketmgr,
2556 isc_sockaddr_pf(&query->sockaddr),
2557 isc_sockettype_udp, &query->sock);
2558 check_result(result, "isc_socket_create");
2560 debug("sockcount=%d", sockcount);
2561 if (specified_source) {
2562 result = isc_socket_bind(query->sock, &bind_address,
2563 ISC_SOCKET_REUSEADDRESS);
2565 isc_sockaddr_anyofpf(&bind_any,
2566 isc_sockaddr_pf(&query->sockaddr));
2567 result = isc_socket_bind(query->sock, &bind_any, 0);
2569 check_result(result, "isc_socket_bind");
2571 query->recv_made = ISC_TRUE;
2572 ISC_LINK_INIT(&query->recvbuf, link);
2573 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf,
2575 debug("recving with lookup=%p, query=%p, sock=%p",
2576 query->lookup, query, query->sock);
2577 result = isc_socket_recvv(query->sock, &query->recvlist, 1,
2578 global_task, recv_done, query);
2579 check_result(result, "isc_socket_recvv");
2581 debug("recvcount=%d", recvcount);
2583 ISC_LIST_INIT(query->sendlist);
2584 ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link);
2585 debug("sending a request");
2586 TIME_NOW(&query->time_sent);
2587 INSIST(query->sock != NULL);
2588 query->waiting_senddone = ISC_TRUE;
2589 result = isc_socket_sendtov(query->sock, &query->sendlist,
2590 global_task, send_done, query,
2591 &query->sockaddr, NULL);
2592 check_result(result, "isc_socket_sendtov");
2597 * IO timeout handler, used for both connect and recv timeouts. If
2598 * retries are still allowed, either resend the UDP packet or queue a
2599 * new TCP lookup. Otherwise, cancel the lookup.
2602 connect_timeout(isc_task_t *task, isc_event_t *event) {
2603 dig_lookup_t *l = NULL;
2604 dig_query_t *query = NULL, *cq;
2607 REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE);
2609 debug("connect_timeout()");
2613 query = l->current_query;
2614 isc_event_free(&event);
2618 if ((query != NULL) && (query->lookup->current_query != NULL) &&
2619 (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) {
2620 debug("trying next server...");
2621 cq = query->lookup->current_query;
2623 send_udp(ISC_LIST_NEXT(cq, link));
2625 if (query->sock != NULL)
2626 isc_socket_cancel(query->sock, NULL,
2627 ISC_SOCKCANCEL_ALL);
2628 send_tcp_connect(ISC_LIST_NEXT(cq, link));
2634 if (l->retries > 1) {
2637 debug("resending UDP request to first server");
2638 send_udp(ISC_LIST_HEAD(l->q));
2640 debug("making new TCP request, %d tries left",
2643 requeue_lookup(l, ISC_TRUE);
2645 check_next_lookup(l);
2648 fputs(l->cmdline, stdout);
2649 printf(";; connection timed out; no servers could be "
2652 check_next_lookup(l);
2660 * Event handler for the TCP recv which gets the length header of TCP
2661 * packets. Start the next recv of length bytes.
2664 tcp_length_done(isc_task_t *task, isc_event_t *event) {
2665 isc_socketevent_t *sevent;
2666 isc_buffer_t *b = NULL;
2667 isc_result_t result;
2668 dig_query_t *query = NULL;
2670 isc_uint16_t length;
2672 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
2677 debug("tcp_length_done()");
2680 sevent = (isc_socketevent_t *)event;
2681 query = event->ev_arg;
2684 INSIST(recvcount >= 0);
2686 b = ISC_LIST_HEAD(sevent->bufferlist);
2687 INSIST(b == &query->lengthbuf);
2688 ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2690 if (sevent->result == ISC_R_CANCELED) {
2691 isc_event_free(&event);
2694 check_next_lookup(l);
2698 if (sevent->result != ISC_R_SUCCESS) {
2699 char sockstr[ISC_SOCKADDR_FORMATSIZE];
2700 isc_sockaddr_format(&query->sockaddr, sockstr,
2702 printf(";; communications error to %s: %s\n",
2703 sockstr, isc_result_totext(sevent->result));
2705 isc_socket_detach(&query->sock);
2707 debug("sockcount=%d", sockcount);
2708 INSIST(sockcount >= 0);
2709 isc_event_free(&event);
2711 check_next_lookup(l);
2715 length = isc_buffer_getuint16(b);
2717 isc_event_free(&event);
2718 launch_next_query(query, ISC_FALSE);
2724 * Even though the buffer was already init'ed, we need
2725 * to redo it now, to force the length we want.
2727 isc_buffer_invalidate(&query->recvbuf);
2728 isc_buffer_init(&query->recvbuf, query->recvspace, length);
2729 ENSURE(ISC_LIST_EMPTY(query->recvlist));
2730 ISC_LINK_INIT(&query->recvbuf, link);
2731 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
2732 debug("recving with lookup=%p, query=%p", query->lookup, query);
2733 result = isc_socket_recvv(query->sock, &query->recvlist, length, task,
2735 check_result(result, "isc_socket_recvv");
2737 debug("resubmitted recv request with length %d, recvcount=%d",
2739 isc_event_free(&event);
2744 * For transfers that involve multiple recvs (XFR's in particular),
2745 * launch the next recv.
2748 launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
2749 isc_result_t result;
2754 debug("launch_next_query()");
2756 if (!query->lookup->pending) {
2757 debug("ignoring launch_next_query because !pending");
2758 isc_socket_detach(&query->sock);
2760 debug("sockcount=%d", sockcount);
2761 INSIST(sockcount >= 0);
2762 query->waiting_connect = ISC_FALSE;
2765 check_next_lookup(l);
2769 isc_buffer_clear(&query->slbuf);
2770 isc_buffer_clear(&query->lengthbuf);
2771 isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->sendbuf.used);
2772 ISC_LIST_INIT(query->sendlist);
2773 ISC_LINK_INIT(&query->slbuf, link);
2774 ISC_LIST_ENQUEUE(query->sendlist, &query->slbuf, link);
2775 if (include_question)
2776 ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link);
2777 ISC_LINK_INIT(&query->lengthbuf, link);
2778 ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
2780 result = isc_socket_recvv(query->sock, &query->lengthlist, 0,
2781 global_task, tcp_length_done, query);
2782 check_result(result, "isc_socket_recvv");
2784 debug("recvcount=%d", recvcount);
2785 if (!query->first_soa_rcvd) {
2786 debug("sending a request in launch_next_query");
2787 TIME_NOW(&query->time_sent);
2788 query->waiting_senddone = ISC_TRUE;
2789 result = isc_socket_sendv(query->sock, &query->sendlist,
2790 global_task, send_done, query);
2791 check_result(result, "isc_socket_sendv");
2793 debug("sendcount=%d", sendcount);
2795 query->waiting_connect = ISC_FALSE;
2797 check_next_lookup(query->lookup);
2803 * Event handler for TCP connect complete. Make sure the connection was
2804 * successful, then pass into launch_next_query to actually send the
2808 connect_done(isc_task_t *task, isc_event_t *event) {
2809 isc_socketevent_t *sevent = NULL;
2810 dig_query_t *query = NULL, *next;
2815 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
2818 debug("connect_done()");
2821 sevent = (isc_socketevent_t *)event;
2822 query = sevent->ev_arg;
2824 INSIST(query->waiting_connect);
2826 query->waiting_connect = ISC_FALSE;
2828 if (sevent->result == ISC_R_CANCELED) {
2829 debug("in cancel handler");
2830 isc_socket_detach(&query->sock);
2831 INSIST(sockcount > 0);
2833 debug("sockcount=%d", sockcount);
2834 query->waiting_connect = ISC_FALSE;
2835 isc_event_free(&event);
2838 check_next_lookup(l);
2842 if (sevent->result != ISC_R_SUCCESS) {
2843 char sockstr[ISC_SOCKADDR_FORMATSIZE];
2845 debug("unsuccessful connection: %s",
2846 isc_result_totext(sevent->result));
2847 isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
2848 if (sevent->result != ISC_R_CANCELED)
2849 printf(";; Connection to %s(%s) for %s failed: "
2851 query->servname, query->lookup->textname,
2852 isc_result_totext(sevent->result));
2853 isc_socket_detach(&query->sock);
2855 INSIST(sockcount >= 0);
2856 /* XXX Clean up exitcodes */
2859 debug("sockcount=%d", sockcount);
2860 query->waiting_connect = ISC_FALSE;
2861 isc_event_free(&event);
2863 if (l->current_query != NULL)
2864 next = ISC_LIST_NEXT(l->current_query, link);
2869 bringup_timer(next, TCP_TIMEOUT);
2870 send_tcp_connect(next);
2872 check_next_lookup(l);
2877 launch_next_query(query, ISC_TRUE);
2878 isc_event_free(&event);
2883 * Check if the ongoing XFR needs more data before it's complete, using
2884 * the semantics of IXFR and AXFR protocols. Much of the complexity of
2885 * this routine comes from determining when an IXFR is complete.
2886 * ISC_FALSE means more data is on the way, and the recv has been issued.
2888 static isc_boolean_t
2889 check_for_more_data(dig_query_t *query, dns_message_t *msg,
2890 isc_socketevent_t *sevent)
2892 dns_rdataset_t *rdataset = NULL;
2893 dns_rdata_t rdata = DNS_RDATA_INIT;
2894 dns_rdata_soa_t soa;
2895 isc_uint32_t ixfr_serial = query->lookup->ixfr_serial, serial;
2896 isc_result_t result;
2897 isc_boolean_t ixfr = query->lookup->rdtype == dns_rdatatype_ixfr;
2898 isc_boolean_t axfr = query->lookup->rdtype == dns_rdatatype_axfr;
2900 debug("check_for_more_data()");
2903 * By the time we're in this routine, we know we're doing
2904 * either an AXFR or IXFR. If there's no second_rr_type,
2905 * then we don't yet know which kind of answer we got back
2906 * from the server. Here, we're going to walk through the
2907 * rr's in the message, acting as necessary whenever we hit
2912 query->byte_count += sevent->n;
2913 result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
2914 if (result != ISC_R_SUCCESS) {
2915 puts("; Transfer failed.");
2921 dns_message_currentname(msg, DNS_SECTION_ANSWER,
2923 for (rdataset = ISC_LIST_HEAD(name->list);
2925 rdataset = ISC_LIST_NEXT(rdataset, link)) {
2926 result = dns_rdataset_first(rdataset);
2927 if (result != ISC_R_SUCCESS)
2931 dns_rdata_reset(&rdata);
2932 dns_rdataset_current(rdataset, &rdata);
2934 * If this is the first rr, make sure
2937 if ((!query->first_soa_rcvd) &&
2938 (rdata.type != dns_rdatatype_soa)) {
2939 puts("; Transfer failed. "
2940 "Didn't start with SOA answer.");
2943 if ((!query->second_rr_rcvd) &&
2944 (rdata.type != dns_rdatatype_soa)) {
2945 query->second_rr_rcvd = ISC_TRUE;
2946 query->second_rr_serial = 0;
2947 debug("got the second rr as nonsoa");
2953 * If the record is anything except an SOA
2954 * now, just continue on...
2956 if (rdata.type != dns_rdatatype_soa)
2959 /* Now we have an SOA. Work with it. */
2960 debug("got an SOA");
2961 result = dns_rdata_tostruct(&rdata, &soa, NULL);
2962 check_result(result, "dns_rdata_tostruct");
2963 serial = soa.serial;
2964 dns_rdata_freestruct(&soa);
2965 if (!query->first_soa_rcvd) {
2966 query->first_soa_rcvd = ISC_TRUE;
2967 query->first_rr_serial = serial;
2968 debug("this is the first serial %u",
2970 if (ixfr && isc_serial_ge(ixfr_serial,
2972 debug("got up to date "
2979 debug("doing axfr, got second SOA");
2982 if (!query->second_rr_rcvd) {
2983 if (query->first_rr_serial == serial) {
2984 debug("doing ixfr, got "
2988 debug("this is the second serial %u",
2990 query->second_rr_rcvd = ISC_TRUE;
2991 query->second_rr_serial = serial;
2995 * If we get to this point, we're doing an
2996 * IXFR and have to start really looking
2997 * at serial numbers.
2999 if (query->first_rr_serial == serial) {
3000 debug("got a match for ixfr");
3001 if (!query->first_repeat_rcvd) {
3002 query->first_repeat_rcvd =
3006 debug("done with ixfr");
3009 debug("meaningless soa %u", serial);
3011 result = dns_rdataset_next(rdataset);
3012 } while (result == ISC_R_SUCCESS);
3014 result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
3015 } while (result == ISC_R_SUCCESS);
3016 launch_next_query(query, ISC_FALSE);
3019 received(sevent->n, &sevent->address, query);
3024 * Event handler for recv complete. Perform whatever actions are necessary,
3025 * based on the specifics of the user's request.
3028 recv_done(isc_task_t *task, isc_event_t *event) {
3029 isc_socketevent_t *sevent = NULL;
3030 dig_query_t *query = NULL;
3031 isc_buffer_t *b = NULL;
3032 dns_message_t *msg = NULL;
3034 dig_message_t *chase_msg = NULL;
3035 dig_message_t *chase_msg2 = NULL;
3037 isc_result_t result;
3038 dig_lookup_t *n, *l;
3039 isc_boolean_t docancel = ISC_FALSE;
3040 isc_boolean_t match = ISC_TRUE;
3041 unsigned int parseflags;
3043 unsigned int msgflags;
3045 isc_result_t do_sigchase = ISC_FALSE;
3047 dns_message_t *msg_temp = NULL;
3049 isc_buffer_t *buf = NULL;
3055 debug("recv_done()");
3059 debug("recvcount=%d", recvcount);
3060 INSIST(recvcount >= 0);
3062 query = event->ev_arg;
3063 debug("lookup=%p, query=%p", query->lookup, query);
3067 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
3068 sevent = (isc_socketevent_t *)event;
3070 b = ISC_LIST_HEAD(sevent->bufferlist);
3071 INSIST(b == &query->recvbuf);
3072 ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link);
3074 if ((l->tcp_mode) && (l->timer != NULL))
3075 isc_timer_touch(l->timer);
3076 if ((!l->pending && !l->ns_search_only) || cancel_now) {
3077 debug("no longer pending. Got %s",
3078 isc_result_totext(sevent->result));
3079 query->waiting_connect = ISC_FALSE;
3081 isc_event_free(&event);
3083 check_next_lookup(l);
3088 if (sevent->result != ISC_R_SUCCESS) {
3089 if (sevent->result == ISC_R_CANCELED) {
3090 debug("in recv cancel handler");
3091 query->waiting_connect = ISC_FALSE;
3093 printf(";; communications error: %s\n",
3094 isc_result_totext(sevent->result));
3095 isc_socket_detach(&query->sock);
3097 debug("sockcount=%d", sockcount);
3098 INSIST(sockcount >= 0);
3100 isc_event_free(&event);
3102 check_next_lookup(l);
3108 !isc_sockaddr_compare(&sevent->address, &query->sockaddr,
3109 ISC_SOCKADDR_CMPADDR|
3110 ISC_SOCKADDR_CMPPORT|
3111 ISC_SOCKADDR_CMPSCOPE|
3112 ISC_SOCKADDR_CMPSCOPEZERO)) {
3113 char buf1[ISC_SOCKADDR_FORMATSIZE];
3114 char buf2[ISC_SOCKADDR_FORMATSIZE];
3117 if (isc_sockaddr_pf(&query->sockaddr) == AF_INET)
3118 isc_sockaddr_any(&any);
3120 isc_sockaddr_any6(&any);
3123 * We don't expect a match when the packet is
3124 * sent to 0.0.0.0, :: or to a multicast addresses.
3125 * XXXMPA broadcast needs to be handled here as well.
3127 if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) &&
3128 !isc_sockaddr_ismulticast(&query->sockaddr)) ||
3129 isc_sockaddr_getport(&query->sockaddr) !=
3130 isc_sockaddr_getport(&sevent->address)) {
3131 isc_sockaddr_format(&sevent->address, buf1,
3133 isc_sockaddr_format(&query->sockaddr, buf2,
3135 printf(";; reply from unexpected source: %s,"
3136 " expected %s\n", buf1, buf2);
3141 result = dns_message_peekheader(b, &id, &msgflags);
3142 if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
3145 isc_boolean_t fail = ISC_TRUE;
3146 if (result == ISC_R_SUCCESS) {
3147 if (!query->first_soa_rcvd ||
3149 printf(";; %s: ID mismatch: "
3150 "expected ID %u, got %u\n",
3151 query->first_soa_rcvd ?
3152 "WARNING" : "ERROR",
3153 l->sendmsg->id, id);
3154 if (query->first_soa_rcvd)
3156 query->warn_id = ISC_FALSE;
3158 printf(";; ERROR: short "
3159 "(< header size) message\n");
3161 isc_event_free(&event);
3163 check_next_lookup(l);
3168 } else if (result == ISC_R_SUCCESS)
3169 printf(";; Warning: ID mismatch: "
3170 "expected ID %u, got %u\n", l->sendmsg->id, id);
3172 printf(";; Warning: short "
3173 "(< header size) message received\n");
3176 if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0)
3177 printf(";; Warning: query response not set\n");
3182 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
3183 check_result(result, "dns_message_create");
3186 if (l->querysig == NULL) {
3187 debug("getting initial querysig");
3188 result = dns_message_getquerytsig(l->sendmsg, mctx,
3190 check_result(result, "dns_message_getquerytsig");
3192 result = dns_message_setquerytsig(msg, l->querysig);
3193 check_result(result, "dns_message_setquerytsig");
3194 result = dns_message_settsigkey(msg, key);
3195 check_result(result, "dns_message_settsigkey");
3196 msg->tsigctx = l->tsigctx;
3198 if (l->msgcounter != 0)
3199 msg->tcp_continuation = 1;
3203 debug("before parse starts");
3204 parseflags = DNS_MESSAGEPARSE_PRESERVEORDER;
3207 do_sigchase = ISC_FALSE;
3210 do_sigchase = ISC_TRUE;
3213 if (l->besteffort) {
3214 parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
3215 parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
3217 result = dns_message_parse(msg, b, parseflags);
3218 if (result == DNS_R_RECOVERABLE) {
3219 printf(";; Warning: Message parser reports malformed "
3220 "message packet.\n");
3221 result = ISC_R_SUCCESS;
3223 if (result != ISC_R_SUCCESS) {
3224 printf(";; Got bad packet: %s\n", isc_result_totext(result));
3226 query->waiting_connect = ISC_FALSE;
3227 dns_message_destroy(&msg);
3228 isc_event_free(&event);
3231 check_next_lookup(l);
3235 if (msg->counts[DNS_SECTION_QUESTION] != 0) {
3237 for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
3238 result == ISC_R_SUCCESS && match;
3239 result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) {
3240 dns_name_t *name = NULL;
3241 dns_rdataset_t *rdataset;
3243 dns_message_currentname(msg, DNS_SECTION_QUESTION,
3245 for (rdataset = ISC_LIST_HEAD(name->list);
3247 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3248 if (l->rdtype != rdataset->type ||
3249 l->rdclass != rdataset->rdclass ||
3250 !dns_name_equal(l->name, name)) {
3251 char namestr[DNS_NAME_FORMATSIZE];
3252 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3253 char classbuf[DNS_RDATACLASS_FORMATSIZE];
3254 dns_name_format(name, namestr,
3256 dns_rdatatype_format(rdataset->type,
3259 dns_rdataclass_format(rdataset->rdclass,
3262 printf(";; Question section mismatch: "
3264 namestr, typebuf, classbuf);
3270 dns_message_destroy(&msg);
3272 isc_event_free(&event);
3274 check_next_lookup(l);
3281 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 &&
3282 !l->ignore && !l->tcp_mode) {
3283 printf(";; Truncated, retrying in TCP mode.\n");
3284 n = requeue_lookup(l, ISC_TRUE);
3285 n->tcp_mode = ISC_TRUE;
3286 n->origin = query->lookup->origin;
3287 dns_message_destroy(&msg);
3288 isc_event_free(&event);
3291 check_next_lookup(l);
3295 if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) ||
3296 (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse))
3298 dig_query_t *next = ISC_LIST_NEXT(query, link);
3299 if (l->current_query == query)
3300 l->current_query = NULL;
3302 debug("sending query %p\n", next);
3304 send_tcp_connect(next);
3309 * If our query is at the head of the list and there
3310 * is no next, we're the only one left, so fall
3311 * through to print the message.
3313 if ((ISC_LIST_HEAD(l->q) != query) ||
3314 (ISC_LIST_NEXT(query, link) != NULL)) {
3315 if( l->comments == ISC_TRUE )
3316 printf(";; Got %s from %s, "
3317 "trying next server\n",
3318 msg->rcode == dns_rcode_servfail ?
3320 "recursion not available",
3323 check_next_lookup(l);
3324 dns_message_destroy(&msg);
3325 isc_event_free(&event);
3332 result = dns_tsig_verify(&query->recvbuf, msg, NULL, NULL);
3333 if (result != ISC_R_SUCCESS) {
3334 printf(";; Couldn't verify signature: %s\n",
3335 isc_result_totext(result));
3336 validated = ISC_FALSE;
3338 l->tsigctx = msg->tsigctx;
3339 msg->tsigctx = NULL;
3340 if (l->querysig != NULL) {
3341 debug("freeing querysig buffer %p", l->querysig);
3342 isc_buffer_free(&l->querysig);
3344 result = dns_message_getquerytsig(msg, mctx, &l->querysig);
3345 check_result(result,"dns_message_getquerytsig");
3348 extrabytes = isc_buffer_remaininglength(b);
3350 debug("after parse");
3351 if (l->doing_xfr && l->xfr_q == NULL) {
3354 * Once we are in the XFR message, increase
3355 * the timeout to much longer, so brief network
3356 * outages won't cause the XFR to abort
3358 if (timeout != INT_MAX && l->timer != NULL) {
3359 unsigned int local_timeout;
3363 local_timeout = TCP_TIMEOUT * 4;
3365 local_timeout = UDP_TIMEOUT * 4;
3367 if (timeout < (INT_MAX / 4))
3368 local_timeout = timeout * 4;
3370 local_timeout = INT_MAX;
3372 debug("have local timeout of %d", local_timeout);
3373 isc_interval_set(&l->interval, local_timeout, 0);
3374 result = isc_timer_reset(l->timer,
3379 check_result(result, "isc_timer_reset");
3383 if (!l->doing_xfr || l->xfr_q == query) {
3384 if (msg->rcode != dns_rcode_noerror &&
3385 (l->origin != NULL || l->need_search)) {
3386 if (!next_origin(query) || showsearch) {
3387 printmessage(query, msg, ISC_TRUE);
3388 received(b->used, &sevent->address, query);
3390 } else if (!l->trace && !l->ns_search_only) {
3394 printmessage(query, msg, ISC_TRUE);
3395 } else if (l->trace) {
3397 int count = msg->counts[DNS_SECTION_ANSWER];
3399 debug("in TRACE code");
3400 if (!l->ns_search_only)
3401 printmessage(query, msg, ISC_TRUE);
3403 l->rdtype = l->qrdtype;
3404 if (l->trace_root || (l->ns_search_only && count > 0)) {
3406 l->rdtype = dns_rdatatype_soa;
3407 n = followup_lookup(msg, query,
3408 DNS_SECTION_ANSWER);
3409 l->trace_root = ISC_FALSE;
3410 } else if (count == 0)
3411 n = followup_lookup(msg, query,
3412 DNS_SECTION_AUTHORITY);
3414 docancel = ISC_TRUE;
3416 debug("in NSSEARCH code");
3418 if (l->trace_root) {
3420 * This is the initial NS query.
3424 l->rdtype = dns_rdatatype_soa;
3425 n = followup_lookup(msg, query,
3426 DNS_SECTION_ANSWER);
3428 docancel = ISC_TRUE;
3429 l->trace_root = ISC_FALSE;
3434 printmessage(query, msg, ISC_TRUE);
3438 chase_msg = isc_mem_allocate(mctx,
3439 sizeof(dig_message_t));
3440 if (chase_msg == NULL) {
3441 fatal("Memory allocation failure in %s:%d",
3442 __FILE__, __LINE__);
3444 ISC_LIST_INITANDAPPEND(chase_message_list, chase_msg,
3446 if (dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
3447 &msg_temp) != ISC_R_SUCCESS) {
3448 fatal("dns_message_create in %s:%d",
3449 __FILE__, __LINE__);
3452 isc_buffer_usedregion(b, &r);
3453 result = isc_buffer_allocate(mctx, &buf, r.length);
3455 check_result(result, "isc_buffer_allocate");
3456 result = isc_buffer_copyregion(buf, &r);
3457 check_result(result, "isc_buffer_copyregion");
3459 result = dns_message_parse(msg_temp, buf, 0);
3461 isc_buffer_free(&buf);
3462 chase_msg->msg = msg_temp;
3464 chase_msg2 = isc_mem_allocate(mctx,
3465 sizeof(dig_message_t));
3466 if (chase_msg2 == NULL) {
3467 fatal("Memory allocation failure in %s:%d",
3468 __FILE__, __LINE__);
3470 ISC_LIST_INITANDAPPEND(chase_message_list2, chase_msg2,
3472 chase_msg2->msg = msg;
3478 if (l->sigchase && ISC_LIST_EMPTY(lookup_list)) {
3484 debug("still pending.");
3486 if (query != l->xfr_q) {
3487 dns_message_destroy(&msg);
3488 isc_event_free(&event);
3489 query->waiting_connect = ISC_FALSE;
3494 docancel = check_for_more_data(query, msg, sevent);
3496 dns_message_destroy(&msg);
3499 check_next_lookup(l);
3503 if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
3508 received(b->used, &sevent->address, query);
3511 if (!query->lookup->ns_search_only)
3512 query->lookup->pending = ISC_FALSE;
3513 if (!query->lookup->ns_search_only ||
3514 query->lookup->trace_root || docancel) {
3518 dns_message_destroy(&msg);
3523 check_next_lookup(l);
3531 dns_message_destroy(&msg);
3533 isc_event_free(&event);
3538 isc_buffer_invalidate(&query->recvbuf);
3539 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
3540 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
3541 result = isc_socket_recvv(query->sock, &query->recvlist, 1,
3542 global_task, recv_done, query);
3543 check_result(result, "isc_socket_recvv");
3545 isc_event_free(&event);
3551 * Turn a name into an address, using system-supplied routines. This is
3552 * used in looking up server names, etc... and needs to use system-supplied
3553 * routines, since they may be using a non-DNS system for these lookups.
3556 get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
3558 isc_result_t result;
3561 result = bind9_getaddresses(host, port, sockaddr, 1, &count);
3563 if (result != ISC_R_SUCCESS)
3568 return (ISC_R_SUCCESS);
3572 getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) {
3573 isc_result_t result;
3574 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
3575 isc_netaddr_t netaddr;
3578 char tmp[ISC_NETADDR_FORMATSIZE];
3580 result = bind9_getaddresses(host, 0, sockaddrs,
3581 DIG_MAX_ADDRESSES, &count);
3582 if (resultp != NULL)
3584 if (result != ISC_R_SUCCESS) {
3585 if (resultp == NULL)
3586 fatal("couldn't get address for '%s': %s",
3587 host, isc_result_totext(result));
3591 for (i = 0; i < count; i++) {
3592 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
3593 isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
3594 srv = make_server(tmp, host);
3595 ISC_LIST_APPEND(lookup->my_server_list, srv, link);
3602 * Initiate either a TCP or UDP lookup
3605 do_lookup(dig_lookup_t *lookup) {
3607 REQUIRE(lookup != NULL);
3609 debug("do_lookup()");
3610 lookup->pending = ISC_TRUE;
3611 if (lookup->tcp_mode)
3612 send_tcp_connect(ISC_LIST_HEAD(lookup->q));
3614 send_udp(ISC_LIST_HEAD(lookup->q));
3618 * Start everything in action upon task startup.
3621 onrun_callback(isc_task_t *task, isc_event_t *event) {
3624 isc_event_free(&event);
3631 * Make everything on the lookup queue go away. Mainly used by the
3636 dig_lookup_t *l, *n;
3637 dig_query_t *q, *nq;
3639 debug("cancel_all()");
3646 cancel_now = ISC_TRUE;
3647 if (current_lookup != NULL) {
3648 if (current_lookup->timer != NULL)
3649 isc_timer_detach(¤t_lookup->timer);
3650 q = ISC_LIST_HEAD(current_lookup->q);
3652 debug("canceling query %p, belonging to %p",
3654 nq = ISC_LIST_NEXT(q, link);
3655 if (q->sock != NULL) {
3656 isc_socket_cancel(q->sock, NULL,
3657 ISC_SOCKCANCEL_ALL);
3664 l = ISC_LIST_HEAD(lookup_list);
3666 n = ISC_LIST_NEXT(l, link);
3667 ISC_LIST_DEQUEUE(lookup_list, l, link);
3668 try_clear_lookup(l);
3675 * Destroy all of the libs we are using, and get everything ready for a
3679 destroy_libs(void) {
3682 dig_message_t *chase_msg;
3685 isc_result_t result;
3688 debug("destroy_libs()");
3689 if (global_task != NULL) {
3690 debug("freeing task");
3691 isc_task_detach(&global_task);
3694 * The taskmgr_destroy() call blocks until all events are cleared
3697 if (taskmgr != NULL) {
3698 debug("freeing taskmgr");
3699 isc_taskmgr_destroy(&taskmgr);
3702 REQUIRE(sockcount == 0);
3703 REQUIRE(recvcount == 0);
3704 REQUIRE(sendcount == 0);
3706 INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
3707 INSIST(current_lookup == NULL);
3710 free_now = ISC_TRUE;
3712 lwres_conf_clear(lwctx);
3713 lwres_context_destroy(&lwctx);
3715 flush_server_list();
3720 result = dns_name_settotextfilter(NULL);
3721 check_result(result, "dns_name_settotextfilter");
3725 if (commctx != NULL) {
3726 debug("freeing commctx");
3727 isc_mempool_destroy(&commctx);
3729 if (socketmgr != NULL) {
3730 debug("freeing socketmgr");
3731 isc_socketmgr_destroy(&socketmgr);
3733 if (timermgr != NULL) {
3734 debug("freeing timermgr");
3735 isc_timermgr_destroy(&timermgr);
3738 debug("freeing key %p", key);
3739 dns_tsigkey_detach(&key);
3741 if (namebuf != NULL)
3742 isc_buffer_free(&namebuf);
3745 debug("destroy DST lib");
3747 is_dst_up = ISC_FALSE;
3750 debug("detach from entropy");
3751 isc_entropy_detach(&entp);
3755 DESTROYLOCK(&lookup_lock);
3758 debug("Destroy the messages kept for sigchase");
3759 /* Destroy the messages kept for sigchase */
3760 chase_msg = ISC_LIST_HEAD(chase_message_list);
3762 while (chase_msg != NULL) {
3763 INSIST(chase_msg->msg != NULL);
3764 dns_message_destroy(&(chase_msg->msg));
3766 chase_msg = ISC_LIST_NEXT(chase_msg, link);
3767 isc_mem_free(mctx, ptr);
3770 chase_msg = ISC_LIST_HEAD(chase_message_list2);
3772 while (chase_msg != NULL) {
3773 INSIST(chase_msg->msg != NULL);
3774 dns_message_destroy(&(chase_msg->msg));
3776 chase_msg = ISC_LIST_NEXT(chase_msg, link);
3777 isc_mem_free(mctx, ptr);
3779 if (dns_name_dynamic(&chase_name))
3780 free_name(&chase_name, mctx);
3782 if (dns_name_dynamic(&chase_current_name))
3783 free_name(&chase_current_name, mctx);
3784 if (dns_name_dynamic(&chase_authority_name))
3785 free_name(&chase_authority_name, mctx);
3788 if (dns_name_dynamic(&chase_signame))
3789 free_name(&chase_signame, mctx);
3793 debug("Removing log context");
3794 isc_log_destroy(&lctx);
3796 debug("Destroy memory");
3797 if (memdebugging != 0)
3798 isc_mem_stats(mctx, stderr);
3800 isc_mem_destroy(&mctx);
3805 initialize_idn(void) {
3807 isc_result_t result;
3809 #ifdef HAVE_SETLOCALE
3811 (void)setlocale(LC_ALL, "");
3813 /* Create configuration context. */
3814 r = idn_nameinit(1);
3815 if (r != idn_success)
3816 fatal("idn api initialization failed: %s",
3817 idn_result_tostring(r));
3819 /* Set domain name -> text post-conversion filter. */
3820 result = dns_name_settotextfilter(output_filter);
3821 check_result(result, "dns_name_settotextfilter");
3825 output_filter(isc_buffer_t *buffer, unsigned int used_org,
3826 isc_boolean_t absolute)
3828 char tmp1[MAXDLEN], tmp2[MAXDLEN];
3829 size_t fromlen, tolen;
3830 isc_boolean_t end_with_dot;
3833 * Copy contents of 'buffer' to 'tmp1', supply trailing dot
3834 * if 'absolute' is true, and terminate with NUL.
3836 fromlen = isc_buffer_usedlength(buffer) - used_org;
3837 if (fromlen >= MAXDLEN)
3838 return (ISC_R_SUCCESS);
3839 memcpy(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
3840 end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE;
3841 if (absolute && !end_with_dot) {
3843 if (fromlen >= MAXDLEN)
3844 return (ISC_R_SUCCESS);
3845 tmp1[fromlen - 1] = '.';
3847 tmp1[fromlen] = '\0';
3850 * Convert contents of 'tmp1' to local encoding.
3852 if (idn_decodename(IDN_DECODE_APP, tmp1, tmp2, MAXDLEN) != idn_success)
3853 return (ISC_R_SUCCESS);
3857 * Copy the converted contents in 'tmp1' back to 'buffer'.
3858 * If we have appended trailing dot, remove it.
3860 tolen = strlen(tmp1);
3861 if (absolute && !end_with_dot && tmp1[tolen - 1] == '.')
3864 if (isc_buffer_length(buffer) < used_org + tolen)
3865 return (ISC_R_NOSPACE);
3867 isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org);
3868 memcpy(isc_buffer_used(buffer), tmp1, tolen);
3869 isc_buffer_add(buffer, tolen);
3871 return (ISC_R_SUCCESS);
3875 append_textname(char *name, const char *origin, size_t namesize) {
3876 size_t namelen = strlen(name);
3877 size_t originlen = strlen(origin);
3879 /* Already absolute? */
3880 if (namelen > 0 && name[namelen - 1] == '.')
3883 /* Append dot and origin */
3885 if (namelen + 1 + originlen >= namesize)
3886 return idn_buffer_overflow;
3888 name[namelen++] = '.';
3889 (void)strcpy(name + namelen, origin);
3894 idn_check_result(idn_result_t r, const char *msg) {
3895 if (r != idn_success) {
3897 fatal("%s: %s", msg, idn_result_tostring(r));
3900 #endif /* WITH_IDN */
3904 print_type(dns_rdatatype_t type)
3906 isc_buffer_t * b = NULL;
3907 isc_result_t result;
3910 result = isc_buffer_allocate(mctx, &b, 4000);
3911 check_result(result, "isc_buffer_allocate");
3913 result = dns_rdatatype_totext(type, b);
3914 check_result(result, "print_type");
3916 isc_buffer_usedregion(b, &r);
3917 r.base[r.length] = '\0';
3919 printf("%s", r.base);
3921 isc_buffer_free(&b);
3925 dump_database_section(dns_message_t *msg, int section)
3927 dns_name_t *msg_name=NULL;
3929 dns_rdataset_t *rdataset;
3932 dns_message_currentname(msg, section, &msg_name);
3934 for (rdataset = ISC_LIST_HEAD(msg_name->list); rdataset != NULL;
3935 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3936 dns_name_print(msg_name, stdout);
3938 print_rdataset(msg_name, rdataset, mctx);
3942 } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
3946 dump_database(void) {
3947 dig_message_t * msg;
3949 for (msg = ISC_LIST_HEAD(chase_message_list); msg != NULL;
3950 msg = ISC_LIST_NEXT(msg, link)) {
3951 if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
3953 dump_database_section(msg->msg, DNS_SECTION_ANSWER);
3955 if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
3957 dump_database_section(msg->msg, DNS_SECTION_AUTHORITY);
3959 if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
3961 dump_database_section(msg->msg, DNS_SECTION_ADDITIONAL);
3967 search_type(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) {
3968 dns_rdataset_t *rdataset;
3969 dns_rdata_sig_t siginfo;
3970 dns_rdata_t sigrdata = DNS_RDATA_INIT;
3971 isc_result_t result;
3973 for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
3974 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3975 if (type == dns_rdatatype_any) {
3976 if (rdataset->type != dns_rdatatype_rrsig)
3978 } else if ((type == dns_rdatatype_rrsig) &&
3979 (rdataset->type == dns_rdatatype_rrsig)) {
3980 result = dns_rdataset_first(rdataset);
3981 check_result(result, "empty rdataset");
3982 dns_rdataset_current(rdataset, &sigrdata);
3983 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
3984 check_result(result, "sigrdata tostruct siginfo");
3986 if ((siginfo.covered == covers) ||
3987 (covers == dns_rdatatype_any)) {
3988 dns_rdata_reset(&sigrdata);
3989 dns_rdata_freestruct(&siginfo);
3992 dns_rdata_reset(&sigrdata);
3993 dns_rdata_freestruct(&siginfo);
3994 } else if (rdataset->type == type)
4001 chase_scanname_section(dns_message_t *msg, dns_name_t *name,
4002 dns_rdatatype_t type, dns_rdatatype_t covers,
4005 dns_rdataset_t *rdataset;
4006 dns_name_t *msg_name = NULL;
4009 dns_message_currentname(msg, section, &msg_name);
4010 if (dns_name_compare(msg_name, name) == 0) {
4011 rdataset = search_type(msg_name, type, covers);
4012 if (rdataset != NULL)
4016 } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
4023 chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers)
4025 dns_rdataset_t *rdataset = NULL;
4026 dig_message_t * msg;
4028 for (msg = ISC_LIST_HEAD(chase_message_list2); msg != NULL;
4029 msg = ISC_LIST_NEXT(msg, link)) {
4030 if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
4032 rdataset = chase_scanname_section(msg->msg, name,
4034 DNS_SECTION_ANSWER);
4035 if (rdataset != NULL)
4037 if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
4040 chase_scanname_section(msg->msg, name,
4042 DNS_SECTION_AUTHORITY);
4043 if (rdataset != NULL)
4045 if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
4048 chase_scanname_section(msg->msg, name, type,
4050 DNS_SECTION_ADDITIONAL);
4051 if (rdataset != NULL)
4059 sigchase_scanname(dns_rdatatype_t type, dns_rdatatype_t covers,
4060 isc_boolean_t * lookedup, dns_name_t *rdata_name)
4062 dig_lookup_t *lookup;
4063 isc_buffer_t *b = NULL;
4065 isc_result_t result;
4066 dns_rdataset_t * temp;
4067 dns_rdatatype_t querytype;
4069 temp = chase_scanname(rdata_name, type, covers);
4073 if (*lookedup == ISC_TRUE)
4076 lookup = clone_lookup(current_lookup, ISC_TRUE);
4077 lookup->trace_root = ISC_FALSE;
4078 lookup->new_search = ISC_TRUE;
4080 result = isc_buffer_allocate(mctx, &b, BUFSIZE);
4081 check_result(result, "isc_buffer_allocate");
4082 result = dns_name_totext(rdata_name, ISC_FALSE, b);
4083 check_result(result, "dns_name_totext");
4084 isc_buffer_usedregion(b, &r);
4085 r.base[r.length] = '\0';
4086 strcpy(lookup->textname, (char*)r.base);
4087 isc_buffer_free(&b);
4089 if (type == dns_rdatatype_rrsig)
4094 if (querytype == 0 || querytype == 255) {
4095 printf("Error in the queried type: %d\n", querytype);
4099 lookup->rdtype = querytype;
4100 lookup->rdtypeset = ISC_TRUE;
4101 lookup->qrdtype = querytype;
4102 *lookedup = ISC_TRUE;
4104 ISC_LIST_APPEND(lookup_list, lookup, link);
4105 printf("\n\nLaunch a query to find a RRset of type ");
4107 printf(" for zone: %s\n", lookup->textname);
4112 insert_trustedkey(dst_key_t **keyp)
4116 if (tk_list.nb_tk >= MAX_TRUSTED_KEY)
4119 tk_list.key[tk_list.nb_tk++] = *keyp;
4129 for (i= 0; i < MAX_TRUSTED_KEY; i++) {
4130 if (tk_list.key[i] != NULL) {
4131 dst_key_free(&tk_list.key[i]);
4132 tk_list.key[i] = NULL;
4141 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
4144 removetmpkey(isc_mem_t *mctx, const char *file)
4146 char *tempnamekey = NULL;
4148 isc_result_t result;
4150 tempnamekeylen = strlen(file)+10;
4152 tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
4153 if (tempnamekey == NULL)
4154 return (ISC_R_NOMEMORY);
4156 memset(tempnamekey, 0, tempnamekeylen);
4158 strcat(tempnamekey, file);
4159 strcat(tempnamekey,".key");
4160 isc_file_remove(tempnamekey);
4162 result = isc_file_remove(tempnamekey);
4163 isc_mem_free(mctx, tempnamekey);
4168 opentmpkey(isc_mem_t *mctx, const char *file, char **tempp, FILE **fp) {
4170 isc_result_t result;
4171 char *tempname = NULL;
4172 char *tempnamekey = NULL;
4180 tempnamelen = strlen(file) + 20;
4181 tempname = isc_mem_allocate(mctx, tempnamelen);
4182 if (tempname == NULL)
4183 return (ISC_R_NOMEMORY);
4184 memset(tempname, 0, tempnamelen);
4186 result = isc_file_mktemplate(file, tempname, tempnamelen);
4187 if (result != ISC_R_SUCCESS)
4193 if (cp == tempname) {
4194 isc_mem_free(mctx, tempname);
4195 return (ISC_R_FAILURE);
4199 while (cp >= tempname && *cp == 'X') {
4200 isc_random_get(&which);
4201 *cp = alphnum[which % (sizeof(alphnum) - 1)];
4205 tempnamekeylen = tempnamelen+5;
4206 tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
4207 if (tempnamekey == NULL)
4208 return (ISC_R_NOMEMORY);
4210 memset(tempnamekey, 0, tempnamekeylen);
4211 strncpy(tempnamekey, tempname, tempnamelen);
4212 strcat(tempnamekey ,".key");
4215 if (isc_file_exists(tempnamekey)) {
4216 isc_mem_free(mctx, tempnamekey);
4217 isc_mem_free(mctx, tempname);
4221 if ((f = fopen(tempnamekey, "w")) == NULL) {
4222 printf("get_trusted_key(): trusted key not found %s\n",
4224 return (ISC_R_FAILURE);
4228 isc_mem_free(mctx, tempnamekey);
4231 return (ISC_R_SUCCESS);
4234 isc_mem_free(mctx, tempname);
4240 get_trusted_key(isc_mem_t *mctx)
4242 isc_result_t result;
4243 const char *filename = NULL;
4244 char *filetemp = NULL;
4247 dst_key_t *key = NULL;
4249 result = isc_file_exists(trustedkey);
4250 if (result != ISC_TRUE) {
4251 result = isc_file_exists("/etc/trusted-key.key");
4252 if (result != ISC_TRUE) {
4253 result = isc_file_exists("./trusted-key.key");
4254 if (result != ISC_TRUE)
4255 return (ISC_R_FAILURE);
4257 filename = "./trusted-key.key";
4259 filename = "/etc/trusted-key.key";
4261 filename = trustedkey;
4263 if (filename == NULL) {
4264 printf("No trusted key\n");
4265 return (ISC_R_FAILURE);
4268 if ((fp = fopen(filename, "r")) == NULL) {
4269 printf("get_trusted_key(): trusted key not found %s\n",
4271 return (ISC_R_FAILURE);
4273 while (fgets(buf, sizeof(buf), fp) != NULL) {
4274 result = opentmpkey(mctx,"tmp_file", &filetemp, &fptemp);
4275 if (result != ISC_R_SUCCESS) {
4277 return (ISC_R_FAILURE);
4279 if (fputs(buf, fptemp) < 0) {
4282 return (ISC_R_FAILURE);
4285 result = dst_key_fromnamedfile(filetemp, NULL, DST_TYPE_PUBLIC,
4287 removetmpkey(mctx, filetemp);
4288 isc_mem_free(mctx, filetemp);
4289 if (result != ISC_R_SUCCESS) {
4291 return (ISC_R_FAILURE);
4294 dst_key_tofile(key, DST_TYPE_PUBLIC,"/tmp");
4296 insert_trustedkey(&key);
4301 return (ISC_R_SUCCESS);
4306 nameFromString(const char *str, dns_name_t *p_ret) {
4307 size_t len = strlen(str);
4308 isc_result_t result;
4309 isc_buffer_t buffer;
4310 dns_fixedname_t fixedname;
4312 REQUIRE(p_ret != NULL);
4313 REQUIRE(str != NULL);
4315 isc_buffer_init(&buffer, str, len);
4316 isc_buffer_add(&buffer, len);
4318 dns_fixedname_init(&fixedname);
4319 result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer,
4320 dns_rootname, DNS_NAME_DOWNCASE, NULL);
4321 check_result(result, "nameFromString");
4323 if (dns_name_dynamic(p_ret))
4324 free_name(p_ret, mctx);
4326 result = dns_name_dup(dns_fixedname_name(&fixedname), mctx, p_ret);
4327 check_result(result, "nameFromString");
4333 prepare_lookup(dns_name_t *name)
4335 isc_result_t result;
4336 dig_lookup_t *lookup = NULL;
4340 lookup = clone_lookup(current_lookup, ISC_TRUE);
4341 lookup->trace_root = ISC_FALSE;
4342 lookup->new_search = ISC_TRUE;
4343 lookup->trace_root_sigchase = ISC_FALSE;
4345 strncpy(lookup->textname, lookup->textnamesigchase, MXNAME);
4347 lookup->rdtype = lookup->rdtype_sigchase;
4348 lookup->rdtypeset = ISC_TRUE;
4349 lookup->qrdtype = lookup->qrdtype_sigchase;
4351 s = ISC_LIST_HEAD(lookup->my_server_list);
4353 debug("freeing server %p belonging to %p",
4356 s = ISC_LIST_NEXT(s, link);
4357 ISC_LIST_DEQUEUE(lookup->my_server_list,
4358 (dig_server_t *)ptr, link);
4359 isc_mem_free(mctx, ptr);
4363 for (result = dns_rdataset_first(chase_nsrdataset);
4364 result == ISC_R_SUCCESS;
4365 result = dns_rdataset_next(chase_nsrdataset)) {
4366 char namestr[DNS_NAME_FORMATSIZE];
4368 dns_rdata_t rdata = DNS_RDATA_INIT;
4369 dig_server_t * srv = NULL;
4370 #define __FOLLOW_GLUE__
4371 #ifdef __FOLLOW_GLUE__
4372 isc_buffer_t *b = NULL;
4373 isc_result_t result;
4375 dns_rdataset_t *rdataset = NULL;
4376 isc_boolean_t true = ISC_TRUE;
4379 memset(namestr, 0, DNS_NAME_FORMATSIZE);
4381 dns_rdataset_current(chase_nsrdataset, &rdata);
4383 result = dns_rdata_tostruct(&rdata, &ns, NULL);
4384 check_result(result, "dns_rdata_tostruct");
4386 #ifdef __FOLLOW_GLUE__
4388 result = advanced_rrsearch(&rdataset, &ns.name,
4390 dns_rdatatype_any, &true);
4391 if (result == ISC_R_SUCCESS) {
4392 for (result = dns_rdataset_first(rdataset);
4393 result == ISC_R_SUCCESS;
4394 result = dns_rdataset_next(rdataset)) {
4395 dns_rdata_t aaaa = DNS_RDATA_INIT;
4396 dns_rdataset_current(rdataset, &aaaa);
4398 result = isc_buffer_allocate(mctx, &b, 80);
4399 check_result(result, "isc_buffer_allocate");
4401 dns_rdata_totext(&aaaa, &ns.name, b);
4402 isc_buffer_usedregion(b, &r);
4403 r.base[r.length] = '\0';
4404 strncpy(namestr, (char*)r.base,
4405 DNS_NAME_FORMATSIZE);
4406 isc_buffer_free(&b);
4407 dns_rdata_reset(&aaaa);
4410 srv = make_server(namestr, namestr);
4412 ISC_LIST_APPEND(lookup->my_server_list,
4418 result = advanced_rrsearch(&rdataset, &ns.name, dns_rdatatype_a,
4419 dns_rdatatype_any, &true);
4420 if (result == ISC_R_SUCCESS) {
4421 for (result = dns_rdataset_first(rdataset);
4422 result == ISC_R_SUCCESS;
4423 result = dns_rdataset_next(rdataset)) {
4424 dns_rdata_t a = DNS_RDATA_INIT;
4425 dns_rdataset_current(rdataset, &a);
4427 result = isc_buffer_allocate(mctx, &b, 80);
4428 check_result(result, "isc_buffer_allocate");
4430 dns_rdata_totext(&a, &ns.name, b);
4431 isc_buffer_usedregion(b, &r);
4432 r.base[r.length] = '\0';
4433 strncpy(namestr, (char*)r.base,
4434 DNS_NAME_FORMATSIZE);
4435 isc_buffer_free(&b);
4436 dns_rdata_reset(&a);
4437 printf("ns name: %s\n", namestr);
4440 srv = make_server(namestr, namestr);
4442 ISC_LIST_APPEND(lookup->my_server_list,
4448 dns_name_format(&ns.name, namestr, sizeof(namestr));
4449 printf("ns name: ");
4450 dns_name_print(&ns.name, stdout);
4452 srv = make_server(namestr, namestr);
4454 ISC_LIST_APPEND(lookup->my_server_list, srv, link);
4457 dns_rdata_freestruct(&ns);
4458 dns_rdata_reset(&rdata);
4462 ISC_LIST_APPEND(lookup_list, lookup, link);
4463 printf("\nLaunch a query to find a RRset of type ");
4464 print_type(lookup->rdtype);
4465 printf(" for zone: %s", lookup->textname);
4466 printf(" with nameservers:");
4468 print_rdataset(name, chase_nsrdataset, mctx);
4469 return (ISC_R_SUCCESS);
4474 child_of_zone(dns_name_t * name, dns_name_t * zone_name,
4475 dns_name_t * child_name)
4477 dns_namereln_t name_reln;
4479 unsigned int nlabelsp;
4481 name_reln = dns_name_fullcompare(name, zone_name, &orderp, &nlabelsp);
4482 if (name_reln != dns_namereln_subdomain ||
4483 dns_name_countlabels(name) <= dns_name_countlabels(zone_name) + 1) {
4484 printf("\n;; ERROR : ");
4485 dns_name_print(name, stdout);
4486 printf(" is not a subdomain of: ");
4487 dns_name_print(zone_name, stdout);
4488 printf(" FAILED\n\n");
4489 return (ISC_R_FAILURE);
4492 dns_name_getlabelsequence(name,
4493 dns_name_countlabels(name) -
4494 dns_name_countlabels(zone_name) -1,
4495 dns_name_countlabels(zone_name) +1,
4497 return (ISC_R_SUCCESS);
4501 grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t *sigrdataset)
4503 isc_result_t result;
4504 dns_rdata_t sigrdata = DNS_RDATA_INIT;
4505 dns_rdata_sig_t siginfo;
4507 result = dns_rdataset_first(sigrdataset);
4508 check_result(result, "empty RRSIG dataset");
4509 dns_rdata_init(&sigrdata);
4512 dns_rdataset_current(sigrdataset, &sigrdata);
4514 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4515 check_result(result, "sigrdata tostruct siginfo");
4517 if (dns_name_compare(&siginfo.signer, zone_name) == 0) {
4518 dns_rdata_freestruct(&siginfo);
4519 dns_rdata_reset(&sigrdata);
4520 return (ISC_R_SUCCESS);
4523 dns_rdata_freestruct(&siginfo);
4524 dns_rdata_reset(&sigrdata);
4526 } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
4528 dns_rdata_reset(&sigrdata);
4530 return (ISC_R_FAILURE);
4535 initialization(dns_name_t *name)
4537 isc_result_t result;
4538 isc_boolean_t true = ISC_TRUE;
4540 chase_nsrdataset = NULL;
4541 result = advanced_rrsearch(&chase_nsrdataset, name, dns_rdatatype_ns,
4542 dns_rdatatype_any, &true);
4543 if (result != ISC_R_SUCCESS) {
4544 printf("\n;; NS RRset is missing to continue validation:"
4546 return (ISC_R_FAILURE);
4548 INSIST(chase_nsrdataset != NULL);
4549 prepare_lookup(name);
4551 dup_name(name, &chase_current_name, mctx);
4553 return (ISC_R_SUCCESS);
4558 print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset, isc_mem_t *mctx)
4560 isc_buffer_t *b = NULL;
4561 isc_result_t result;
4564 result = isc_buffer_allocate(mctx, &b, 9000);
4565 check_result(result, "isc_buffer_allocate");
4567 printrdataset(name, rdataset, b);
4569 isc_buffer_usedregion(b, &r);
4570 r.base[r.length] = '\0';
4573 printf("%s\n", r.base);
4575 isc_buffer_free(&b);
4580 dup_name(dns_name_t *source, dns_name_t *target, isc_mem_t *mctx) {
4581 isc_result_t result;
4583 if (dns_name_dynamic(target))
4584 free_name(target, mctx);
4585 result = dns_name_dup(source, mctx, target);
4586 check_result(result, "dns_name_dup");
4590 free_name(dns_name_t *name, isc_mem_t *mctx) {
4591 dns_name_free(name, mctx);
4592 dns_name_init(name, NULL);
4597 * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter
4598 * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key
4599 * and the RRset is valid
4600 * return ISC_R_NOTFOUND if not contains trusted key
4601 or if the RRset isn't valid
4602 * return ISC_R_FAILURE if problem
4606 contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset,
4607 dns_rdataset_t *sigrdataset,
4610 isc_result_t result;
4611 dns_rdata_t rdata = DNS_RDATA_INIT;
4612 dst_key_t *trustedKey = NULL;
4613 dst_key_t *dnsseckey = NULL;
4616 if (name == NULL || rdataset == NULL)
4617 return (ISC_R_FAILURE);
4619 result = dns_rdataset_first(rdataset);
4620 check_result(result, "empty rdataset");
4623 dns_rdataset_current(rdataset, &rdata);
4624 INSIST(rdata.type == dns_rdatatype_dnskey);
4626 result = dns_dnssec_keyfromrdata(name, &rdata,
4628 check_result(result, "dns_dnssec_keyfromrdata");
4631 for (i = 0; i < tk_list.nb_tk; i++) {
4632 if (dst_key_compare(tk_list.key[i], dnsseckey)
4634 dns_rdata_reset(&rdata);
4636 printf(";; Ok, find a Trusted Key in the "
4637 "DNSKEY RRset: %d\n",
4638 dst_key_id(dnsseckey));
4639 if (sigchase_verify_sig_key(name, rdataset,
4644 dst_key_free(&dnsseckey);
4646 return (ISC_R_SUCCESS);
4651 dns_rdata_reset(&rdata);
4652 if (dnsseckey != NULL)
4653 dst_key_free(&dnsseckey);
4654 } while (dns_rdataset_next(rdataset) == ISC_R_SUCCESS);
4656 if (trustedKey != NULL)
4657 dst_key_free(&trustedKey);
4660 return (ISC_R_NOTFOUND);
4664 sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset,
4665 dns_rdataset_t *keyrdataset,
4666 dns_rdataset_t *sigrdataset,
4669 isc_result_t result;
4670 dns_rdata_t keyrdata = DNS_RDATA_INIT;
4671 dst_key_t *dnsseckey = NULL;
4673 result = dns_rdataset_first(keyrdataset);
4674 check_result(result, "empty DNSKEY dataset");
4675 dns_rdata_init(&keyrdata);
4678 dns_rdataset_current(keyrdataset, &keyrdata);
4679 INSIST(keyrdata.type == dns_rdatatype_dnskey);
4681 result = dns_dnssec_keyfromrdata(name, &keyrdata,
4683 check_result(result, "dns_dnssec_keyfromrdata");
4685 result = sigchase_verify_sig_key(name, rdataset, dnsseckey,
4687 if (result == ISC_R_SUCCESS) {
4688 dns_rdata_reset(&keyrdata);
4689 dst_key_free(&dnsseckey);
4690 return (ISC_R_SUCCESS);
4692 dst_key_free(&dnsseckey);
4693 dns_rdata_reset(&keyrdata);
4694 } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
4696 dns_rdata_reset(&keyrdata);
4698 return (ISC_R_NOTFOUND);
4702 sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset,
4703 dst_key_t *dnsseckey, dns_rdataset_t *sigrdataset,
4706 isc_result_t result;
4707 dns_rdata_t sigrdata = DNS_RDATA_INIT;
4708 dns_rdata_sig_t siginfo;
4710 result = dns_rdataset_first(sigrdataset);
4711 check_result(result, "empty RRSIG dataset");
4712 dns_rdata_init(&sigrdata);
4715 dns_rdataset_current(sigrdataset, &sigrdata);
4717 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4718 check_result(result, "sigrdata tostruct siginfo");
4721 * Test if the id of the DNSKEY is
4722 * the id of the DNSKEY signer's
4724 if (siginfo.keyid == dst_key_id(dnsseckey)) {
4726 result = dns_rdataset_first(rdataset);
4727 check_result(result, "empty DS dataset");
4729 result = dns_dnssec_verify(name, rdataset, dnsseckey,
4730 ISC_FALSE, mctx, &sigrdata);
4732 printf(";; VERIFYING ");
4733 print_type(rdataset->type);
4734 printf(" RRset for ");
4735 dns_name_print(name, stdout);
4736 printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey),
4737 isc_result_totext(result));
4739 if (result == ISC_R_SUCCESS) {
4740 dns_rdata_reset(&sigrdata);
4744 dns_rdata_freestruct(&siginfo);
4745 dns_rdata_reset(&sigrdata);
4747 } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
4749 dns_rdata_reset(&sigrdata);
4751 return (ISC_R_NOTFOUND);
4756 sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset,
4757 dns_rdataset_t *dsrdataset, isc_mem_t *mctx)
4759 isc_result_t result;
4760 dns_rdata_t keyrdata = DNS_RDATA_INIT;
4761 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
4762 dns_rdata_t dsrdata = DNS_RDATA_INIT;
4763 dns_rdata_ds_t dsinfo;
4764 dst_key_t *dnsseckey = NULL;
4765 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
4767 result = dns_rdataset_first(dsrdataset);
4768 check_result(result, "empty DSset dataset");
4770 dns_rdataset_current(dsrdataset, &dsrdata);
4772 result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL);
4773 check_result(result, "dns_rdata_tostruct for DS");
4775 result = dns_rdataset_first(keyrdataset);
4776 check_result(result, "empty KEY dataset");
4779 dns_rdataset_current(keyrdataset, &keyrdata);
4780 INSIST(keyrdata.type == dns_rdatatype_dnskey);
4782 result = dns_dnssec_keyfromrdata(name, &keyrdata,
4784 check_result(result, "dns_dnssec_keyfromrdata");
4787 * Test if the id of the DNSKEY is the
4788 * id of DNSKEY referenced by the DS
4790 if (dsinfo.key_tag == dst_key_id(dnsseckey)) {
4792 result = dns_ds_buildrdata(name, &keyrdata,
4794 dsbuf, &newdsrdata);
4795 dns_rdata_freestruct(&dsinfo);
4797 if (result != ISC_R_SUCCESS) {
4798 dns_rdata_reset(&keyrdata);
4799 dns_rdata_reset(&newdsrdata);
4800 dns_rdata_reset(&dsrdata);
4801 dst_key_free(&dnsseckey);
4802 dns_rdata_freestruct(&dsinfo);
4803 printf("Oops: impossible to build"
4809 if (dns_rdata_compare(&dsrdata,
4810 &newdsrdata) == 0) {
4811 printf(";; OK a DS valids a DNSKEY"
4813 printf(";; Now verify that this"
4814 " DNSKEY validates the "
4817 result = sigchase_verify_sig_key(name,
4820 chase_sigkeyrdataset,
4822 if (result == ISC_R_SUCCESS) {
4823 dns_rdata_reset(&keyrdata);
4824 dns_rdata_reset(&newdsrdata);
4825 dns_rdata_reset(&dsrdata);
4826 dst_key_free(&dnsseckey);
4831 printf(";; This DS is NOT the DS for"
4832 " the chasing KEY: FAILED\n");
4835 dns_rdata_reset(&newdsrdata);
4837 dst_key_free(&dnsseckey);
4838 dns_rdata_reset(&keyrdata);
4840 } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
4841 dns_rdata_reset(&dsrdata);
4843 } while (dns_rdataset_next(chase_dsrdataset) == ISC_R_SUCCESS);
4845 dns_rdata_reset(&keyrdata);
4846 dns_rdata_reset(&newdsrdata);
4847 dns_rdata_reset(&dsrdata);
4849 return (ISC_R_NOTFOUND);
4854 * take a pointer on a rdataset in parameter and try to resolv it.
4855 * the searched rrset is a rrset on 'name' with type 'type'
4856 * (and if the type is a rrsig the signature cover 'covers').
4857 * the lookedup is to known if you have already done the query on the net.
4858 * ISC_R_SUCCESS: if we found the rrset
4859 * ISC_R_NOTFOUND: we do not found the rrset in cache
4860 * and we do a query on the net
4861 * ISC_R_FAILURE: rrset not found
4864 advanced_rrsearch(dns_rdataset_t **rdataset, dns_name_t *name,
4865 dns_rdatatype_t type, dns_rdatatype_t covers,
4866 isc_boolean_t *lookedup)
4868 isc_boolean_t tmplookedup;
4870 INSIST(rdataset != NULL);
4872 if (*rdataset != NULL)
4873 return (ISC_R_SUCCESS);
4875 tmplookedup = *lookedup;
4876 if ((*rdataset = sigchase_scanname(type, covers,
4877 lookedup, name)) == NULL) {
4879 return (ISC_R_FAILURE);
4880 return (ISC_R_NOTFOUND);
4882 *lookedup = ISC_FALSE;
4883 return (ISC_R_SUCCESS);
4890 sigchase_td(dns_message_t *msg)
4892 isc_result_t result;
4893 dns_name_t *name = NULL;
4894 isc_boolean_t have_answer = ISC_FALSE;
4895 isc_boolean_t true = ISC_TRUE;
4897 if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
4899 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
4900 if (current_lookup->trace_root_sigchase) {
4901 initialization(name);
4906 if (!current_lookup->trace_root_sigchase) {
4907 result = dns_message_firstname(msg,
4908 DNS_SECTION_AUTHORITY);
4909 if (result == ISC_R_SUCCESS)
4910 dns_message_currentname(msg,
4911 DNS_SECTION_AUTHORITY,
4914 = chase_scanname_section(msg, name,
4917 DNS_SECTION_AUTHORITY);
4918 dup_name(name, &chase_authority_name, mctx);
4919 if (chase_nsrdataset != NULL) {
4920 have_delegation_ns = ISC_TRUE;
4921 printf("no response but there is a delegation"
4922 " in authority section:");
4923 dns_name_print(name, stdout);
4926 printf("no response and no delegation in "
4927 "authority section but a reference"
4929 dns_name_print(name, stdout);
4931 error_message = msg;
4934 printf(";; NO ANSWERS: %s\n",
4935 isc_result_totext(result));
4936 free_name(&chase_name, mctx);
4945 = chase_scanname_section(msg, &chase_name,
4949 DNS_SECTION_ANSWER);
4950 if (chase_rdataset != NULL)
4951 have_response = ISC_TRUE;
4954 result = advanced_rrsearch(&chase_keyrdataset,
4955 &chase_current_name,
4956 dns_rdatatype_dnskey,
4958 &chase_keylookedup);
4959 if (result == ISC_R_FAILURE) {
4960 printf("\n;; DNSKEY is missing to continue validation:"
4964 if (result == ISC_R_NOTFOUND)
4966 INSIST(chase_keyrdataset != NULL);
4967 printf("\n;; DNSKEYset:\n");
4968 print_rdataset(&chase_current_name , chase_keyrdataset, mctx);
4971 result = advanced_rrsearch(&chase_sigkeyrdataset,
4972 &chase_current_name,
4973 dns_rdatatype_rrsig,
4974 dns_rdatatype_dnskey,
4975 &chase_sigkeylookedup);
4976 if (result == ISC_R_FAILURE) {
4977 printf("\n;; RRSIG of DNSKEY is missing to continue validation:"
4981 if (result == ISC_R_NOTFOUND)
4983 INSIST(chase_sigkeyrdataset != NULL);
4984 printf("\n;; RRSIG of the DNSKEYset:\n");
4985 print_rdataset(&chase_current_name , chase_sigkeyrdataset, mctx);
4988 if (!chase_dslookedup && !chase_nslookedup) {
4989 if (!delegation_follow) {
4990 result = contains_trusted_key(&chase_current_name,
4992 chase_sigkeyrdataset,
4995 INSIST(chase_dsrdataset != NULL);
4996 INSIST(chase_sigdsrdataset != NULL);
4997 result = sigchase_verify_ds(&chase_current_name,
5003 if (result != ISC_R_SUCCESS) {
5004 printf("\n;; chain of trust can't be validated:"
5008 chase_dsrdataset = NULL;
5009 chase_sigdsrdataset = NULL;
5013 if (have_response || (!have_delegation_ns && !have_response)) {
5014 /* test if it's a grand father case */
5016 if (have_response) {
5017 result = advanced_rrsearch(&chase_sigrdataset,
5019 dns_rdatatype_rrsig,
5023 if (result == ISC_R_FAILURE) {
5024 printf("\n;; RRset is missing to continue"
5025 " validation SHOULD NOT APPEND:"
5031 result = advanced_rrsearch(&chase_sigrdataset,
5032 &chase_authority_name,
5033 dns_rdatatype_rrsig,
5036 if (result == ISC_R_FAILURE) {
5037 printf("\n;; RRSIG is missing to continue"
5038 " validation SHOULD NOT APPEND:"
5043 result = grandfather_pb_test(&chase_current_name,
5045 if (result != ISC_R_SUCCESS) {
5046 dns_name_t tmp_name;
5048 printf("\n;; We are in a Grand Father Problem:"
5049 " See 2.2.1 in RFC 3568\n");
5050 chase_rdataset = NULL;
5051 chase_sigrdataset = NULL;
5052 have_response = ISC_FALSE;
5053 have_delegation_ns = ISC_FALSE;
5055 dns_name_init(&tmp_name, NULL);
5056 result = child_of_zone(&chase_name, &chase_current_name,
5058 if (dns_name_dynamic(&chase_authority_name))
5059 free_name(&chase_authority_name, mctx);
5060 dup_name(&tmp_name, &chase_authority_name, mctx);
5061 printf(";; and we try to continue chain of trust"
5062 " validation of the zone: ");
5063 dns_name_print(&chase_authority_name, stdout);
5065 have_delegation_ns = ISC_TRUE;
5070 chase_sigrdataset = NULL;
5074 if (have_delegation_ns) {
5075 chase_nsrdataset = NULL;
5076 result = advanced_rrsearch(&chase_nsrdataset,
5077 &chase_authority_name,
5081 if (result == ISC_R_FAILURE) {
5082 printf("\n;;NSset is missing to continue validation:"
5086 if (result == ISC_R_NOTFOUND) {
5089 INSIST(chase_nsrdataset != NULL);
5091 result = advanced_rrsearch(&chase_dsrdataset,
5092 &chase_authority_name,
5096 if (result == ISC_R_FAILURE) {
5097 printf("\n;; DSset is missing to continue validation:"
5101 if (result == ISC_R_NOTFOUND)
5103 INSIST(chase_dsrdataset != NULL);
5104 printf("\n;; DSset:\n");
5105 print_rdataset(&chase_authority_name , chase_dsrdataset, mctx);
5107 result = advanced_rrsearch(&chase_sigdsrdataset,
5108 &chase_authority_name,
5109 dns_rdatatype_rrsig,
5112 if (result != ISC_R_SUCCESS) {
5113 printf("\n;; DSset is missing to continue validation:"
5117 printf("\n;; RRSIGset of DSset\n");
5118 print_rdataset(&chase_authority_name,
5119 chase_sigdsrdataset, mctx);
5120 INSIST(chase_sigdsrdataset != NULL);
5122 result = sigchase_verify_sig(&chase_authority_name,
5125 chase_sigdsrdataset, mctx);
5126 if (result != ISC_R_SUCCESS) {
5127 printf("\n;; Impossible to verify the DSset:"
5131 chase_keyrdataset = NULL;
5132 chase_sigkeyrdataset = NULL;
5135 prepare_lookup(&chase_authority_name);
5137 have_response = ISC_FALSE;
5138 have_delegation_ns = ISC_FALSE;
5139 delegation_follow = ISC_TRUE;
5140 error_message = NULL;
5141 dup_name(&chase_authority_name, &chase_current_name, mctx);
5142 free_name(&chase_authority_name, mctx);
5147 if (error_message != NULL) {
5148 dns_rdataset_t *rdataset;
5149 dns_rdataset_t *sigrdataset;
5150 dns_name_t rdata_name;
5151 isc_result_t ret = ISC_R_FAILURE;
5153 dns_name_init(&rdata_name, NULL);
5154 result = prove_nx(error_message, &chase_name,
5155 current_lookup->rdclass_sigchase,
5156 current_lookup->rdtype_sigchase, &rdata_name,
5157 &rdataset, &sigrdataset);
5158 if (rdataset == NULL || sigrdataset == NULL ||
5159 dns_name_countlabels(&rdata_name) == 0) {
5160 printf("\n;; Impossible to verify the non-existence,"
5161 " the NSEC RRset can't be validated:"
5165 ret = sigchase_verify_sig(&rdata_name, rdataset,
5168 if (ret != ISC_R_SUCCESS) {
5169 free_name(&rdata_name, mctx);
5170 printf("\n;; Impossible to verify the NSEC RR to prove"
5171 " the non-existence : FAILED\n\n");
5174 free_name(&rdata_name, mctx);
5175 if (result != ISC_R_SUCCESS) {
5176 printf("\n;; Impossible to verify the non-existence:"
5180 printf("\n;; OK the query doesn't have response but"
5181 " we have validate this fact : SUCCESS\n\n");
5187 printf(";; cleanandgo \n");
5188 if (dns_name_dynamic(&chase_current_name))
5189 free_name(&chase_current_name, mctx);
5190 if (dns_name_dynamic(&chase_authority_name))
5191 free_name(&chase_authority_name, mctx);
5196 result = advanced_rrsearch(&chase_rdataset, &chase_name,
5197 current_lookup->rdtype_sigchase,
5200 if (result == ISC_R_FAILURE) {
5201 printf("\n;; RRsig of RRset is missing to continue validation"
5202 " SHOULD NOT APPEND: FAILED\n\n");
5205 result = sigchase_verify_sig(&chase_name, chase_rdataset,
5207 chase_sigrdataset, mctx);
5208 if (result != ISC_R_SUCCESS) {
5209 printf("\n;; Impossible to verify the RRset : FAILED\n\n");
5212 print_rdataset(&chase_name , chase_rdataset, mctx);
5213 printf("DNSKEYset:\n");
5214 print_rdataset(&chase_name , chase_keyrdataset, mctx);
5215 printf("RRSIG of RRset:\n");
5216 print_rdataset(&chase_name , chase_sigrdataset, mctx);
5221 printf("\n;; The Answer:\n");
5222 print_rdataset(&chase_name , chase_rdataset, mctx);
5224 printf("\n;; FINISH : we have validate the DNSSEC chain"
5225 " of trust: SUCCESS\n\n");
5236 getneededrr(dns_message_t *msg)
5238 isc_result_t result;
5239 dns_name_t *name = NULL;
5240 dns_rdata_t sigrdata = DNS_RDATA_INIT;
5241 dns_rdata_sig_t siginfo;
5242 isc_boolean_t true = ISC_TRUE;
5244 if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
5246 printf(";; NO ANSWERS: %s\n", isc_result_totext(result));
5248 if (chase_name.ndata == NULL)
5249 return (ISC_R_ADDRNOTAVAIL);
5251 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
5254 /* What do we chase? */
5255 if (chase_rdataset == NULL) {
5256 result = advanced_rrsearch(&chase_rdataset, name,
5258 dns_rdatatype_any, &true);
5259 if (result != ISC_R_SUCCESS) {
5260 printf("\n;; No Answers: Validation FAILED\n\n");
5261 return (ISC_R_NOTFOUND);
5263 dup_name(name, &chase_name, mctx);
5264 printf(";; RRset to chase:\n");
5265 print_rdataset(&chase_name, chase_rdataset, mctx);
5267 INSIST(chase_rdataset != NULL);
5270 if (chase_sigrdataset == NULL) {
5271 result = advanced_rrsearch(&chase_sigrdataset, name,
5272 dns_rdatatype_rrsig,
5273 chase_rdataset->type,
5274 &chase_siglookedup);
5275 if (result == ISC_R_FAILURE) {
5276 printf("\n;; RRSIG is missing for continue validation:"
5278 if (dns_name_dynamic(&chase_name))
5279 free_name(&chase_name, mctx);
5280 return (ISC_R_NOTFOUND);
5282 if (result == ISC_R_NOTFOUND) {
5283 return (ISC_R_NOTFOUND);
5285 printf("\n;; RRSIG of the RRset to chase:\n");
5286 print_rdataset(&chase_name, chase_sigrdataset, mctx);
5288 INSIST(chase_sigrdataset != NULL);
5291 /* first find the DNSKEY name */
5292 result = dns_rdataset_first(chase_sigrdataset);
5293 check_result(result, "empty RRSIG dataset");
5294 dns_rdataset_current(chase_sigrdataset, &sigrdata);
5295 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
5296 check_result(result, "sigrdata tostruct siginfo");
5297 dup_name(&siginfo.signer, &chase_signame, mctx);
5298 dns_rdata_freestruct(&siginfo);
5299 dns_rdata_reset(&sigrdata);
5301 /* Do we have a key? */
5302 if (chase_keyrdataset == NULL) {
5303 result = advanced_rrsearch(&chase_keyrdataset,
5305 dns_rdatatype_dnskey,
5307 &chase_keylookedup);
5308 if (result == ISC_R_FAILURE) {
5309 printf("\n;; DNSKEY is missing to continue validation:"
5311 free_name(&chase_signame, mctx);
5312 if (dns_name_dynamic(&chase_name))
5313 free_name(&chase_name, mctx);
5314 return (ISC_R_NOTFOUND);
5316 if (result == ISC_R_NOTFOUND) {
5317 free_name(&chase_signame, mctx);
5318 return (ISC_R_NOTFOUND);
5320 printf("\n;; DNSKEYset that signs the RRset to chase:\n");
5321 print_rdataset(&chase_signame, chase_keyrdataset, mctx);
5323 INSIST(chase_keyrdataset != NULL);
5325 if (chase_sigkeyrdataset == NULL) {
5326 result = advanced_rrsearch(&chase_sigkeyrdataset,
5328 dns_rdatatype_rrsig,
5329 dns_rdatatype_dnskey,
5330 &chase_sigkeylookedup);
5331 if (result == ISC_R_FAILURE) {
5332 printf("\n;; RRSIG for DNSKEY is missing to continue"
5333 " validation : FAILED\n\n");
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;; RRSIG of the DNSKEYset that signs the "
5344 "RRset to chase:\n");
5345 print_rdataset(&chase_signame, chase_sigkeyrdataset, mctx);
5347 INSIST(chase_sigkeyrdataset != NULL);
5350 if (chase_dsrdataset == NULL) {
5351 result = advanced_rrsearch(&chase_dsrdataset, &chase_signame,
5355 if (result == ISC_R_FAILURE) {
5356 printf("\n;; WARNING There is no DS for the zone: ");
5357 dns_name_print(&chase_signame, stdout);
5360 if (result == ISC_R_NOTFOUND) {
5361 free_name(&chase_signame, mctx);
5362 return (ISC_R_NOTFOUND);
5364 if (chase_dsrdataset != NULL) {
5365 printf("\n;; DSset of the DNSKEYset\n");
5366 print_rdataset(&chase_signame, chase_dsrdataset, mctx);
5370 if (chase_dsrdataset != NULL) {
5372 * if there is no RRSIG of DS,
5373 * we don't want to search on the network
5375 result = advanced_rrsearch(&chase_sigdsrdataset,
5377 dns_rdatatype_rrsig,
5378 dns_rdatatype_ds, &true);
5379 if (result == ISC_R_FAILURE) {
5380 printf(";; WARNING : NO RRSIG DS : RRSIG DS"
5381 " should come with DS\n");
5383 * We continue even the DS couldn't be validated,
5384 * because the DNSKEY could be a Trusted Key.
5386 chase_dsrdataset = NULL;
5388 printf("\n;; RRSIG of the DSset of the DNSKEYset\n");
5389 print_rdataset(&chase_signame, chase_sigdsrdataset,
5399 sigchase_bu(dns_message_t *msg)
5401 isc_result_t result;
5404 if (tk_list.nb_tk == 0) {
5405 result = get_trusted_key(mctx);
5406 if (result != ISC_R_SUCCESS) {
5407 printf("No trusted keys present\n");
5413 ret = getneededrr(msg);
5414 if (ret == ISC_R_NOTFOUND)
5417 if (ret == ISC_R_ADDRNOTAVAIL) {
5418 /* We have no response */
5419 dns_rdataset_t *rdataset;
5420 dns_rdataset_t *sigrdataset;
5421 dns_name_t rdata_name;
5422 dns_name_t query_name;
5425 dns_name_init(&query_name, NULL);
5426 dns_name_init(&rdata_name, NULL);
5427 nameFromString(current_lookup->textname, &query_name);
5429 result = prove_nx(msg, &query_name, current_lookup->rdclass,
5430 current_lookup->rdtype, &rdata_name,
5431 &rdataset, &sigrdataset);
5432 free_name(&query_name, mctx);
5433 if (rdataset == NULL || sigrdataset == NULL ||
5434 dns_name_countlabels(&rdata_name) == 0) {
5435 printf("\n;; Impossible to verify the Non-existence,"
5436 " the NSEC RRset can't be validated: "
5442 if (result != ISC_R_SUCCESS) {
5443 printf("\n No Answers and impossible to prove the"
5444 " unsecurity : Validation FAILED\n\n");
5448 printf(";; An NSEC prove the non-existence of a answers,"
5449 " Now we want validate this NSEC\n");
5451 dup_name(&rdata_name, &chase_name, mctx);
5452 free_name(&rdata_name, mctx);
5453 chase_rdataset = rdataset;
5454 chase_sigrdataset = sigrdataset;
5455 chase_keyrdataset = NULL;
5456 chase_sigkeyrdataset = NULL;
5457 chase_dsrdataset = NULL;
5458 chase_sigdsrdataset = NULL;
5459 chase_siglookedup = ISC_FALSE;
5460 chase_keylookedup = ISC_FALSE;
5461 chase_dslookedup = ISC_FALSE;
5462 chase_sigdslookedup = ISC_FALSE;
5469 printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n");
5471 result = sigchase_verify_sig(&chase_name, chase_rdataset,
5473 chase_sigrdataset, mctx);
5474 if (result != ISC_R_SUCCESS) {
5475 free_name(&chase_name, mctx);
5476 free_name(&chase_signame, mctx);
5477 printf(";; No DNSKEY is valid to check the RRSIG"
5478 " of the RRset: FAILED\n");
5482 printf(";; OK We found DNSKEY (or more) to validate the RRset\n");
5484 result = contains_trusted_key(&chase_signame, chase_keyrdataset,
5485 chase_sigkeyrdataset, mctx);
5486 if (result == ISC_R_SUCCESS) {
5487 free_name(&chase_name, mctx);
5488 free_name(&chase_signame, mctx);
5489 printf("\n;; Ok this DNSKEY is a Trusted Key,"
5490 " DNSSEC validation is ok: SUCCESS\n\n");
5495 printf(";; Now, we are going to validate this DNSKEY by the DS\n");
5497 if (chase_dsrdataset == NULL) {
5498 free_name(&chase_name, mctx);
5499 free_name(&chase_signame, mctx);
5500 printf(";; the DNSKEY isn't trusted-key and there isn't"
5501 " DS to validate the DNSKEY: FAILED\n");
5506 result = sigchase_verify_ds(&chase_signame, chase_keyrdataset,
5507 chase_dsrdataset, mctx);
5508 if (result != ISC_R_SUCCESS) {
5509 free_name(&chase_signame, mctx);
5510 free_name(&chase_name, mctx);
5511 printf(";; ERROR no DS validates a DNSKEY in the"
5512 " DNSKEY RRset: FAILED\n");
5516 printf(";; OK this DNSKEY (validated by the DS) validates"
5517 " the RRset of the DNSKEYs, thus the DNSKEY validates"
5519 INSIST(chase_sigdsrdataset != NULL);
5521 dup_name(&chase_signame, &chase_name, mctx);
5522 free_name(&chase_signame, mctx);
5523 chase_rdataset = chase_dsrdataset;
5524 chase_sigrdataset = chase_sigdsrdataset;
5525 chase_keyrdataset = NULL;
5526 chase_sigkeyrdataset = NULL;
5527 chase_dsrdataset = NULL;
5528 chase_sigdsrdataset = NULL;
5529 chase_siglookedup = chase_keylookedup = ISC_FALSE;
5530 chase_dslookedup = chase_sigdslookedup = ISC_FALSE;
5532 printf(";; Now, we want to validate the DS : recursive call\n");
5539 sigchase(dns_message_t *msg) {
5541 if (current_lookup->do_topdown) {
5554 * return 1 if name1 < name2
5555 * 0 if name1 == name2
5556 * -1 if name1 > name2
5560 inf_name(dns_name_t *name1, dns_name_t *name2)
5564 unsigned int nblabel1;
5565 unsigned int nblabel2;
5570 nblabel1 = dns_name_countlabels(name1);
5571 nblabel2 = dns_name_countlabels(name2);
5573 if (nblabel1 >= nblabel2)
5574 min_lum_label = nblabel2;
5576 min_lum_label = nblabel1;
5579 for (i=1 ; i < min_lum_label; i++) {
5580 dns_name_getlabel(name1, nblabel1 -1 - i, &label1);
5581 dns_name_getlabel(name2, nblabel2 -1 - i, &label2);
5582 if ((ret = isc_region_compare(&label1, &label2)) != 0) {
5589 if (nblabel1 == nblabel2)
5592 if (nblabel1 < nblabel2)
5604 prove_nx_domain(dns_message_t *msg,
5606 dns_name_t *rdata_name,
5607 dns_rdataset_t **rdataset,
5608 dns_rdataset_t **sigrdataset)
5610 isc_result_t ret = ISC_R_FAILURE;
5611 isc_result_t result = ISC_R_NOTFOUND;
5612 dns_rdataset_t *nsecset = NULL;
5613 dns_rdataset_t *signsecset = NULL ;
5614 dns_rdata_t nsec = DNS_RDATA_INIT;
5615 dns_name_t *nsecname;
5616 dns_rdata_nsec_t nsecstruct;
5618 if ((result = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
5620 printf(";; nothing in authority section : impossible to"
5621 " validate the non-existence : FAILED\n");
5622 return (ISC_R_FAILURE);
5627 dns_message_currentname(msg, DNS_SECTION_AUTHORITY, &nsecname);
5628 nsecset = search_type(nsecname, dns_rdatatype_nsec,
5630 if (nsecset == NULL)
5633 printf("There is a NSEC for this zone in the"
5634 " AUTHORITY section:\n");
5635 print_rdataset(nsecname, nsecset, mctx);
5637 for (result = dns_rdataset_first(nsecset);
5638 result == ISC_R_SUCCESS;
5639 result = dns_rdataset_next(nsecset)) {
5640 dns_rdataset_current(nsecset, &nsec);
5644 = chase_scanname_section(msg, nsecname,
5645 dns_rdatatype_rrsig,
5647 DNS_SECTION_AUTHORITY);
5648 if (signsecset == NULL) {
5649 printf(";; no RRSIG NSEC in authority section:"
5650 " impossible to validate the "
5651 "non-existence: FAILED\n");
5652 return (ISC_R_FAILURE);
5655 ret = dns_rdata_tostruct(&nsec, &nsecstruct, NULL);
5656 check_result(ret,"dns_rdata_tostruct");
5658 if ((inf_name(nsecname, &nsecstruct.next) == 1 &&
5659 inf_name(name, &nsecstruct.next) == 1) ||
5660 (inf_name(name, nsecname) == 1 &&
5661 inf_name(&nsecstruct.next, name) == 1)) {
5662 dns_rdata_freestruct(&nsecstruct);
5663 *rdataset = nsecset;
5664 *sigrdataset = signsecset;
5665 dup_name(nsecname, rdata_name, mctx);
5667 return (ISC_R_SUCCESS);
5670 dns_rdata_freestruct(&nsecstruct);
5671 dns_rdata_reset(&nsec);
5673 } while (dns_message_nextname(msg, DNS_SECTION_AUTHORITY)
5677 *sigrdataset = NULL;
5679 return (ISC_R_FAILURE);
5690 prove_nx_type(dns_message_t *msg, dns_name_t *name, dns_rdataset_t *nsecset,
5691 dns_rdataclass_t class, dns_rdatatype_t type,
5692 dns_name_t *rdata_name, dns_rdataset_t **rdataset,
5693 dns_rdataset_t **sigrdataset)
5696 dns_rdataset_t *signsecset;
5697 dns_rdata_t nsec = DNS_RDATA_INIT;
5701 ret = dns_rdataset_first(nsecset);
5702 check_result(ret,"dns_rdataset_first");
5704 dns_rdataset_current(nsecset, &nsec);
5706 ret = dns_nsec_typepresent(&nsec, type);
5707 if (ret == ISC_R_SUCCESS)
5708 printf("OK the NSEC said that the type doesn't exist \n");
5710 signsecset = chase_scanname_section(msg, name,
5711 dns_rdatatype_rrsig,
5713 DNS_SECTION_AUTHORITY);
5714 if (signsecset == NULL) {
5715 printf("There isn't RRSIG NSEC for the zone \n");
5716 return (ISC_R_FAILURE);
5718 dup_name(name, rdata_name, mctx);
5719 *rdataset = nsecset;
5720 *sigrdataset = signsecset;
5732 prove_nx(dns_message_t *msg, dns_name_t *name, dns_rdataclass_t class,
5733 dns_rdatatype_t type, dns_name_t *rdata_name,
5734 dns_rdataset_t **rdataset, dns_rdataset_t **sigrdataset)
5737 dns_rdataset_t *nsecset = NULL;
5739 printf("We want to prove the non-existence of a type of rdata %d"
5740 " or of the zone: \n", type);
5742 if ((ret = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
5744 printf(";; nothing in authority section : impossible to"
5745 " validate the non-existence : FAILED\n");
5746 return (ISC_R_FAILURE);
5749 nsecset = chase_scanname_section(msg, name, dns_rdatatype_nsec,
5751 DNS_SECTION_AUTHORITY);
5752 if (nsecset != NULL) {
5753 printf("We have a NSEC for this zone :OK\n");
5754 ret = prove_nx_type(msg, name, nsecset, class,
5755 type, rdata_name, rdataset,
5757 if (ret != ISC_R_SUCCESS) {
5758 printf("prove_nx: ERROR type exist\n");
5761 printf("prove_nx: OK type does not exist\n");
5762 return (ISC_R_SUCCESS);
5765 printf("there is no NSEC for this zone: validating "
5766 "that the zone doesn't exist\n");
5767 ret = prove_nx_domain(msg, name, rdata_name,
5768 rdataset, sigrdataset);
5771 /* Never get here */