2 * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: dighost.c,v 1.345 2011/12/07 17:23:28 each Exp $ */
22 * Notice to programmers: Do not use this code as an example of how to
23 * use the ISC library to perform DNS lookups. Dig and Host both operate
24 * on the request level, since they allow fine-tuning of output and are
25 * intended as debugging tools. As a result, they perform many of the
26 * functions which could be better handled using the dns_resolver
27 * functions in most applications.
41 #include <idn/result.h>
43 #include <idn/resconf.h>
47 #include <dns/byaddr.h>
49 #include <dns/callbacks.h>
50 #include <dns/dnssec.h>
52 #include <dns/master.h>
54 #include <isc/random.h>
57 #include <dns/fixedname.h>
59 #include <dns/message.h>
61 #include <dns/rdata.h>
62 #include <dns/rdataclass.h>
63 #include <dns/rdatalist.h>
64 #include <dns/rdataset.h>
65 #include <dns/rdatastruct.h>
66 #include <dns/rdatatype.h>
67 #include <dns/result.h>
71 #include <dst/result.h>
74 #include <isc/base64.h>
75 #include <isc/entropy.h>
79 #include <isc/netaddr.h>
81 #include <isc/netdb.h>
83 #include <isc/parseint.h>
84 #include <isc/print.h>
85 #include <isc/random.h>
86 #include <isc/result.h>
87 #include <isc/serial.h>
88 #include <isc/string.h>
90 #include <isc/timer.h>
91 #include <isc/types.h>
94 #include <isccfg/namedconf.h>
96 #include <lwres/lwres.h>
97 #include <lwres/net.h>
99 #include <bind9/getaddresses.h>
103 #if ! defined(NS_INADDRSZ)
104 #define NS_INADDRSZ 4
107 #if ! defined(NS_IN6ADDRSZ)
108 #define NS_IN6ADDRSZ 16
111 static lwres_context_t *lwctx = NULL;
112 static lwres_conf_t *lwconf;
114 dig_lookuplist_t lookup_list;
115 dig_serverlist_t server_list;
116 dig_searchlistlist_t search_list;
119 check_ra = ISC_FALSE,
120 have_ipv4 = ISC_FALSE,
121 have_ipv6 = ISC_FALSE,
122 specified_source = ISC_FALSE,
123 free_now = ISC_FALSE,
124 cancel_now = ISC_FALSE,
125 usesearch = ISC_FALSE,
126 showsearch = ISC_FALSE,
128 is_dst_up = ISC_FALSE,
129 keep_open = ISC_FALSE;
131 unsigned int timeout = 0;
132 unsigned int extrabytes;
133 isc_mem_t *mctx = NULL;
134 isc_log_t *lctx = NULL;
135 isc_taskmgr_t *taskmgr = NULL;
136 isc_task_t *global_task = NULL;
137 isc_timermgr_t *timermgr = NULL;
138 isc_socketmgr_t *socketmgr = NULL;
139 isc_sockaddr_t bind_address;
140 isc_sockaddr_t bind_any;
146 int lookup_counter = 0;
149 static void initialize_idn(void);
150 static isc_result_t output_filter(isc_buffer_t *buffer,
151 unsigned int used_org,
152 isc_boolean_t absolute);
153 static idn_result_t append_textname(char *name, const char *origin,
155 static void idn_check_result(idn_result_t r, const char *msg);
161 isc_socket_t *keep = NULL;
162 isc_sockaddr_t keepaddr;
167 *\li 0 Everything went well, including things like NXDOMAIN
169 *\li 7 Got too many RR's or Names
170 *\li 8 Couldn't open batch file
171 *\li 9 No reply from server
172 *\li 10 Internal error
176 char keynametext[MXNAME];
177 char keyfile[MXNAME] = "";
178 char keysecret[MXNAME] = "";
179 dns_name_t *hmacname = NULL;
180 unsigned int digestbits = 0;
181 isc_buffer_t *namebuf = NULL;
182 dns_tsigkey_t *key = NULL;
183 isc_boolean_t validated = ISC_TRUE;
184 isc_entropy_t *entp = NULL;
185 isc_mempool_t *commctx = NULL;
186 isc_boolean_t debugging = ISC_FALSE;
187 isc_boolean_t debugtiming = ISC_FALSE;
188 isc_boolean_t memdebugging = ISC_FALSE;
189 char *progname = NULL;
190 isc_mutex_t lookup_lock;
191 dig_lookup_t *current_lookup = NULL;
195 isc_result_t get_trusted_key(isc_mem_t *mctx);
196 dns_rdataset_t * sigchase_scanname(dns_rdatatype_t type,
197 dns_rdatatype_t covers,
198 isc_boolean_t *lookedup,
199 dns_name_t *rdata_name);
200 dns_rdataset_t * chase_scanname_section(dns_message_t *msg,
202 dns_rdatatype_t type,
203 dns_rdatatype_t covers,
205 isc_result_t advanced_rrsearch(dns_rdataset_t **rdataset,
207 dns_rdatatype_t type,
208 dns_rdatatype_t covers,
209 isc_boolean_t *lookedup);
210 isc_result_t sigchase_verify_sig_key(dns_name_t *name,
211 dns_rdataset_t *rdataset,
212 dst_key_t* dnsseckey,
213 dns_rdataset_t *sigrdataset,
215 isc_result_t sigchase_verify_sig(dns_name_t *name,
216 dns_rdataset_t *rdataset,
217 dns_rdataset_t *keyrdataset,
218 dns_rdataset_t *sigrdataset,
220 isc_result_t sigchase_verify_ds(dns_name_t *name,
221 dns_rdataset_t *keyrdataset,
222 dns_rdataset_t *dsrdataset,
224 void sigchase(dns_message_t *msg);
225 void print_rdata(dns_rdata_t *rdata, isc_mem_t *mctx);
226 void print_rdataset(dns_name_t *name,
227 dns_rdataset_t *rdataset, isc_mem_t *mctx);
228 void dup_name(dns_name_t *source, dns_name_t* target,
230 void free_name(dns_name_t *name, isc_mem_t *mctx);
231 void dump_database(void);
232 void dump_database_section(dns_message_t *msg, int section);
233 dns_rdataset_t * search_type(dns_name_t *name, dns_rdatatype_t type,
234 dns_rdatatype_t covers);
235 isc_result_t contains_trusted_key(dns_name_t *name,
236 dns_rdataset_t *rdataset,
237 dns_rdataset_t *sigrdataset,
239 void print_type(dns_rdatatype_t type);
240 isc_result_t prove_nx_domain(dns_message_t * msg,
242 dns_name_t * rdata_name,
243 dns_rdataset_t ** rdataset,
244 dns_rdataset_t ** sigrdataset);
245 isc_result_t prove_nx_type(dns_message_t * msg, dns_name_t *name,
246 dns_rdataset_t *nsec,
247 dns_rdataclass_t class,
248 dns_rdatatype_t type,
249 dns_name_t * rdata_name,
250 dns_rdataset_t ** rdataset,
251 dns_rdataset_t ** sigrdataset);
252 isc_result_t prove_nx(dns_message_t * msg, dns_name_t * name,
253 dns_rdataclass_t class,
254 dns_rdatatype_t type,
255 dns_name_t * rdata_name,
256 dns_rdataset_t ** rdataset,
257 dns_rdataset_t ** sigrdataset);
258 static void nameFromString(const char *str, dns_name_t *p_ret);
259 int inf_name(dns_name_t * name1, dns_name_t * name2);
260 isc_result_t removetmpkey(isc_mem_t *mctx, const char *file);
261 void clean_trustedkey(void);
262 isc_result_t insert_trustedkey(void *arg, dns_name_t *name,
263 dns_rdataset_t *rdataset);
265 isc_result_t getneededrr(dns_message_t *msg);
266 void sigchase_bottom_up(dns_message_t *msg);
267 void sigchase_bu(dns_message_t *msg);
270 isc_result_t initialization(dns_name_t *name);
271 isc_result_t prepare_lookup(dns_name_t *name);
272 isc_result_t grandfather_pb_test(dns_name_t * zone_name,
273 dns_rdataset_t *sigrdataset);
274 isc_result_t child_of_zone(dns_name_t *name,
275 dns_name_t *zone_name,
276 dns_name_t *child_name);
277 void sigchase_td(dns_message_t *msg);
279 char trustedkey[MXNAME] = "";
281 dns_rdataset_t *chase_rdataset = NULL;
282 dns_rdataset_t *chase_sigrdataset = NULL;
283 dns_rdataset_t *chase_dsrdataset = NULL;
284 dns_rdataset_t *chase_sigdsrdataset = NULL;
285 dns_rdataset_t *chase_keyrdataset = NULL;
286 dns_rdataset_t *chase_sigkeyrdataset = NULL;
287 dns_rdataset_t *chase_nsrdataset = NULL;
289 dns_name_t chase_name; /* the query name */
292 * the current name is the parent name when we follow delegation
294 dns_name_t chase_current_name;
296 * the child name is used for delegation (NS DS responses in AUTHORITY section)
298 dns_name_t chase_authority_name;
301 dns_name_t chase_signame;
305 isc_boolean_t chase_siglookedup = ISC_FALSE;
306 isc_boolean_t chase_keylookedup = ISC_FALSE;
307 isc_boolean_t chase_sigkeylookedup = ISC_FALSE;
308 isc_boolean_t chase_dslookedup = ISC_FALSE;
309 isc_boolean_t chase_sigdslookedup = ISC_FALSE;
311 isc_boolean_t chase_nslookedup = ISC_FALSE;
312 isc_boolean_t chase_lookedup = ISC_FALSE;
315 isc_boolean_t delegation_follow = ISC_FALSE;
316 isc_boolean_t grandfather_pb = ISC_FALSE;
317 isc_boolean_t have_response = ISC_FALSE;
318 isc_boolean_t have_delegation_ns = ISC_FALSE;
319 dns_message_t * error_message = NULL;
322 isc_boolean_t dsvalidating = ISC_FALSE;
323 isc_boolean_t chase_name_dup = ISC_FALSE;
325 ISC_LIST(dig_message_t) chase_message_list;
326 ISC_LIST(dig_message_t) chase_message_list2;
329 #define MAX_TRUSTED_KEY 5
330 typedef struct struct_trusted_key_list {
331 dst_key_t * key[MAX_TRUSTED_KEY];
335 struct_tk_list tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0};
339 #define DIG_MAX_ADDRESSES 20
342 * Apply and clear locks at the event level in global task.
343 * Can I get rid of these using shutdown events? XXX
345 #define LOCK_LOOKUP {\
346 debug("lock_lookup %s:%d", __FILE__, __LINE__);\
347 check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\
350 #define UNLOCK_LOOKUP {\
351 debug("unlock_lookup %s:%d", __FILE__, __LINE__);\
352 check_result(isc_mutex_unlock((&lookup_lock)),\
353 "isc_mutex_unlock");\
357 cancel_lookup(dig_lookup_t *lookup);
360 recv_done(isc_task_t *task, isc_event_t *event);
363 send_udp(dig_query_t *query);
366 connect_timeout(isc_task_t *task, isc_event_t *event);
369 launch_next_query(dig_query_t *query, isc_boolean_t include_question);
373 mem_alloc(void *arg, size_t size) {
374 return (isc_mem_get(arg, size));
378 mem_free(void *arg, void *mem, size_t size) {
379 isc_mem_put(arg, mem, size);
383 next_token(char **stringp, const char *delim) {
387 res = strsep(stringp, delim);
390 } while (*res == '\0');
395 count_dots(char *string) {
409 hex_dump(isc_buffer_t *b) {
413 isc_buffer_usedregion(b, &r);
415 printf("%d bytes\n", r.length);
416 for (len = 0; len < r.length; len++) {
417 printf("%02x ", r.base[len]);
418 if (len % 16 == 15) {
420 for (i = len - 15; i <= len; i++) {
421 if (r.base[i] >= '!' && r.base[i] <= '}')
430 for (i = len; (i % 16) != 0; i++)
433 for (i = ((len>>4)<<4); i < len; i++) {
434 if (r.base[i] >= '!' && r.base[i] <= '}')
444 * Append 'len' bytes of 'text' at '*p', failing with
445 * ISC_R_NOSPACE if that would advance p past 'end'.
448 append(const char *text, int len, char **p, char *end) {
450 return (ISC_R_NOSPACE);
451 memmove(*p, text, len);
453 return (ISC_R_SUCCESS);
457 reverse_octets(const char *in, char **p, char *end) {
458 char *dot = strchr(in, '.');
462 result = reverse_octets(dot + 1, p, end);
463 if (result != ISC_R_SUCCESS)
465 result = append(".", 1, p, end);
466 if (result != ISC_R_SUCCESS)
468 len = (int)(dot - in);
472 return (append(in, len, p, end));
476 get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int,
477 isc_boolean_t strict)
483 addr.family = AF_INET6;
484 r = inet_pton(AF_INET6, value, &addr.type.in6);
486 /* This is a valid IPv6 address. */
487 dns_fixedname_t fname;
489 unsigned int options = 0;
492 options |= DNS_BYADDROPT_IPV6INT;
493 dns_fixedname_init(&fname);
494 name = dns_fixedname_name(&fname);
495 result = dns_byaddr_createptrname2(&addr, options, name);
496 if (result != ISC_R_SUCCESS)
498 dns_name_format(name, reverse, (unsigned int)len);
499 return (ISC_R_SUCCESS);
502 * Not a valid IPv6 address. Assume IPv4.
503 * If 'strict' is not set, construct the
504 * in-addr.arpa name by blindly reversing
505 * octets whether or not they look like integers,
506 * so that this can be used for RFC2317 names
510 char *end = reverse + len;
511 if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1)
512 return (DNS_R_BADDOTTEDQUAD);
513 result = reverse_octets(value, &p, end);
514 if (result != ISC_R_SUCCESS)
516 /* Append .in-addr.arpa. and a terminating NUL. */
517 result = append(".in-addr.arpa.", 15, &p, end);
518 if (result != ISC_R_SUCCESS)
520 return (ISC_R_SUCCESS);
525 fatal(const char *format, ...) {
529 fprintf(stderr, "%s: ", progname);
530 va_start(args, format);
531 vfprintf(stderr, format, args);
533 fprintf(stderr, "\n");
537 exitcode = fatalexit;
542 debug(const char *format, ...) {
550 fprintf(stderr, "%d.%06d: ", isc_time_seconds(&t),
551 isc_time_nanoseconds(&t) / 1000);
553 va_start(args, format);
554 vfprintf(stderr, format, args);
556 fprintf(stderr, "\n");
561 check_result(isc_result_t result, const char *msg) {
562 if (result != ISC_R_SUCCESS) {
563 fatal("%s: %s", msg, isc_result_totext(result));
568 * Create a server structure, which is part of the lookup structure.
569 * This is little more than a linked list of servers to query in hopes
570 * of finding the answer the user is looking for
573 make_server(const char *servname, const char *userarg) {
576 REQUIRE(servname != NULL);
578 debug("make_server(%s)", servname);
579 srv = isc_mem_allocate(mctx, sizeof(struct dig_server));
581 fatal("memory allocation failure in %s:%d",
583 strlcpy(srv->servername, servname, MXNAME);
584 strlcpy(srv->userarg, userarg, MXNAME);
585 ISC_LINK_INIT(srv, link);
590 addr2af(int lwresaddrtype)
594 switch (lwresaddrtype) {
595 case LWRES_ADDRTYPE_V4:
599 case LWRES_ADDRTYPE_V6:
608 * Create a copy of the server list from the lwres configuration structure.
609 * The dest list must have already had ISC_LIST_INIT applied.
612 copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) {
613 dig_server_t *newsrv;
614 char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
618 debug("copy_server_list()");
619 for (i = 0; i < confdata->nsnext; i++) {
620 af = addr2af(confdata->nameservers[i].family);
622 if (af == AF_INET && !have_ipv4)
624 if (af == AF_INET6 && !have_ipv6)
627 lwres_net_ntop(af, confdata->nameservers[i].address,
629 newsrv = make_server(tmp, tmp);
630 ISC_LINK_INIT(newsrv, link);
631 ISC_LIST_ENQUEUE(*dest, newsrv, link);
636 flush_server_list(void) {
637 dig_server_t *s, *ps;
639 debug("flush_server_list()");
640 s = ISC_LIST_HEAD(server_list);
643 s = ISC_LIST_NEXT(s, link);
644 ISC_LIST_DEQUEUE(server_list, ps, link);
645 isc_mem_free(mctx, ps);
650 set_nameserver(char *opt) {
652 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
653 isc_netaddr_t netaddr;
656 char tmp[ISC_NETADDR_FORMATSIZE];
661 result = bind9_getaddresses(opt, 0, sockaddrs,
662 DIG_MAX_ADDRESSES, &count);
663 if (result != ISC_R_SUCCESS)
664 fatal("couldn't get address for '%s': %s",
665 opt, isc_result_totext(result));
669 for (i = 0; i < count; i++) {
670 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
671 isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
672 srv = make_server(tmp, opt);
674 fatal("memory allocation failure");
675 ISC_LIST_APPEND(server_list, srv, link);
680 add_nameserver(lwres_conf_t *confdata, const char *addr, int af) {
682 int i = confdata->nsnext;
684 if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS)
685 return (ISC_R_FAILURE);
689 confdata->nameservers[i].family = LWRES_ADDRTYPE_V4;
690 confdata->nameservers[i].length = NS_INADDRSZ;
693 confdata->nameservers[i].family = LWRES_ADDRTYPE_V6;
694 confdata->nameservers[i].length = NS_IN6ADDRSZ;
697 return (ISC_R_FAILURE);
700 if (lwres_net_pton(af, addr, &confdata->nameservers[i].address) == 1) {
702 return (ISC_R_SUCCESS);
704 return (ISC_R_FAILURE);
708 * Produce a cloned server list. The dest list must have already had
709 * ISC_LIST_INIT applied.
712 clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
713 dig_server_t *srv, *newsrv;
715 debug("clone_server_list()");
716 srv = ISC_LIST_HEAD(src);
717 while (srv != NULL) {
718 newsrv = make_server(srv->servername, srv->userarg);
719 ISC_LINK_INIT(newsrv, link);
720 ISC_LIST_ENQUEUE(*dest, newsrv, link);
721 srv = ISC_LIST_NEXT(srv, link);
726 * Create an empty lookup structure, which holds all the information needed
727 * to get an answer to a user's question. This structure contains two
728 * linked lists: the server list (servers to query) and the query list
729 * (outstanding queries which have been made to the listed servers).
732 make_empty_lookup(void) {
733 dig_lookup_t *looknew;
735 debug("make_empty_lookup()");
739 looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
741 fatal("memory allocation failure in %s:%d",
743 looknew->pending = ISC_TRUE;
744 looknew->textname[0] = 0;
745 looknew->cmdline[0] = 0;
746 looknew->rdtype = dns_rdatatype_a;
747 looknew->qrdtype = dns_rdatatype_a;
748 looknew->rdclass = dns_rdataclass_in;
749 looknew->rdtypeset = ISC_FALSE;
750 looknew->rdclassset = ISC_FALSE;
751 looknew->sendspace = NULL;
752 looknew->sendmsg = NULL;
753 looknew->name = NULL;
754 looknew->oname = NULL;
755 looknew->timer = NULL;
756 looknew->xfr_q = NULL;
757 looknew->current_query = NULL;
758 looknew->doing_xfr = ISC_FALSE;
759 looknew->ixfr_serial = 0;
760 looknew->trace = ISC_FALSE;
761 looknew->trace_root = ISC_FALSE;
762 looknew->identify = ISC_FALSE;
763 looknew->identify_previous_line = ISC_FALSE;
764 looknew->ignore = ISC_FALSE;
765 looknew->servfail_stops = ISC_TRUE;
766 looknew->besteffort = ISC_TRUE;
767 looknew->dnssec = ISC_FALSE;
768 looknew->nsid = ISC_FALSE;
770 looknew->sigchase = ISC_FALSE;
772 looknew->do_topdown = ISC_FALSE;
773 looknew->trace_root_sigchase = ISC_FALSE;
774 looknew->rdtype_sigchaseset = ISC_FALSE;
775 looknew->rdtype_sigchase = dns_rdatatype_any;
776 looknew->qrdtype_sigchase = dns_rdatatype_any;
777 looknew->rdclass_sigchase = dns_rdataclass_in;
778 looknew->rdclass_sigchaseset = ISC_FALSE;
781 looknew->udpsize = 0;
783 looknew->recurse = ISC_TRUE;
784 looknew->aaonly = ISC_FALSE;
785 looknew->adflag = ISC_FALSE;
786 looknew->cdflag = ISC_FALSE;
787 looknew->ns_search_only = ISC_FALSE;
788 looknew->origin = NULL;
789 looknew->tsigctx = NULL;
790 looknew->querysig = NULL;
791 looknew->retries = tries;
792 looknew->nsfound = 0;
793 looknew->tcp_mode = ISC_FALSE;
794 looknew->ip6_int = ISC_FALSE;
795 looknew->comments = ISC_TRUE;
796 looknew->stats = ISC_TRUE;
797 looknew->section_question = ISC_TRUE;
798 looknew->section_answer = ISC_TRUE;
799 looknew->section_authority = ISC_TRUE;
800 looknew->section_additional = ISC_TRUE;
801 looknew->new_search = ISC_FALSE;
802 looknew->done_as_is = ISC_FALSE;
803 looknew->need_search = ISC_FALSE;
804 ISC_LINK_INIT(looknew, link);
805 ISC_LIST_INIT(looknew->q);
806 ISC_LIST_INIT(looknew->connecting);
807 ISC_LIST_INIT(looknew->my_server_list);
812 * Clone a lookup, perhaps copying the server list. This does not clone
813 * the query list, since it will be regenerated by the setup_lookup()
814 * function, nor does it queue up the new lookup for processing.
815 * Caution: If you don't clone the servers, you MUST clone the server
816 * list separately from somewhere else, or construct it by hand.
819 clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
820 dig_lookup_t *looknew;
822 debug("clone_lookup()");
826 looknew = make_empty_lookup();
827 INSIST(looknew != NULL);
828 strlcpy(looknew->textname, lookold->textname, MXNAME);
830 strlcpy(looknew->textnamesigchase, lookold->textnamesigchase, MXNAME);
832 strlcpy(looknew->cmdline, lookold->cmdline, MXNAME);
833 looknew->textname[MXNAME-1] = 0;
834 looknew->rdtype = lookold->rdtype;
835 looknew->qrdtype = lookold->qrdtype;
836 looknew->rdclass = lookold->rdclass;
837 looknew->rdtypeset = lookold->rdtypeset;
838 looknew->rdclassset = lookold->rdclassset;
839 looknew->doing_xfr = lookold->doing_xfr;
840 looknew->ixfr_serial = lookold->ixfr_serial;
841 looknew->trace = lookold->trace;
842 looknew->trace_root = lookold->trace_root;
843 looknew->identify = lookold->identify;
844 looknew->identify_previous_line = lookold->identify_previous_line;
845 looknew->ignore = lookold->ignore;
846 looknew->servfail_stops = lookold->servfail_stops;
847 looknew->besteffort = lookold->besteffort;
848 looknew->dnssec = lookold->dnssec;
849 looknew->nsid = lookold->nsid;
851 looknew->sigchase = lookold->sigchase;
853 looknew->do_topdown = lookold->do_topdown;
854 looknew->trace_root_sigchase = lookold->trace_root_sigchase;
855 looknew->rdtype_sigchaseset = lookold->rdtype_sigchaseset;
856 looknew->rdtype_sigchase = lookold->rdtype_sigchase;
857 looknew->qrdtype_sigchase = lookold->qrdtype_sigchase;
858 looknew->rdclass_sigchase = lookold->rdclass_sigchase;
859 looknew->rdclass_sigchaseset = lookold->rdclass_sigchaseset;
862 looknew->udpsize = lookold->udpsize;
863 looknew->edns = lookold->edns;
864 looknew->recurse = lookold->recurse;
865 looknew->aaonly = lookold->aaonly;
866 looknew->adflag = lookold->adflag;
867 looknew->cdflag = lookold->cdflag;
868 looknew->ns_search_only = lookold->ns_search_only;
869 looknew->tcp_mode = lookold->tcp_mode;
870 looknew->comments = lookold->comments;
871 looknew->stats = lookold->stats;
872 looknew->section_question = lookold->section_question;
873 looknew->section_answer = lookold->section_answer;
874 looknew->section_authority = lookold->section_authority;
875 looknew->section_additional = lookold->section_additional;
876 looknew->retries = lookold->retries;
877 looknew->tsigctx = NULL;
878 looknew->need_search = lookold->need_search;
879 looknew->done_as_is = lookold->done_as_is;
882 clone_server_list(lookold->my_server_list,
883 &looknew->my_server_list);
888 * Requeue a lookup for further processing, perhaps copying the server
889 * list. The new lookup structure is returned to the caller, and is
890 * queued for processing. If servers are not cloned in the requeue, they
891 * must be added before allowing the current event to complete, since the
892 * completion of the event may result in the next entry on the lookup
896 requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
897 dig_lookup_t *looknew;
899 debug("requeue_lookup()");
902 if (lookup_counter > LOOKUP_LIMIT)
903 fatal("too many lookups");
905 looknew = clone_lookup(lookold, servers);
906 INSIST(looknew != NULL);
908 debug("before insertion, init@%p -> %p, new@%p -> %p",
909 lookold, lookold->link.next, looknew, looknew->link.next);
910 ISC_LIST_PREPEND(lookup_list, looknew, link);
911 debug("after insertion, init -> %p, new = %p, new -> %p",
912 lookold, looknew, looknew->link.next);
918 setup_text_key(void) {
921 isc_buffer_t secretbuf;
923 unsigned char *secretstore;
925 debug("setup_text_key()");
926 result = isc_buffer_allocate(mctx, &namebuf, MXNAME);
927 check_result(result, "isc_buffer_allocate");
928 dns_name_init(&keyname, NULL);
929 check_result(result, "dns_name_init");
930 isc_buffer_putstr(namebuf, keynametext);
931 secretsize = strlen(keysecret) * 3 / 4;
932 secretstore = isc_mem_allocate(mctx, secretsize);
933 if (secretstore == NULL)
934 fatal("memory allocation failure in %s:%d",
936 isc_buffer_init(&secretbuf, secretstore, secretsize);
937 result = isc_base64_decodestring(keysecret, &secretbuf);
938 if (result != ISC_R_SUCCESS)
941 secretsize = isc_buffer_usedlength(&secretbuf);
943 if (hmacname == NULL) {
944 result = DST_R_UNSUPPORTEDALG;
948 result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf);
949 if (result != ISC_R_SUCCESS)
952 result = dns_tsigkey_create(&keyname, hmacname, secretstore,
953 secretsize, ISC_FALSE, NULL, 0, 0, mctx,
956 if (result != ISC_R_SUCCESS)
957 printf(";; Couldn't create key %s: %s\n",
958 keynametext, isc_result_totext(result));
960 dst_key_setbits(key->key, digestbits);
962 isc_mem_free(mctx, secretstore);
963 dns_name_invalidate(&keyname);
964 isc_buffer_free(&namebuf);
968 parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max,
971 isc_result_t result = isc_parse_uint32(&n, value, 10);
972 if (result == ISC_R_SUCCESS && n > max)
973 result = ISC_R_RANGE;
974 if (result != ISC_R_SUCCESS) {
975 printf("invalid %s '%s': %s\n", desc,
976 value, isc_result_totext(result));
980 return (ISC_R_SUCCESS);
984 parse_bits(char *arg, const char *desc, isc_uint32_t max) {
988 result = parse_uint(&tmp, arg, max, desc);
989 if (result != ISC_R_SUCCESS)
990 fatal("couldn't parse digest bits");
991 tmp = (tmp + 7) & ~0x7U;
997 * Parse HMAC algorithm specification
1000 parse_hmac(const char *hmac) {
1004 REQUIRE(hmac != NULL);
1007 if (len >= (int) sizeof(buf))
1008 fatal("unknown key type '%.*s'", len, hmac);
1009 strlcpy(buf, hmac, sizeof(buf));
1013 if (strcasecmp(buf, "hmac-md5") == 0) {
1014 hmacname = DNS_TSIG_HMACMD5_NAME;
1015 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
1016 hmacname = DNS_TSIG_HMACMD5_NAME;
1017 digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128);
1018 } else if (strcasecmp(buf, "hmac-sha1") == 0) {
1019 hmacname = DNS_TSIG_HMACSHA1_NAME;
1021 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
1022 hmacname = DNS_TSIG_HMACSHA1_NAME;
1023 digestbits = parse_bits(&buf[10], "digest-bits [0..160]", 160);
1024 } else if (strcasecmp(buf, "hmac-sha224") == 0) {
1025 hmacname = DNS_TSIG_HMACSHA224_NAME;
1026 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
1027 hmacname = DNS_TSIG_HMACSHA224_NAME;
1028 digestbits = parse_bits(&buf[12], "digest-bits [0..224]", 224);
1029 } else if (strcasecmp(buf, "hmac-sha256") == 0) {
1030 hmacname = DNS_TSIG_HMACSHA256_NAME;
1031 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
1032 hmacname = DNS_TSIG_HMACSHA256_NAME;
1033 digestbits = parse_bits(&buf[12], "digest-bits [0..256]", 256);
1034 } else if (strcasecmp(buf, "hmac-sha384") == 0) {
1035 hmacname = DNS_TSIG_HMACSHA384_NAME;
1036 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
1037 hmacname = DNS_TSIG_HMACSHA384_NAME;
1038 digestbits = parse_bits(&buf[12], "digest-bits [0..384]", 384);
1039 } else if (strcasecmp(buf, "hmac-sha512") == 0) {
1040 hmacname = DNS_TSIG_HMACSHA512_NAME;
1041 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
1042 hmacname = DNS_TSIG_HMACSHA512_NAME;
1043 digestbits = parse_bits(&buf[12], "digest-bits [0..512]", 512);
1045 fprintf(stderr, ";; Warning, ignoring "
1046 "invalid TSIG algorithm %s\n", buf);
1051 * Get a key from a named.conf format keyfile
1054 read_confkey(void) {
1055 isc_log_t *lctx = NULL;
1056 cfg_parser_t *pctx = NULL;
1057 cfg_obj_t *file = NULL;
1058 const cfg_obj_t *key = NULL;
1059 const cfg_obj_t *secretobj = NULL;
1060 const cfg_obj_t *algorithmobj = NULL;
1061 const char *keyname;
1062 const char *secretstr;
1063 const char *algorithm;
1064 isc_result_t result;
1066 if (! isc_file_exists(keyfile))
1067 return (ISC_R_FILENOTFOUND);
1069 result = cfg_parser_create(mctx, lctx, &pctx);
1070 if (result != ISC_R_SUCCESS)
1073 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
1075 if (result != ISC_R_SUCCESS)
1078 result = cfg_map_get(file, "key", &key);
1079 if (result != ISC_R_SUCCESS)
1082 (void) cfg_map_get(key, "secret", &secretobj);
1083 (void) cfg_map_get(key, "algorithm", &algorithmobj);
1084 if (secretobj == NULL || algorithmobj == NULL)
1085 fatal("key must have algorithm and secret");
1087 keyname = cfg_obj_asstring(cfg_map_getname(key));
1088 secretstr = cfg_obj_asstring(secretobj);
1089 algorithm = cfg_obj_asstring(algorithmobj);
1091 strlcpy(keynametext, keyname, sizeof(keynametext));
1092 strlcpy(keysecret, secretstr, sizeof(keysecret));
1093 parse_hmac(algorithm);
1099 cfg_obj_destroy(pctx, &file);
1100 cfg_parser_destroy(&pctx);
1107 setup_file_key(void) {
1108 isc_result_t result;
1109 dst_key_t *dstkey = NULL;
1111 debug("setup_file_key()");
1113 /* Try reading the key from a K* pair */
1114 result = dst_key_fromnamedfile(keyfile, NULL,
1115 DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
1118 /* If that didn't work, try reading it as a session.key keyfile */
1119 if (result != ISC_R_SUCCESS) {
1120 result = read_confkey();
1121 if (result == ISC_R_SUCCESS)
1125 if (result != ISC_R_SUCCESS) {
1126 fprintf(stderr, "Couldn't read key from %s: %s\n",
1127 keyfile, isc_result_totext(result));
1131 switch (dst_key_alg(dstkey)) {
1132 case DST_ALG_HMACMD5:
1133 hmacname = DNS_TSIG_HMACMD5_NAME;
1135 case DST_ALG_HMACSHA1:
1136 hmacname = DNS_TSIG_HMACSHA1_NAME;
1138 case DST_ALG_HMACSHA224:
1139 hmacname = DNS_TSIG_HMACSHA224_NAME;
1141 case DST_ALG_HMACSHA256:
1142 hmacname = DNS_TSIG_HMACSHA256_NAME;
1144 case DST_ALG_HMACSHA384:
1145 hmacname = DNS_TSIG_HMACSHA384_NAME;
1147 case DST_ALG_HMACSHA512:
1148 hmacname = DNS_TSIG_HMACSHA512_NAME;
1151 printf(";; Couldn't create key %s: bad algorithm\n",
1155 result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmacname,
1156 dstkey, ISC_FALSE, NULL, 0, 0,
1158 if (result != ISC_R_SUCCESS) {
1159 printf(";; Couldn't create key %s: %s\n",
1160 keynametext, isc_result_totext(result));
1165 dst_key_free(&dstkey);
1168 static dig_searchlist_t *
1169 make_searchlist_entry(char *domain) {
1170 dig_searchlist_t *search;
1171 search = isc_mem_allocate(mctx, sizeof(*search));
1173 fatal("memory allocation failure in %s:%d",
1174 __FILE__, __LINE__);
1175 strlcpy(search->origin, domain, MXNAME);
1176 search->origin[MXNAME-1] = 0;
1177 ISC_LINK_INIT(search, link);
1182 clear_searchlist(void) {
1183 dig_searchlist_t *search;
1184 while ((search = ISC_LIST_HEAD(search_list)) != NULL) {
1185 ISC_LIST_UNLINK(search_list, search, link);
1186 isc_mem_free(mctx, search);
1191 create_search_list(lwres_conf_t *confdata) {
1193 dig_searchlist_t *search;
1195 debug("create_search_list()");
1198 for (i = 0; i < confdata->searchnxt; i++) {
1199 search = make_searchlist_entry(confdata->search[i]);
1200 ISC_LIST_APPEND(search_list, search, link);
1205 * Setup the system as a whole, reading key information and resolv.conf
1209 setup_system(void) {
1210 dig_searchlist_t *domain = NULL;
1211 lwres_result_t lwresult;
1212 unsigned int lwresflags;
1214 debug("setup_system()");
1216 lwresflags = LWRES_CONTEXT_SERVERMODE;
1218 lwresflags |= LWRES_CONTEXT_USEIPV4;
1220 lwresflags |= LWRES_CONTEXT_USEIPV6;
1222 lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free,
1224 if (lwresult != LWRES_R_SUCCESS)
1225 fatal("lwres_context_create failed");
1227 lwresult = lwres_conf_parse(lwctx, RESOLV_CONF);
1228 if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND)
1229 fatal("parse of %s failed", RESOLV_CONF);
1231 lwconf = lwres_conf_get(lwctx);
1233 /* Make the search list */
1234 if (lwconf->searchnxt > 0)
1235 create_search_list(lwconf);
1236 else { /* No search list. Use the domain name if any */
1237 if (lwconf->domainname != NULL) {
1238 domain = make_searchlist_entry(lwconf->domainname);
1239 ISC_LIST_APPEND(search_list, domain, link);
1245 ndots = lwconf->ndots;
1246 debug("ndots is %d.", ndots);
1249 /* If user doesn't specify server use nameservers from resolv.conf. */
1250 if (ISC_LIST_EMPTY(server_list))
1251 copy_server_list(lwconf, &server_list);
1253 /* If we don't find a nameserver fall back to localhost */
1254 if (ISC_LIST_EMPTY(server_list)) {
1256 lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET);
1257 if (lwresult != ISC_R_SUCCESS)
1258 fatal("add_nameserver failed");
1261 lwresult = add_nameserver(lwconf, "::1", AF_INET6);
1262 if (lwresult != ISC_R_SUCCESS)
1263 fatal("add_nameserver failed");
1266 copy_server_list(lwconf, &server_list);
1273 if (keyfile[0] != 0)
1275 else if (keysecret[0] != 0)
1278 /* Setup the list of messages for +sigchase */
1279 ISC_LIST_INIT(chase_message_list);
1280 ISC_LIST_INIT(chase_message_list2);
1281 dns_name_init(&chase_name, NULL);
1283 dns_name_init(&chase_current_name, NULL);
1284 dns_name_init(&chase_authority_name, NULL);
1287 dns_name_init(&chase_signame, NULL);
1295 * Override the search list derived from resolv.conf by 'domain'.
1298 set_search_domain(char *domain) {
1299 dig_searchlist_t *search;
1302 search = make_searchlist_entry(domain);
1303 ISC_LIST_APPEND(search_list, search, link);
1307 * Setup the ISC and DNS libraries for use by the system.
1311 isc_result_t result;
1312 isc_logconfig_t *logconfig = NULL;
1314 debug("setup_libs()");
1316 result = isc_net_probeipv4();
1317 if (result == ISC_R_SUCCESS)
1318 have_ipv4 = ISC_TRUE;
1320 result = isc_net_probeipv6();
1321 if (result == ISC_R_SUCCESS)
1322 have_ipv6 = ISC_TRUE;
1323 if (!have_ipv6 && !have_ipv4)
1324 fatal("can't find either v4 or v6 networking");
1326 result = isc_mem_create(0, 0, &mctx);
1327 check_result(result, "isc_mem_create");
1328 isc_mem_setname(mctx, "dig", NULL);
1330 result = isc_log_create(mctx, &lctx, &logconfig);
1331 check_result(result, "isc_log_create");
1333 isc_log_setcontext(lctx);
1335 dns_log_setcontext(lctx);
1337 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
1338 check_result(result, "isc_log_usechannel");
1340 isc_log_setdebuglevel(lctx, 0);
1342 result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
1343 check_result(result, "isc_taskmgr_create");
1345 result = isc_task_create(taskmgr, 0, &global_task);
1346 check_result(result, "isc_task_create");
1347 isc_task_setname(global_task, "dig", NULL);
1349 result = isc_timermgr_create(mctx, &timermgr);
1350 check_result(result, "isc_timermgr_create");
1352 result = isc_socketmgr_create(mctx, &socketmgr);
1353 check_result(result, "isc_socketmgr_create");
1355 result = isc_entropy_create(mctx, &entp);
1356 check_result(result, "isc_entropy_create");
1358 result = dst_lib_init(mctx, entp, 0);
1359 check_result(result, "dst_lib_init");
1360 is_dst_up = ISC_TRUE;
1362 result = isc_mempool_create(mctx, COMMSIZE, &commctx);
1363 check_result(result, "isc_mempool_create");
1364 isc_mempool_setname(commctx, "COMMPOOL");
1366 * 6 and 2 set as reasonable parameters for 3 or 4 nameserver
1369 isc_mempool_setfreemax(commctx, 6);
1370 isc_mempool_setfillcount(commctx, 2);
1372 result = isc_mutex_init(&lookup_lock);
1373 check_result(result, "isc_mutex_init");
1375 dns_result_register();
1379 * Add EDNS0 option record to a message. Currently, the only supported
1380 * options are UDP buffer size, the DO bit, and NSID request.
1383 add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns,
1384 isc_boolean_t dnssec, isc_boolean_t nsid)
1386 dns_rdataset_t *rdataset = NULL;
1387 dns_rdatalist_t *rdatalist = NULL;
1388 dns_rdata_t *rdata = NULL;
1389 isc_result_t result;
1392 result = dns_message_gettemprdataset(msg, &rdataset);
1393 check_result(result, "dns_message_gettemprdataset");
1394 dns_rdataset_init(rdataset);
1395 result = dns_message_gettemprdatalist(msg, &rdatalist);
1396 check_result(result, "dns_message_gettemprdatalist");
1397 result = dns_message_gettemprdata(msg, &rdata);
1398 check_result(result, "dns_message_gettemprdata");
1400 debug("setting udp size of %d", udpsize);
1401 rdatalist->type = dns_rdatatype_opt;
1402 rdatalist->covers = 0;
1403 rdatalist->rdclass = udpsize;
1404 rdatalist->ttl = edns << 16;
1406 rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
1408 isc_buffer_t *b = NULL;
1410 result = isc_buffer_allocate(mctx, &b, 4);
1411 check_result(result, "isc_buffer_allocate");
1412 isc_buffer_putuint16(b, DNS_OPT_NSID);
1413 isc_buffer_putuint16(b, 0);
1414 rdata->data = isc_buffer_base(b);
1415 rdata->length = isc_buffer_usedlength(b);
1416 dns_message_takebuffer(msg, &b);
1421 ISC_LIST_INIT(rdatalist->rdata);
1422 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1423 dns_rdatalist_tordataset(rdatalist, rdataset);
1424 result = dns_message_setopt(msg, rdataset);
1425 check_result(result, "dns_message_setopt");
1429 * Add a question section to a message, asking for the specified name,
1433 add_question(dns_message_t *message, dns_name_t *name,
1434 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype)
1436 dns_rdataset_t *rdataset;
1437 isc_result_t result;
1439 debug("add_question()");
1441 result = dns_message_gettemprdataset(message, &rdataset);
1442 check_result(result, "dns_message_gettemprdataset()");
1443 dns_rdataset_init(rdataset);
1444 dns_rdataset_makequestion(rdataset, rdclass, rdtype);
1445 ISC_LIST_APPEND(name->list, rdataset, link);
1449 * Check if we're done with all the queued lookups, which is true iff
1450 * all sockets, sends, and recvs are accounted for (counters == 0),
1451 * and the lookup list is empty.
1452 * If we are done, pass control back out to dighost_shutdown() (which is
1453 * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
1454 * a whole or reseed the lookup list.
1457 check_if_done(void) {
1458 debug("check_if_done()");
1459 debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
1460 if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
1462 INSIST(sockcount == 0);
1463 INSIST(recvcount == 0);
1464 debug("shutting down");
1470 * Clear out a query when we're done with it. WARNING: This routine
1471 * WILL invalidate the query pointer.
1474 clear_query(dig_query_t *query) {
1475 dig_lookup_t *lookup;
1477 REQUIRE(query != NULL);
1479 debug("clear_query(%p)", query);
1481 lookup = query->lookup;
1483 if (lookup->current_query == query)
1484 lookup->current_query = NULL;
1486 if (ISC_LINK_LINKED(query, link))
1487 ISC_LIST_UNLINK(lookup->q, query, link);
1488 if (ISC_LINK_LINKED(query, clink))
1489 ISC_LIST_UNLINK(lookup->connecting, query, clink);
1490 if (ISC_LINK_LINKED(&query->recvbuf, link))
1491 ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf,
1493 if (ISC_LINK_LINKED(&query->lengthbuf, link))
1494 ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf,
1496 INSIST(query->recvspace != NULL);
1498 if (query->sock != NULL) {
1499 isc_socket_detach(&query->sock);
1501 debug("sockcount=%d", sockcount);
1503 isc_mempool_put(commctx, query->recvspace);
1504 isc_buffer_invalidate(&query->recvbuf);
1505 isc_buffer_invalidate(&query->lengthbuf);
1506 if (query->waiting_senddone)
1507 query->pending_free = ISC_TRUE;
1509 isc_mem_free(mctx, query);
1513 * Try and clear out a lookup if we're done with it. Return ISC_TRUE if
1514 * the lookup was successfully cleared. If ISC_TRUE is returned, the
1515 * lookup pointer has been invalidated.
1517 static isc_boolean_t
1518 try_clear_lookup(dig_lookup_t *lookup) {
1521 REQUIRE(lookup != NULL);
1523 debug("try_clear_lookup(%p)", lookup);
1525 if (ISC_LIST_HEAD(lookup->q) != NULL ||
1526 ISC_LIST_HEAD(lookup->connecting) != NULL)
1529 q = ISC_LIST_HEAD(lookup->q);
1531 debug("query to %s still pending", q->servname);
1532 q = ISC_LIST_NEXT(q, link);
1535 q = ISC_LIST_HEAD(lookup->connecting);
1537 debug("query to %s still connecting",
1539 q = ISC_LIST_NEXT(q, clink);
1546 * At this point, we know there are no queries on the lookup,
1547 * so can make it go away also.
1549 destroy_lookup(lookup);
1554 destroy_lookup(dig_lookup_t *lookup) {
1559 s = ISC_LIST_HEAD(lookup->my_server_list);
1561 debug("freeing server %p belonging to %p", s, lookup);
1563 s = ISC_LIST_NEXT(s, link);
1564 ISC_LIST_DEQUEUE(lookup->my_server_list,
1565 (dig_server_t *)ptr, link);
1566 isc_mem_free(mctx, ptr);
1568 if (lookup->sendmsg != NULL)
1569 dns_message_destroy(&lookup->sendmsg);
1570 if (lookup->querysig != NULL) {
1571 debug("freeing buffer %p", lookup->querysig);
1572 isc_buffer_free(&lookup->querysig);
1574 if (lookup->timer != NULL)
1575 isc_timer_detach(&lookup->timer);
1576 if (lookup->sendspace != NULL)
1577 isc_mempool_put(commctx, lookup->sendspace);
1579 if (lookup->tsigctx != NULL)
1580 dst_context_destroy(&lookup->tsigctx);
1582 isc_mem_free(mctx, lookup);
1586 * If we can, start the next lookup in the queue running.
1587 * This assumes that the lookup on the head of the queue hasn't been
1588 * started yet. It also removes the lookup from the head of the queue,
1589 * setting the current_lookup pointer pointing to it.
1592 start_lookup(void) {
1593 debug("start_lookup()");
1598 * If there's a current lookup running, we really shouldn't get
1601 INSIST(current_lookup == NULL);
1603 current_lookup = ISC_LIST_HEAD(lookup_list);
1605 * Put the current lookup somewhere so cancel_all can find it
1607 if (current_lookup != NULL) {
1608 ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
1610 if (current_lookup->do_topdown &&
1611 !current_lookup->rdtype_sigchaseset) {
1612 dst_key_t *trustedkey = NULL;
1613 isc_buffer_t *b = NULL;
1615 isc_result_t result;
1616 dns_name_t query_name;
1617 dns_name_t *key_name;
1620 result = get_trusted_key(mctx);
1621 if (result != ISC_R_SUCCESS) {
1622 printf("\n;; No trusted key, "
1623 "+sigchase option is disabled\n");
1624 current_lookup->sigchase = ISC_FALSE;
1627 dns_name_init(&query_name, NULL);
1628 nameFromString(current_lookup->textname, &query_name);
1630 for (i = 0; i < tk_list.nb_tk; i++) {
1631 key_name = dst_key_name(tk_list.key[i]);
1633 if (dns_name_issubdomain(&query_name,
1634 key_name) == ISC_TRUE)
1635 trustedkey = tk_list.key[i];
1637 * Verify temp is really the lowest
1641 if (trustedkey == NULL) {
1642 printf("\n;; The queried zone: ");
1643 dns_name_print(&query_name, stdout);
1644 printf(" isn't a subdomain of any Trusted Keys"
1645 ": +sigchase option is disable\n");
1646 current_lookup->sigchase = ISC_FALSE;
1647 free_name(&query_name, mctx);
1650 free_name(&query_name, mctx);
1652 current_lookup->rdtype_sigchase
1653 = current_lookup->rdtype;
1654 current_lookup->rdtype_sigchaseset
1655 = current_lookup->rdtypeset;
1656 current_lookup->rdtype = dns_rdatatype_ns;
1658 current_lookup->qrdtype_sigchase
1659 = current_lookup->qrdtype;
1660 current_lookup->qrdtype = dns_rdatatype_ns;
1662 current_lookup->rdclass_sigchase
1663 = current_lookup->rdclass;
1664 current_lookup->rdclass_sigchaseset
1665 = current_lookup->rdclassset;
1666 current_lookup->rdclass = dns_rdataclass_in;
1668 strlcpy(current_lookup->textnamesigchase,
1669 current_lookup->textname, MXNAME);
1671 current_lookup->trace_root_sigchase = ISC_TRUE;
1673 result = isc_buffer_allocate(mctx, &b, BUFSIZE);
1674 check_result(result, "isc_buffer_allocate");
1675 result = dns_name_totext(dst_key_name(trustedkey),
1677 check_result(result, "dns_name_totext");
1678 isc_buffer_usedregion(b, &r);
1679 r.base[r.length] = '\0';
1680 strlcpy(current_lookup->textname, (char*)r.base,
1682 isc_buffer_free(&b);
1684 nameFromString(current_lookup->textnamesigchase,
1687 dns_name_init(&chase_authority_name, NULL);
1691 setup_lookup(current_lookup);
1692 do_lookup(current_lookup);
1699 * If we can, clear the current lookup and start the next one running.
1700 * This calls try_clear_lookup, so may invalidate the lookup pointer.
1703 check_next_lookup(dig_lookup_t *lookup) {
1707 debug("check_next_lookup(%p)", lookup);
1709 if (ISC_LIST_HEAD(lookup->q) != NULL) {
1710 debug("still have a worker");
1713 if (try_clear_lookup(lookup)) {
1714 current_lookup = NULL;
1720 * Create and queue a new lookup as a followup to the current lookup,
1721 * based on the supplied message and section. This is used in trace and
1722 * name server search modes to start a new lookup using servers from
1723 * NS records in a reply. Returns the number of followup lookups made.
1726 followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section)
1728 dig_lookup_t *lookup = NULL;
1729 dig_server_t *srv = NULL;
1730 dns_rdataset_t *rdataset = NULL;
1731 dns_rdata_t rdata = DNS_RDATA_INIT;
1732 dns_name_t *name = NULL;
1733 isc_result_t result;
1734 isc_boolean_t success = ISC_FALSE;
1737 isc_result_t lresult, addresses_result;
1738 char bad_namestr[DNS_NAME_FORMATSIZE];
1740 isc_boolean_t horizontal = ISC_FALSE, bad = ISC_FALSE;
1744 debug("following up %s", query->lookup->textname);
1746 addresses_result = ISC_R_SUCCESS;
1747 bad_namestr[0] = '\0';
1748 for (result = dns_message_firstname(msg, section);
1749 result == ISC_R_SUCCESS;
1750 result = dns_message_nextname(msg, section)) {
1752 dns_message_currentname(msg, section, &name);
1754 if (section == DNS_SECTION_AUTHORITY) {
1756 result = dns_message_findtype(name, dns_rdatatype_soa,
1758 if (result == ISC_R_SUCCESS)
1762 result = dns_message_findtype(name, dns_rdatatype_ns, 0,
1764 if (result != ISC_R_SUCCESS)
1767 debug("found NS set");
1769 if (query->lookup->trace && !query->lookup->trace_root) {
1770 dns_namereln_t namereln;
1771 unsigned int nlabels;
1774 domain = dns_fixedname_name(&query->lookup->fdomain);
1775 namereln = dns_name_fullcompare(name, domain,
1777 if (namereln == dns_namereln_equal) {
1779 printf(";; BAD (HORIZONTAL) REFERRAL\n");
1780 horizontal = ISC_TRUE;
1781 } else if (namereln != dns_namereln_subdomain) {
1783 printf(";; BAD REFERRAL\n");
1789 for (result = dns_rdataset_first(rdataset);
1790 result == ISC_R_SUCCESS;
1791 result = dns_rdataset_next(rdataset)) {
1792 char namestr[DNS_NAME_FORMATSIZE];
1795 if (query->lookup->trace_root &&
1796 query->lookup->nsfound >= MXSERV)
1799 dns_rdataset_current(rdataset, &rdata);
1801 query->lookup->nsfound++;
1802 result = dns_rdata_tostruct(&rdata, &ns, NULL);
1803 check_result(result, "dns_rdata_tostruct");
1804 dns_name_format(&ns.name, namestr, sizeof(namestr));
1805 dns_rdata_freestruct(&ns);
1807 /* Initialize lookup if we've not yet */
1808 debug("found NS %s", namestr);
1812 lookup = requeue_lookup(query->lookup,
1814 cancel_lookup(query->lookup);
1815 lookup->doing_xfr = ISC_FALSE;
1816 if (!lookup->trace_root &&
1817 section == DNS_SECTION_ANSWER)
1818 lookup->trace = ISC_FALSE;
1820 lookup->trace = query->lookup->trace;
1821 lookup->ns_search_only =
1822 query->lookup->ns_search_only;
1823 lookup->trace_root = ISC_FALSE;
1824 if (lookup->ns_search_only)
1825 lookup->recurse = ISC_FALSE;
1826 dns_fixedname_init(&lookup->fdomain);
1827 domain = dns_fixedname_name(&lookup->fdomain);
1828 dns_name_copy(name, domain, NULL);
1830 debug("adding server %s", namestr);
1831 num = getaddresses(lookup, namestr, &lresult);
1832 if (lresult != ISC_R_SUCCESS) {
1833 debug("couldn't get address for '%s': %s",
1834 namestr, isc_result_totext(lresult));
1835 if (addresses_result == ISC_R_SUCCESS) {
1836 addresses_result = lresult;
1837 strcpy(bad_namestr, namestr);
1841 dns_rdata_reset(&rdata);
1844 if (numLookups == 0 && addresses_result != ISC_R_SUCCESS) {
1845 fatal("couldn't get address for '%s': %s",
1846 bad_namestr, isc_result_totext(result));
1849 if (lookup == NULL &&
1850 section == DNS_SECTION_ANSWER &&
1851 (query->lookup->trace || query->lookup->ns_search_only))
1852 return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY));
1855 * Randomize the order the nameserver will be tried.
1857 if (numLookups > 1) {
1859 dig_serverlist_t my_server_list;
1862 ISC_LIST_INIT(my_server_list);
1865 for (srv = ISC_LIST_HEAD(lookup->my_server_list);
1867 srv = ISC_LIST_HEAD(lookup->my_server_list)) {
1871 next = ISC_LIST_NEXT(srv, link);
1872 while (j-- > 0 && next != NULL) {
1874 next = ISC_LIST_NEXT(srv, link);
1876 ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link);
1877 ISC_LIST_APPEND(my_server_list, srv, link);
1880 ISC_LIST_APPENDLIST(lookup->my_server_list,
1881 my_server_list, link);
1884 return (numLookups);
1888 * Create and queue a new lookup using the next origin from the search
1889 * list, read in setup_system().
1891 * Return ISC_TRUE iff there was another searchlist entry.
1893 static isc_boolean_t
1894 next_origin(dig_query_t *query) {
1895 dig_lookup_t *lookup;
1896 dig_searchlist_t *search;
1897 dns_fixedname_t fixed;
1899 isc_result_t result;
1903 debug("next_origin()");
1904 debug("following up %s", query->lookup->textname);
1908 * We're not using a search list, so don't even think
1909 * about finding the next entry.
1914 * Check for a absolute name or ndots being met.
1916 dns_fixedname_init(&fixed);
1917 name = dns_fixedname_name(&fixed);
1918 result = dns_name_fromstring2(name, query->lookup->textname, NULL,
1920 if (result == ISC_R_SUCCESS &&
1921 (dns_name_isabsolute(name) ||
1922 (int)dns_name_countlabels(name) > ndots))
1925 if (query->lookup->origin == NULL && !query->lookup->need_search)
1927 * Then we just did rootorg; there's nothing left.
1930 if (query->lookup->origin == NULL && query->lookup->need_search) {
1931 lookup = requeue_lookup(query->lookup, ISC_TRUE);
1932 lookup->origin = ISC_LIST_HEAD(search_list);
1933 lookup->need_search = ISC_FALSE;
1935 search = ISC_LIST_NEXT(query->lookup->origin, link);
1936 if (search == NULL && query->lookup->done_as_is)
1938 lookup = requeue_lookup(query->lookup, ISC_TRUE);
1939 lookup->origin = search;
1941 cancel_lookup(query->lookup);
1946 * Insert an SOA record into the sendmessage in a lookup. Used for
1947 * creating IXFR queries.
1950 insert_soa(dig_lookup_t *lookup) {
1951 isc_result_t result;
1952 dns_rdata_soa_t soa;
1953 dns_rdata_t *rdata = NULL;
1954 dns_rdatalist_t *rdatalist = NULL;
1955 dns_rdataset_t *rdataset = NULL;
1956 dns_name_t *soaname = NULL;
1958 debug("insert_soa()");
1960 soa.serial = lookup->ixfr_serial;
1965 soa.common.rdclass = lookup->rdclass;
1966 soa.common.rdtype = dns_rdatatype_soa;
1968 dns_name_init(&soa.origin, NULL);
1969 dns_name_init(&soa.contact, NULL);
1971 dns_name_clone(dns_rootname, &soa.origin);
1972 dns_name_clone(dns_rootname, &soa.contact);
1974 isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
1975 sizeof(lookup->rdatastore));
1977 result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
1978 check_result(result, "dns_message_gettemprdata");
1980 result = dns_rdata_fromstruct(rdata, lookup->rdclass,
1981 dns_rdatatype_soa, &soa,
1983 check_result(result, "isc_rdata_fromstruct");
1985 result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
1986 check_result(result, "dns_message_gettemprdatalist");
1988 result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
1989 check_result(result, "dns_message_gettemprdataset");
1991 dns_rdatalist_init(rdatalist);
1992 rdatalist->type = dns_rdatatype_soa;
1993 rdatalist->rdclass = lookup->rdclass;
1994 rdatalist->covers = 0;
1996 ISC_LIST_INIT(rdatalist->rdata);
1997 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1999 dns_rdataset_init(rdataset);
2000 dns_rdatalist_tordataset(rdatalist, rdataset);
2002 result = dns_message_gettempname(lookup->sendmsg, &soaname);
2003 check_result(result, "dns_message_gettempname");
2004 dns_name_init(soaname, NULL);
2005 dns_name_clone(lookup->name, soaname);
2006 ISC_LIST_INIT(soaname->list);
2007 ISC_LIST_APPEND(soaname->list, rdataset, link);
2008 dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
2012 * Setup the supplied lookup structure, making it ready to start sending
2013 * queries to servers. Create and initialize the message to be sent as
2014 * well as the query structures and buffer space for the replies. If the
2015 * server list is empty, clone it from the system default list.
2018 setup_lookup(dig_lookup_t *lookup) {
2019 isc_result_t result;
2025 dns_compress_t cctx;
2029 char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME];
2033 result = dns_name_settotextfilter(output_filter);
2034 check_result(result, "dns_name_settotextfilter");
2037 REQUIRE(lookup != NULL);
2040 debug("setup_lookup(%p)", lookup);
2042 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
2044 check_result(result, "dns_message_create");
2046 if (lookup->new_search) {
2047 debug("resetting lookup counter.");
2051 if (ISC_LIST_EMPTY(lookup->my_server_list)) {
2052 debug("cloning server list");
2053 clone_server_list(server_list, &lookup->my_server_list);
2055 result = dns_message_gettempname(lookup->sendmsg, &lookup->name);
2056 check_result(result, "dns_message_gettempname");
2057 dns_name_init(lookup->name, NULL);
2059 isc_buffer_init(&lookup->namebuf, lookup->namespace,
2060 sizeof(lookup->namespace));
2061 isc_buffer_init(&lookup->onamebuf, lookup->onamespace,
2062 sizeof(lookup->onamespace));
2066 * We cannot convert `textname' and `origin' separately.
2067 * `textname' doesn't contain TLD, but local mapping needs
2070 mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname,
2071 utf8_textname, sizeof(utf8_textname));
2072 idn_check_result(mr, "convert textname to UTF-8");
2076 * If the name has too many dots, force the origin to be NULL
2077 * (which produces an absolute lookup). Otherwise, take the origin
2078 * we have if there's one in the struct already. If it's NULL,
2079 * take the first entry in the searchlist iff either usesearch
2080 * is TRUE or we got a domain line in the resolv.conf file.
2082 if (lookup->new_search) {
2084 if ((count_dots(utf8_textname) >= ndots) || !usesearch) {
2085 lookup->origin = NULL; /* Force abs lookup */
2086 lookup->done_as_is = ISC_TRUE;
2087 lookup->need_search = usesearch;
2088 } else if (lookup->origin == NULL && usesearch) {
2089 lookup->origin = ISC_LIST_HEAD(search_list);
2090 lookup->need_search = ISC_FALSE;
2093 if ((count_dots(lookup->textname) >= ndots) || !usesearch) {
2094 lookup->origin = NULL; /* Force abs lookup */
2095 lookup->done_as_is = ISC_TRUE;
2096 lookup->need_search = usesearch;
2097 } else if (lookup->origin == NULL && usesearch) {
2098 lookup->origin = ISC_LIST_HEAD(search_list);
2099 lookup->need_search = ISC_FALSE;
2105 if (lookup->origin != NULL) {
2106 mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP,
2107 lookup->origin->origin, utf8_origin,
2108 sizeof(utf8_origin));
2109 idn_check_result(mr, "convert origin to UTF-8");
2110 mr = append_textname(utf8_textname, utf8_origin,
2111 sizeof(utf8_textname));
2112 idn_check_result(mr, "append origin to textname");
2114 mr = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP |
2115 IDN_IDNCONV | IDN_LENCHECK, utf8_textname,
2116 idn_textname, sizeof(idn_textname));
2117 idn_check_result(mr, "convert UTF-8 textname to IDN encoding");
2119 if (lookup->origin != NULL) {
2120 debug("trying origin %s", lookup->origin->origin);
2121 result = dns_message_gettempname(lookup->sendmsg,
2123 check_result(result, "dns_message_gettempname");
2124 dns_name_init(lookup->oname, NULL);
2125 /* XXX Helper funct to conv char* to name? */
2126 len = strlen(lookup->origin->origin);
2127 isc_buffer_init(&b, lookup->origin->origin, len);
2128 isc_buffer_add(&b, len);
2129 result = dns_name_fromtext(lookup->oname, &b, dns_rootname,
2130 0, &lookup->onamebuf);
2131 if (result != ISC_R_SUCCESS) {
2132 dns_message_puttempname(lookup->sendmsg,
2134 dns_message_puttempname(lookup->sendmsg,
2136 fatal("'%s' is not in legal name syntax (%s)",
2137 lookup->origin->origin,
2138 isc_result_totext(result));
2140 if (lookup->trace && lookup->trace_root) {
2141 dns_name_clone(dns_rootname, lookup->name);
2143 len = strlen(lookup->textname);
2144 isc_buffer_init(&b, lookup->textname, len);
2145 isc_buffer_add(&b, len);
2146 result = dns_name_fromtext(lookup->name, &b,
2150 if (result != ISC_R_SUCCESS) {
2151 dns_message_puttempname(lookup->sendmsg,
2153 dns_message_puttempname(lookup->sendmsg,
2155 fatal("'%s' is not in legal name syntax (%s)",
2156 lookup->textname, isc_result_totext(result));
2158 dns_message_puttempname(lookup->sendmsg, &lookup->oname);
2162 debug("using root origin");
2163 if (lookup->trace && lookup->trace_root)
2164 dns_name_clone(dns_rootname, lookup->name);
2167 len = strlen(idn_textname);
2168 isc_buffer_init(&b, idn_textname, len);
2169 isc_buffer_add(&b, len);
2170 result = dns_name_fromtext(lookup->name, &b,
2174 len = strlen(lookup->textname);
2175 isc_buffer_init(&b, lookup->textname, len);
2176 isc_buffer_add(&b, len);
2177 result = dns_name_fromtext(lookup->name, &b,
2182 if (result != ISC_R_SUCCESS) {
2183 dns_message_puttempname(lookup->sendmsg,
2185 isc_buffer_init(&b, store, MXNAME);
2186 fatal("'%s' is not a legal name "
2187 "(%s)", lookup->textname,
2188 isc_result_totext(result));
2191 dns_name_format(lookup->name, store, sizeof(store));
2192 trying(store, lookup);
2193 INSIST(dns_name_isabsolute(lookup->name));
2195 isc_random_get(&id);
2196 lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
2197 lookup->sendmsg->opcode = dns_opcode_query;
2198 lookup->msgcounter = 0;
2200 * If this is a trace request, completely disallow recursion, since
2201 * it's meaningless for traces.
2203 if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root))
2204 lookup->recurse = ISC_FALSE;
2206 if (lookup->recurse &&
2207 lookup->rdtype != dns_rdatatype_axfr &&
2208 lookup->rdtype != dns_rdatatype_ixfr) {
2209 debug("recursive query");
2210 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD;
2214 if (lookup->aaonly) {
2216 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA;
2219 if (lookup->adflag) {
2221 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD;
2224 if (lookup->cdflag) {
2226 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD;
2229 dns_message_addname(lookup->sendmsg, lookup->name,
2230 DNS_SECTION_QUESTION);
2232 if (lookup->trace && lookup->trace_root) {
2233 lookup->qrdtype = lookup->rdtype;
2234 lookup->rdtype = dns_rdatatype_ns;
2237 if ((lookup->rdtype == dns_rdatatype_axfr) ||
2238 (lookup->rdtype == dns_rdatatype_ixfr)) {
2240 * Force TCP mode if we're doing an axfr.
2242 if (lookup->rdtype == dns_rdatatype_axfr) {
2243 lookup->doing_xfr = ISC_TRUE;
2244 lookup->tcp_mode = ISC_TRUE;
2245 } else if (lookup->tcp_mode) {
2246 lookup->doing_xfr = ISC_TRUE;
2250 add_question(lookup->sendmsg, lookup->name, lookup->rdclass,
2254 if (lookup->rdtype == dns_rdatatype_ixfr)
2257 /* XXX Insist this? */
2258 lookup->tsigctx = NULL;
2259 lookup->querysig = NULL;
2261 debug("initializing keys");
2262 result = dns_message_settsigkey(lookup->sendmsg, key);
2263 check_result(result, "dns_message_settsigkey");
2266 lookup->sendspace = isc_mempool_get(commctx);
2267 if (lookup->sendspace == NULL)
2268 fatal("memory allocation failure");
2270 result = dns_compress_init(&cctx, -1, mctx);
2271 check_result(result, "dns_compress_init");
2273 debug("starting to render the message");
2274 isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE);
2275 result = dns_message_renderbegin(lookup->sendmsg, &cctx,
2276 &lookup->renderbuf);
2277 check_result(result, "dns_message_renderbegin");
2278 if (lookup->udpsize > 0 || lookup->dnssec || lookup->edns > -1) {
2279 if (lookup->udpsize == 0)
2280 lookup->udpsize = 4096;
2281 if (lookup->edns < 0)
2283 add_opt(lookup->sendmsg, lookup->udpsize,
2284 lookup->edns, lookup->dnssec, lookup->nsid);
2287 result = dns_message_rendersection(lookup->sendmsg,
2288 DNS_SECTION_QUESTION, 0);
2289 check_result(result, "dns_message_rendersection");
2290 result = dns_message_rendersection(lookup->sendmsg,
2291 DNS_SECTION_AUTHORITY, 0);
2292 check_result(result, "dns_message_rendersection");
2293 result = dns_message_renderend(lookup->sendmsg);
2294 check_result(result, "dns_message_renderend");
2295 debug("done rendering");
2297 dns_compress_invalidate(&cctx);
2300 * Force TCP mode if the request is larger than 512 bytes.
2302 if (isc_buffer_usedlength(&lookup->renderbuf) > 512)
2303 lookup->tcp_mode = ISC_TRUE;
2305 lookup->pending = ISC_FALSE;
2307 for (serv = ISC_LIST_HEAD(lookup->my_server_list);
2309 serv = ISC_LIST_NEXT(serv, link)) {
2310 query = isc_mem_allocate(mctx, sizeof(dig_query_t));
2312 fatal("memory allocation failure in %s:%d",
2313 __FILE__, __LINE__);
2314 debug("create query %p linked to lookup %p",
2316 query->lookup = lookup;
2317 query->waiting_connect = ISC_FALSE;
2318 query->waiting_senddone = ISC_FALSE;
2319 query->pending_free = ISC_FALSE;
2320 query->recv_made = ISC_FALSE;
2321 query->first_pass = ISC_TRUE;
2322 query->first_soa_rcvd = ISC_FALSE;
2323 query->second_rr_rcvd = ISC_FALSE;
2324 query->first_repeat_rcvd = ISC_FALSE;
2325 query->warn_id = ISC_TRUE;
2326 query->first_rr_serial = 0;
2327 query->second_rr_serial = 0;
2328 query->servname = serv->servername;
2329 query->userarg = serv->userarg;
2330 query->rr_count = 0;
2331 query->msg_count = 0;
2332 query->byte_count = 0;
2333 query->ixfr_axfr = ISC_FALSE;
2334 ISC_LIST_INIT(query->recvlist);
2335 ISC_LIST_INIT(query->lengthlist);
2337 query->recvspace = isc_mempool_get(commctx);
2338 if (query->recvspace == NULL)
2339 fatal("memory allocation failure");
2341 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
2342 isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
2343 isc_buffer_init(&query->slbuf, query->slspace, 2);
2344 query->sendbuf = lookup->renderbuf;
2346 ISC_LINK_INIT(query, clink);
2347 ISC_LINK_INIT(query, link);
2348 ISC_LIST_ENQUEUE(lookup->q, query, link);
2350 /* XXX qrflag, print_query, etc... */
2351 if (!ISC_LIST_EMPTY(lookup->q) && qr) {
2353 printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg,
2359 * Event handler for send completion. Track send counter, and clear out
2360 * the query if the send was canceled.
2363 send_done(isc_task_t *_task, isc_event_t *event) {
2364 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
2365 isc_buffer_t *b = NULL;
2366 dig_query_t *query, *next;
2369 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
2375 debug("send_done()");
2377 debug("sendcount=%d", sendcount);
2378 INSIST(sendcount >= 0);
2380 for (b = ISC_LIST_HEAD(sevent->bufferlist);
2382 b = ISC_LIST_HEAD(sevent->bufferlist)) {
2383 ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2384 isc_mem_free(mctx, b);
2387 query = event->ev_arg;
2388 query->waiting_senddone = ISC_FALSE;
2391 if (l->ns_search_only && !l->trace_root && !l->tcp_mode) {
2392 debug("sending next, since searching");
2393 next = ISC_LIST_NEXT(query, link);
2398 isc_event_free(&event);
2400 if (query->pending_free)
2401 isc_mem_free(mctx, query);
2408 * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
2409 * IO sockets. The cancel handlers should take care of cleaning up the
2410 * query and lookup structures
2413 cancel_lookup(dig_lookup_t *lookup) {
2414 dig_query_t *query, *next;
2416 debug("cancel_lookup()");
2417 query = ISC_LIST_HEAD(lookup->q);
2418 while (query != NULL) {
2419 next = ISC_LIST_NEXT(query, link);
2420 if (query->sock != NULL) {
2421 isc_socket_cancel(query->sock, global_task,
2422 ISC_SOCKCANCEL_ALL);
2429 if (lookup->timer != NULL)
2430 isc_timer_detach(&lookup->timer);
2431 lookup->pending = ISC_FALSE;
2432 lookup->retries = 0;
2436 bringup_timer(dig_query_t *query, unsigned int default_timeout) {
2438 unsigned int local_timeout;
2439 isc_result_t result;
2441 debug("bringup_timer()");
2443 * If the timer already exists, that means we're calling this
2444 * a second time (for a retry). Don't need to recreate it,
2448 if (ISC_LIST_NEXT(query, link) != NULL)
2449 local_timeout = SERVER_TIMEOUT;
2452 local_timeout = default_timeout;
2454 local_timeout = timeout;
2456 debug("have local timeout of %d", local_timeout);
2457 isc_interval_set(&l->interval, local_timeout, 0);
2458 if (l->timer != NULL)
2459 isc_timer_detach(&l->timer);
2460 result = isc_timer_create(timermgr, isc_timertype_once, NULL,
2461 &l->interval, global_task, connect_timeout,
2463 check_result(result, "isc_timer_create");
2467 force_timeout(dig_lookup_t *l, dig_query_t *query) {
2470 debug("force_timeout ()");
2471 event = isc_event_allocate(mctx, query, ISC_TIMEREVENT_IDLE,
2473 sizeof(isc_event_t));
2474 if (event == NULL) {
2475 fatal("isc_event_allocate: %s",
2476 isc_result_totext(ISC_R_NOMEMORY));
2478 isc_task_send(global_task, &event);
2481 * The timer may have expired if, for example, get_address() takes
2482 * long time and the timer was running on a different thread.
2483 * We need to cancel the possible timeout event not to confuse
2484 * ourselves due to the duplicate events.
2486 if (l->timer != NULL)
2487 isc_timer_detach(&l->timer);
2492 connect_done(isc_task_t *task, isc_event_t *event);
2495 * Unlike send_udp, this can't be called multiple times with the same
2496 * query. When we retry TCP, we requeue the whole lookup, which should
2500 send_tcp_connect(dig_query_t *query) {
2501 isc_result_t result;
2505 debug("send_tcp_connect(%p)", query);
2508 query->waiting_connect = ISC_TRUE;
2509 query->lookup->current_query = query;
2510 result = get_address(query->servname, port, &query->sockaddr);
2511 if (result != ISC_R_SUCCESS) {
2513 * This servname doesn't have an address. Try the next server
2514 * by triggering an immediate 'timeout' (we lie, but the effect
2517 force_timeout(l, query);
2521 if (specified_source &&
2522 (isc_sockaddr_pf(&query->sockaddr) !=
2523 isc_sockaddr_pf(&bind_address))) {
2524 printf(";; Skipping server %s, incompatible "
2525 "address family\n", query->servname);
2526 query->waiting_connect = ISC_FALSE;
2527 next = ISC_LIST_NEXT(query, link);
2531 printf(";; No acceptable nameservers\n");
2532 check_next_lookup(l);
2535 send_tcp_connect(next);
2539 INSIST(query->sock == NULL);
2541 if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) {
2543 isc_socket_attach(keep, &query->sock);
2544 query->waiting_connect = ISC_FALSE;
2545 launch_next_query(query, ISC_TRUE);
2549 result = isc_socket_create(socketmgr,
2550 isc_sockaddr_pf(&query->sockaddr),
2551 isc_sockettype_tcp, &query->sock);
2552 check_result(result, "isc_socket_create");
2554 debug("sockcount=%d", sockcount);
2555 if (specified_source)
2556 result = isc_socket_bind(query->sock, &bind_address,
2557 ISC_SOCKET_REUSEADDRESS);
2559 if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
2561 isc_sockaddr_any(&bind_any);
2563 isc_sockaddr_any6(&bind_any);
2564 result = isc_socket_bind(query->sock, &bind_any, 0);
2566 check_result(result, "isc_socket_bind");
2567 bringup_timer(query, TCP_TIMEOUT);
2568 result = isc_socket_connect(query->sock, &query->sockaddr,
2569 global_task, connect_done, query);
2570 check_result(result, "isc_socket_connect");
2573 * If we're at the endgame of a nameserver search, we need to
2574 * immediately bring up all the queries. Do it here.
2576 if (l->ns_search_only && !l->trace_root) {
2577 debug("sending next, since searching");
2578 next = ISC_LIST_NEXT(query, link);
2579 if (ISC_LINK_LINKED(query, link))
2580 ISC_LIST_DEQUEUE(l->q, query, link);
2581 ISC_LIST_ENQUEUE(l->connecting, query, clink);
2583 send_tcp_connect(next);
2587 static isc_buffer_t *
2588 clone_buffer(isc_buffer_t *source) {
2589 isc_buffer_t *buffer;
2590 buffer = isc_mem_allocate(mctx, sizeof(*buffer));
2592 fatal("memory allocation failure in %s:%d",
2593 __FILE__, __LINE__);
2599 * Send a UDP packet to the remote nameserver, possible starting the
2600 * recv action as well. Also make sure that the timer is running and
2601 * is properly reset.
2604 send_udp(dig_query_t *query) {
2605 dig_lookup_t *l = NULL;
2606 isc_result_t result;
2607 isc_buffer_t *sendbuf;
2609 debug("send_udp(%p)", query);
2612 bringup_timer(query, UDP_TIMEOUT);
2613 l->current_query = query;
2614 debug("working on lookup %p, query %p", query->lookup, query);
2615 if (!query->recv_made) {
2616 /* XXX Check the sense of this, need assertion? */
2617 query->waiting_connect = ISC_FALSE;
2618 result = get_address(query->servname, port, &query->sockaddr);
2619 if (result != ISC_R_SUCCESS) {
2620 /* This servname doesn't have an address. */
2621 force_timeout(l, query);
2625 result = isc_socket_create(socketmgr,
2626 isc_sockaddr_pf(&query->sockaddr),
2627 isc_sockettype_udp, &query->sock);
2628 check_result(result, "isc_socket_create");
2630 debug("sockcount=%d", sockcount);
2631 if (specified_source) {
2632 result = isc_socket_bind(query->sock, &bind_address,
2633 ISC_SOCKET_REUSEADDRESS);
2635 isc_sockaddr_anyofpf(&bind_any,
2636 isc_sockaddr_pf(&query->sockaddr));
2637 result = isc_socket_bind(query->sock, &bind_any, 0);
2639 check_result(result, "isc_socket_bind");
2641 query->recv_made = ISC_TRUE;
2642 ISC_LINK_INIT(&query->recvbuf, link);
2643 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf,
2645 debug("recving with lookup=%p, query=%p, sock=%p",
2646 query->lookup, query, query->sock);
2647 result = isc_socket_recvv(query->sock, &query->recvlist, 1,
2648 global_task, recv_done, query);
2649 check_result(result, "isc_socket_recvv");
2651 debug("recvcount=%d", recvcount);
2653 ISC_LIST_INIT(query->sendlist);
2654 sendbuf = clone_buffer(&query->sendbuf);
2655 ISC_LIST_ENQUEUE(query->sendlist, sendbuf, link);
2656 debug("sending a request");
2657 TIME_NOW(&query->time_sent);
2658 INSIST(query->sock != NULL);
2659 query->waiting_senddone = ISC_TRUE;
2660 result = isc_socket_sendtov2(query->sock, &query->sendlist,
2661 global_task, send_done, query,
2662 &query->sockaddr, NULL,
2663 ISC_SOCKFLAG_NORETRY);
2664 check_result(result, "isc_socket_sendtov");
2669 * IO timeout handler, used for both connect and recv timeouts. If
2670 * retries are still allowed, either resend the UDP packet or queue a
2671 * new TCP lookup. Otherwise, cancel the lookup.
2674 connect_timeout(isc_task_t *task, isc_event_t *event) {
2675 dig_lookup_t *l = NULL;
2676 dig_query_t *query = NULL, *next, *cq;
2679 REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE);
2681 debug("connect_timeout()");
2685 query = l->current_query;
2686 isc_event_free(&event);
2690 if ((query != NULL) && (query->lookup->current_query != NULL) &&
2691 (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) {
2692 debug("trying next server...");
2693 cq = query->lookup->current_query;
2695 send_udp(ISC_LIST_NEXT(cq, link));
2697 if (query->sock != NULL)
2698 isc_socket_cancel(query->sock, NULL,
2699 ISC_SOCKCANCEL_ALL);
2700 next = ISC_LIST_NEXT(cq, link);
2702 send_tcp_connect(next);
2708 if (l->retries > 1) {
2711 debug("resending UDP request to first server");
2712 send_udp(ISC_LIST_HEAD(l->q));
2714 debug("making new TCP request, %d tries left",
2717 requeue_lookup(l, ISC_TRUE);
2719 check_next_lookup(l);
2722 fputs(l->cmdline, stdout);
2723 printf(";; connection timed out; no servers could be "
2726 check_next_lookup(l);
2734 * Event handler for the TCP recv which gets the length header of TCP
2735 * packets. Start the next recv of length bytes.
2738 tcp_length_done(isc_task_t *task, isc_event_t *event) {
2739 isc_socketevent_t *sevent;
2740 isc_buffer_t *b = NULL;
2741 isc_result_t result;
2742 dig_query_t *query = NULL;
2744 isc_uint16_t length;
2746 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
2751 debug("tcp_length_done()");
2754 sevent = (isc_socketevent_t *)event;
2755 query = event->ev_arg;
2758 INSIST(recvcount >= 0);
2760 b = ISC_LIST_HEAD(sevent->bufferlist);
2761 INSIST(b == &query->lengthbuf);
2762 ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2764 if (sevent->result == ISC_R_CANCELED) {
2765 isc_event_free(&event);
2768 check_next_lookup(l);
2772 if (sevent->result != ISC_R_SUCCESS) {
2773 char sockstr[ISC_SOCKADDR_FORMATSIZE];
2774 isc_sockaddr_format(&query->sockaddr, sockstr,
2776 printf(";; communications error to %s: %s\n",
2777 sockstr, isc_result_totext(sevent->result));
2779 isc_socket_detach(&query->sock);
2781 debug("sockcount=%d", sockcount);
2782 INSIST(sockcount >= 0);
2783 isc_event_free(&event);
2785 check_next_lookup(l);
2789 length = isc_buffer_getuint16(b);
2791 isc_event_free(&event);
2792 launch_next_query(query, ISC_FALSE);
2798 * Even though the buffer was already init'ed, we need
2799 * to redo it now, to force the length we want.
2801 isc_buffer_invalidate(&query->recvbuf);
2802 isc_buffer_init(&query->recvbuf, query->recvspace, length);
2803 ENSURE(ISC_LIST_EMPTY(query->recvlist));
2804 ISC_LINK_INIT(&query->recvbuf, link);
2805 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
2806 debug("recving with lookup=%p, query=%p", query->lookup, query);
2807 result = isc_socket_recvv(query->sock, &query->recvlist, length, task,
2809 check_result(result, "isc_socket_recvv");
2811 debug("resubmitted recv request with length %d, recvcount=%d",
2813 isc_event_free(&event);
2818 * For transfers that involve multiple recvs (XFR's in particular),
2819 * launch the next recv.
2822 launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
2823 isc_result_t result;
2825 isc_buffer_t *buffer;
2829 debug("launch_next_query()");
2831 if (!query->lookup->pending) {
2832 debug("ignoring launch_next_query because !pending");
2833 isc_socket_detach(&query->sock);
2835 debug("sockcount=%d", sockcount);
2836 INSIST(sockcount >= 0);
2837 query->waiting_connect = ISC_FALSE;
2840 check_next_lookup(l);
2844 isc_buffer_clear(&query->slbuf);
2845 isc_buffer_clear(&query->lengthbuf);
2846 isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->sendbuf.used);
2847 ISC_LIST_INIT(query->sendlist);
2848 ISC_LINK_INIT(&query->slbuf, link);
2849 if (!query->first_soa_rcvd) {
2850 buffer = clone_buffer(&query->slbuf);
2851 ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
2852 if (include_question) {
2853 buffer = clone_buffer(&query->sendbuf);
2854 ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
2858 ISC_LINK_INIT(&query->lengthbuf, link);
2859 ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
2861 result = isc_socket_recvv(query->sock, &query->lengthlist, 0,
2862 global_task, tcp_length_done, query);
2863 check_result(result, "isc_socket_recvv");
2865 debug("recvcount=%d", recvcount);
2866 if (!query->first_soa_rcvd) {
2867 debug("sending a request in launch_next_query");
2868 TIME_NOW(&query->time_sent);
2869 query->waiting_senddone = ISC_TRUE;
2870 result = isc_socket_sendv(query->sock, &query->sendlist,
2871 global_task, send_done, query);
2872 check_result(result, "isc_socket_sendv");
2874 debug("sendcount=%d", sendcount);
2876 query->waiting_connect = ISC_FALSE;
2878 check_next_lookup(query->lookup);
2884 * Event handler for TCP connect complete. Make sure the connection was
2885 * successful, then pass into launch_next_query to actually send the
2889 connect_done(isc_task_t *task, isc_event_t *event) {
2890 isc_socketevent_t *sevent = NULL;
2891 dig_query_t *query = NULL, *next;
2896 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
2899 debug("connect_done()");
2902 sevent = (isc_socketevent_t *)event;
2903 query = sevent->ev_arg;
2905 INSIST(query->waiting_connect);
2907 query->waiting_connect = ISC_FALSE;
2909 if (sevent->result == ISC_R_CANCELED) {
2910 debug("in cancel handler");
2911 isc_socket_detach(&query->sock);
2912 INSIST(sockcount > 0);
2914 debug("sockcount=%d", sockcount);
2915 query->waiting_connect = ISC_FALSE;
2916 isc_event_free(&event);
2919 check_next_lookup(l);
2923 if (sevent->result != ISC_R_SUCCESS) {
2924 char sockstr[ISC_SOCKADDR_FORMATSIZE];
2926 debug("unsuccessful connection: %s",
2927 isc_result_totext(sevent->result));
2928 isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
2929 if (sevent->result != ISC_R_CANCELED)
2930 printf(";; Connection to %s(%s) for %s failed: "
2932 query->servname, query->lookup->textname,
2933 isc_result_totext(sevent->result));
2934 isc_socket_detach(&query->sock);
2936 INSIST(sockcount >= 0);
2937 /* XXX Clean up exitcodes */
2940 debug("sockcount=%d", sockcount);
2941 query->waiting_connect = ISC_FALSE;
2942 isc_event_free(&event);
2944 if (l->current_query != NULL)
2945 next = ISC_LIST_NEXT(l->current_query, link);
2950 bringup_timer(next, TCP_TIMEOUT);
2951 send_tcp_connect(next);
2953 check_next_lookup(l);
2959 isc_socket_detach(&keep);
2960 isc_socket_attach(query->sock, &keep);
2961 keepaddr = query->sockaddr;
2963 launch_next_query(query, ISC_TRUE);
2964 isc_event_free(&event);
2969 * Check if the ongoing XFR needs more data before it's complete, using
2970 * the semantics of IXFR and AXFR protocols. Much of the complexity of
2971 * this routine comes from determining when an IXFR is complete.
2972 * ISC_FALSE means more data is on the way, and the recv has been issued.
2974 static isc_boolean_t
2975 check_for_more_data(dig_query_t *query, dns_message_t *msg,
2976 isc_socketevent_t *sevent)
2978 dns_rdataset_t *rdataset = NULL;
2979 dns_rdata_t rdata = DNS_RDATA_INIT;
2980 dns_rdata_soa_t soa;
2981 isc_uint32_t ixfr_serial = query->lookup->ixfr_serial, serial;
2982 isc_result_t result;
2983 isc_boolean_t ixfr = query->lookup->rdtype == dns_rdatatype_ixfr;
2984 isc_boolean_t axfr = query->lookup->rdtype == dns_rdatatype_axfr;
2987 axfr = query->ixfr_axfr;
2989 debug("check_for_more_data()");
2992 * By the time we're in this routine, we know we're doing
2993 * either an AXFR or IXFR. If there's no second_rr_type,
2994 * then we don't yet know which kind of answer we got back
2995 * from the server. Here, we're going to walk through the
2996 * rr's in the message, acting as necessary whenever we hit
3001 query->byte_count += sevent->n;
3002 result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
3003 if (result != ISC_R_SUCCESS) {
3004 puts("; Transfer failed.");
3010 dns_message_currentname(msg, DNS_SECTION_ANSWER,
3012 for (rdataset = ISC_LIST_HEAD(name->list);
3014 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3015 result = dns_rdataset_first(rdataset);
3016 if (result != ISC_R_SUCCESS)
3020 dns_rdata_reset(&rdata);
3021 dns_rdataset_current(rdataset, &rdata);
3023 * If this is the first rr, make sure
3026 if ((!query->first_soa_rcvd) &&
3027 (rdata.type != dns_rdatatype_soa)) {
3028 puts("; Transfer failed. "
3029 "Didn't start with SOA answer.");
3032 if ((!query->second_rr_rcvd) &&
3033 (rdata.type != dns_rdatatype_soa)) {
3034 query->second_rr_rcvd = ISC_TRUE;
3035 query->second_rr_serial = 0;
3036 debug("got the second rr as nonsoa");
3037 axfr = query->ixfr_axfr = ISC_TRUE;
3042 * If the record is anything except an SOA
3043 * now, just continue on...
3045 if (rdata.type != dns_rdatatype_soa)
3048 /* Now we have an SOA. Work with it. */
3049 debug("got an SOA");
3050 result = dns_rdata_tostruct(&rdata, &soa, NULL);
3051 check_result(result, "dns_rdata_tostruct");
3052 serial = soa.serial;
3053 dns_rdata_freestruct(&soa);
3054 if (!query->first_soa_rcvd) {
3055 query->first_soa_rcvd = ISC_TRUE;
3056 query->first_rr_serial = serial;
3057 debug("this is the first serial %u",
3059 if (ixfr && isc_serial_ge(ixfr_serial,
3061 debug("got up to date "
3068 debug("doing axfr, got second SOA");
3071 if (!query->second_rr_rcvd) {
3072 if (query->first_rr_serial == serial) {
3073 debug("doing ixfr, got "
3077 debug("this is the second serial %u",
3079 query->second_rr_rcvd = ISC_TRUE;
3080 query->second_rr_serial = serial;
3084 * If we get to this point, we're doing an
3085 * IXFR and have to start really looking
3086 * at serial numbers.
3088 if (query->first_rr_serial == serial) {
3089 debug("got a match for ixfr");
3090 if (!query->first_repeat_rcvd) {
3091 query->first_repeat_rcvd =
3095 debug("done with ixfr");
3098 debug("meaningless soa %u", serial);
3100 result = dns_rdataset_next(rdataset);
3101 } while (result == ISC_R_SUCCESS);
3103 result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
3104 } while (result == ISC_R_SUCCESS);
3105 launch_next_query(query, ISC_FALSE);
3108 received(sevent->n, &sevent->address, query);
3113 * Event handler for recv complete. Perform whatever actions are necessary,
3114 * based on the specifics of the user's request.
3117 recv_done(isc_task_t *task, isc_event_t *event) {
3118 isc_socketevent_t *sevent = NULL;
3119 dig_query_t *query = NULL;
3120 isc_buffer_t *b = NULL;
3121 dns_message_t *msg = NULL;
3123 dig_message_t *chase_msg = NULL;
3124 dig_message_t *chase_msg2 = NULL;
3126 isc_result_t result;
3127 dig_lookup_t *n, *l;
3128 isc_boolean_t docancel = ISC_FALSE;
3129 isc_boolean_t match = ISC_TRUE;
3130 unsigned int parseflags;
3132 unsigned int msgflags;
3134 isc_result_t do_sigchase = ISC_FALSE;
3136 dns_message_t *msg_temp = NULL;
3138 isc_buffer_t *buf = NULL;
3144 debug("recv_done()");
3148 debug("recvcount=%d", recvcount);
3149 INSIST(recvcount >= 0);
3151 query = event->ev_arg;
3152 debug("lookup=%p, query=%p", query->lookup, query);
3156 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
3157 sevent = (isc_socketevent_t *)event;
3159 b = ISC_LIST_HEAD(sevent->bufferlist);
3160 INSIST(b == &query->recvbuf);
3161 ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link);
3163 if ((l->tcp_mode) && (l->timer != NULL))
3164 isc_timer_touch(l->timer);
3165 if ((!l->pending && !l->ns_search_only) || cancel_now) {
3166 debug("no longer pending. Got %s",
3167 isc_result_totext(sevent->result));
3168 query->waiting_connect = ISC_FALSE;
3170 isc_event_free(&event);
3172 check_next_lookup(l);
3177 if (sevent->result != ISC_R_SUCCESS) {
3178 if (sevent->result == ISC_R_CANCELED) {
3179 debug("in recv cancel handler");
3180 query->waiting_connect = ISC_FALSE;
3182 printf(";; communications error: %s\n",
3183 isc_result_totext(sevent->result));
3184 isc_socket_detach(&query->sock);
3186 debug("sockcount=%d", sockcount);
3187 INSIST(sockcount >= 0);
3189 isc_event_free(&event);
3191 check_next_lookup(l);
3197 !isc_sockaddr_compare(&sevent->address, &query->sockaddr,
3198 ISC_SOCKADDR_CMPADDR|
3199 ISC_SOCKADDR_CMPPORT|
3200 ISC_SOCKADDR_CMPSCOPE|
3201 ISC_SOCKADDR_CMPSCOPEZERO)) {
3202 char buf1[ISC_SOCKADDR_FORMATSIZE];
3203 char buf2[ISC_SOCKADDR_FORMATSIZE];
3206 if (isc_sockaddr_pf(&query->sockaddr) == AF_INET)
3207 isc_sockaddr_any(&any);
3209 isc_sockaddr_any6(&any);
3212 * We don't expect a match when the packet is
3213 * sent to 0.0.0.0, :: or to a multicast addresses.
3214 * XXXMPA broadcast needs to be handled here as well.
3216 if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) &&
3217 !isc_sockaddr_ismulticast(&query->sockaddr)) ||
3218 isc_sockaddr_getport(&query->sockaddr) !=
3219 isc_sockaddr_getport(&sevent->address)) {
3220 isc_sockaddr_format(&sevent->address, buf1,
3222 isc_sockaddr_format(&query->sockaddr, buf2,
3224 printf(";; reply from unexpected source: %s,"
3225 " expected %s\n", buf1, buf2);
3230 result = dns_message_peekheader(b, &id, &msgflags);
3231 if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
3234 isc_boolean_t fail = ISC_TRUE;
3235 if (result == ISC_R_SUCCESS) {
3236 if (!query->first_soa_rcvd ||
3238 printf(";; %s: ID mismatch: "
3239 "expected ID %u, got %u\n",
3240 query->first_soa_rcvd ?
3241 "WARNING" : "ERROR",
3242 l->sendmsg->id, id);
3243 if (query->first_soa_rcvd)
3245 query->warn_id = ISC_FALSE;
3247 printf(";; ERROR: short "
3248 "(< header size) message\n");
3250 isc_event_free(&event);
3252 check_next_lookup(l);
3257 } else if (result == ISC_R_SUCCESS)
3258 printf(";; Warning: ID mismatch: "
3259 "expected ID %u, got %u\n", l->sendmsg->id, id);
3261 printf(";; Warning: short "
3262 "(< header size) message received\n");
3265 if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0)
3266 printf(";; Warning: query response not set\n");
3271 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
3272 check_result(result, "dns_message_create");
3275 if (l->querysig == NULL) {
3276 debug("getting initial querysig");
3277 result = dns_message_getquerytsig(l->sendmsg, mctx,
3279 check_result(result, "dns_message_getquerytsig");
3281 result = dns_message_setquerytsig(msg, l->querysig);
3282 check_result(result, "dns_message_setquerytsig");
3283 result = dns_message_settsigkey(msg, key);
3284 check_result(result, "dns_message_settsigkey");
3285 msg->tsigctx = l->tsigctx;
3287 if (l->msgcounter != 0)
3288 msg->tcp_continuation = 1;
3292 debug("before parse starts");
3293 parseflags = DNS_MESSAGEPARSE_PRESERVEORDER;
3296 do_sigchase = ISC_FALSE;
3299 do_sigchase = ISC_TRUE;
3302 if (l->besteffort) {
3303 parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
3304 parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
3306 result = dns_message_parse(msg, b, parseflags);
3307 if (result == DNS_R_RECOVERABLE) {
3308 printf(";; Warning: Message parser reports malformed "
3309 "message packet.\n");
3310 result = ISC_R_SUCCESS;
3312 if (result != ISC_R_SUCCESS) {
3313 printf(";; Got bad packet: %s\n", isc_result_totext(result));
3315 query->waiting_connect = ISC_FALSE;
3316 dns_message_destroy(&msg);
3317 isc_event_free(&event);
3320 check_next_lookup(l);
3324 if (msg->counts[DNS_SECTION_QUESTION] != 0) {
3326 for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
3327 result == ISC_R_SUCCESS && match;
3328 result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) {
3329 dns_name_t *name = NULL;
3330 dns_rdataset_t *rdataset;
3332 dns_message_currentname(msg, DNS_SECTION_QUESTION,
3334 for (rdataset = ISC_LIST_HEAD(name->list);
3336 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3337 if (l->rdtype != rdataset->type ||
3338 l->rdclass != rdataset->rdclass ||
3339 !dns_name_equal(l->name, name)) {
3340 char namestr[DNS_NAME_FORMATSIZE];
3341 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3342 char classbuf[DNS_RDATACLASS_FORMATSIZE];
3343 dns_name_format(name, namestr,
3345 dns_rdatatype_format(rdataset->type,
3348 dns_rdataclass_format(rdataset->rdclass,
3351 printf(";; Question section mismatch: "
3353 namestr, typebuf, classbuf);
3359 dns_message_destroy(&msg);
3361 isc_event_free(&event);
3363 check_next_lookup(l);
3370 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 &&
3371 !l->ignore && !l->tcp_mode) {
3372 printf(";; Truncated, retrying in TCP mode.\n");
3373 n = requeue_lookup(l, ISC_TRUE);
3374 n->tcp_mode = ISC_TRUE;
3375 n->origin = query->lookup->origin;
3376 dns_message_destroy(&msg);
3377 isc_event_free(&event);
3380 check_next_lookup(l);
3384 if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) ||
3385 (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse))
3387 dig_query_t *next = ISC_LIST_NEXT(query, link);
3388 if (l->current_query == query)
3389 l->current_query = NULL;
3391 debug("sending query %p\n", next);
3393 send_tcp_connect(next);
3398 * If our query is at the head of the list and there
3399 * is no next, we're the only one left, so fall
3400 * through to print the message.
3402 if ((ISC_LIST_HEAD(l->q) != query) ||
3403 (ISC_LIST_NEXT(query, link) != NULL)) {
3404 if( l->comments == ISC_TRUE )
3405 printf(";; Got %s from %s, "
3406 "trying next server\n",
3407 msg->rcode == dns_rcode_servfail ?
3409 "recursion not available",
3412 check_next_lookup(l);
3413 dns_message_destroy(&msg);
3414 isc_event_free(&event);
3421 result = dns_tsig_verify(&query->recvbuf, msg, NULL, NULL);
3422 if (result != ISC_R_SUCCESS) {
3423 printf(";; Couldn't verify signature: %s\n",
3424 isc_result_totext(result));
3425 validated = ISC_FALSE;
3427 l->tsigctx = msg->tsigctx;
3428 msg->tsigctx = NULL;
3429 if (l->querysig != NULL) {
3430 debug("freeing querysig buffer %p", l->querysig);
3431 isc_buffer_free(&l->querysig);
3433 result = dns_message_getquerytsig(msg, mctx, &l->querysig);
3434 check_result(result,"dns_message_getquerytsig");
3437 extrabytes = isc_buffer_remaininglength(b);
3439 debug("after parse");
3440 if (l->doing_xfr && l->xfr_q == NULL) {
3443 * Once we are in the XFR message, increase
3444 * the timeout to much longer, so brief network
3445 * outages won't cause the XFR to abort
3447 if (timeout != INT_MAX && l->timer != NULL) {
3448 unsigned int local_timeout;
3452 local_timeout = TCP_TIMEOUT * 4;
3454 local_timeout = UDP_TIMEOUT * 4;
3456 if (timeout < (INT_MAX / 4))
3457 local_timeout = timeout * 4;
3459 local_timeout = INT_MAX;
3461 debug("have local timeout of %d", local_timeout);
3462 isc_interval_set(&l->interval, local_timeout, 0);
3463 result = isc_timer_reset(l->timer,
3468 check_result(result, "isc_timer_reset");
3472 if (!l->doing_xfr || l->xfr_q == query) {
3473 if (msg->rcode == dns_rcode_nxdomain &&
3474 (l->origin != NULL || l->need_search)) {
3475 if (!next_origin(query) || showsearch) {
3476 printmessage(query, msg, ISC_TRUE);
3477 received(b->used, &sevent->address, query);
3479 } else if (!l->trace && !l->ns_search_only) {
3483 printmessage(query, msg, ISC_TRUE);
3484 } else if (l->trace) {
3486 int count = msg->counts[DNS_SECTION_ANSWER];
3488 debug("in TRACE code");
3489 if (!l->ns_search_only)
3490 printmessage(query, msg, ISC_TRUE);
3492 l->rdtype = l->qrdtype;
3493 if (l->trace_root || (l->ns_search_only && count > 0)) {
3495 l->rdtype = dns_rdatatype_soa;
3496 n = followup_lookup(msg, query,
3497 DNS_SECTION_ANSWER);
3498 l->trace_root = ISC_FALSE;
3499 } else if (count == 0)
3500 n = followup_lookup(msg, query,
3501 DNS_SECTION_AUTHORITY);
3503 docancel = ISC_TRUE;
3505 debug("in NSSEARCH code");
3507 if (l->trace_root) {
3509 * This is the initial NS query.
3513 l->rdtype = dns_rdatatype_soa;
3514 n = followup_lookup(msg, query,
3515 DNS_SECTION_ANSWER);
3517 docancel = ISC_TRUE;
3518 l->trace_root = ISC_FALSE;
3519 usesearch = ISC_FALSE;
3524 printmessage(query, msg, ISC_TRUE);
3528 chase_msg = isc_mem_allocate(mctx,
3529 sizeof(dig_message_t));
3530 if (chase_msg == NULL) {
3531 fatal("Memory allocation failure in %s:%d",
3532 __FILE__, __LINE__);
3534 ISC_LIST_INITANDAPPEND(chase_message_list, chase_msg,
3536 if (dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
3537 &msg_temp) != ISC_R_SUCCESS) {
3538 fatal("dns_message_create in %s:%d",
3539 __FILE__, __LINE__);
3542 isc_buffer_usedregion(b, &r);
3543 result = isc_buffer_allocate(mctx, &buf, r.length);
3545 check_result(result, "isc_buffer_allocate");
3546 result = isc_buffer_copyregion(buf, &r);
3547 check_result(result, "isc_buffer_copyregion");
3549 result = dns_message_parse(msg_temp, buf, 0);
3551 isc_buffer_free(&buf);
3552 chase_msg->msg = msg_temp;
3554 chase_msg2 = isc_mem_allocate(mctx,
3555 sizeof(dig_message_t));
3556 if (chase_msg2 == NULL) {
3557 fatal("Memory allocation failure in %s:%d",
3558 __FILE__, __LINE__);
3560 ISC_LIST_INITANDAPPEND(chase_message_list2, chase_msg2,
3562 chase_msg2->msg = msg;
3568 if (l->sigchase && ISC_LIST_EMPTY(lookup_list)) {
3574 debug("still pending.");
3576 if (query != l->xfr_q) {
3577 dns_message_destroy(&msg);
3578 isc_event_free(&event);
3579 query->waiting_connect = ISC_FALSE;
3584 docancel = check_for_more_data(query, msg, sevent);
3586 dns_message_destroy(&msg);
3589 check_next_lookup(l);
3593 if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
3598 received(b->used, &sevent->address, query);
3601 if (!query->lookup->ns_search_only)
3602 query->lookup->pending = ISC_FALSE;
3603 if (!query->lookup->ns_search_only ||
3604 query->lookup->trace_root || docancel) {
3608 dns_message_destroy(&msg);
3613 check_next_lookup(l);
3621 dns_message_destroy(&msg);
3623 isc_event_free(&event);
3628 isc_buffer_invalidate(&query->recvbuf);
3629 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
3630 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
3631 result = isc_socket_recvv(query->sock, &query->recvlist, 1,
3632 global_task, recv_done, query);
3633 check_result(result, "isc_socket_recvv");
3635 isc_event_free(&event);
3641 * Turn a name into an address, using system-supplied routines. This is
3642 * used in looking up server names, etc... and needs to use system-supplied
3643 * routines, since they may be using a non-DNS system for these lookups.
3646 get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
3648 isc_result_t result;
3651 result = bind9_getaddresses(host, port, sockaddr, 1, &count);
3653 if (result != ISC_R_SUCCESS)
3658 return (ISC_R_SUCCESS);
3662 getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) {
3663 isc_result_t result;
3664 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
3665 isc_netaddr_t netaddr;
3668 char tmp[ISC_NETADDR_FORMATSIZE];
3670 result = bind9_getaddresses(host, 0, sockaddrs,
3671 DIG_MAX_ADDRESSES, &count);
3672 if (resultp != NULL)
3674 if (result != ISC_R_SUCCESS) {
3675 if (resultp == NULL)
3676 fatal("couldn't get address for '%s': %s",
3677 host, isc_result_totext(result));
3681 for (i = 0; i < count; i++) {
3682 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
3683 isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
3684 srv = make_server(tmp, host);
3685 ISC_LIST_APPEND(lookup->my_server_list, srv, link);
3692 * Initiate either a TCP or UDP lookup
3695 do_lookup(dig_lookup_t *lookup) {
3698 REQUIRE(lookup != NULL);
3700 debug("do_lookup()");
3701 lookup->pending = ISC_TRUE;
3702 query = ISC_LIST_HEAD(lookup->q);
3703 if (query != NULL) {
3704 if (lookup->tcp_mode)
3705 send_tcp_connect(query);
3712 * Start everything in action upon task startup.
3715 onrun_callback(isc_task_t *task, isc_event_t *event) {
3718 isc_event_free(&event);
3725 * Make everything on the lookup queue go away. Mainly used by the
3730 dig_lookup_t *l, *n;
3731 dig_query_t *q, *nq;
3733 debug("cancel_all()");
3740 cancel_now = ISC_TRUE;
3741 if (current_lookup != NULL) {
3742 if (current_lookup->timer != NULL)
3743 isc_timer_detach(¤t_lookup->timer);
3744 for (q = ISC_LIST_HEAD(current_lookup->q);
3748 nq = ISC_LIST_NEXT(q, link);
3749 debug("canceling pending query %p, belonging to %p",
3751 if (q->sock != NULL)
3752 isc_socket_cancel(q->sock, NULL,
3753 ISC_SOCKCANCEL_ALL);
3757 for (q = ISC_LIST_HEAD(current_lookup->connecting);
3761 nq = ISC_LIST_NEXT(q, clink);
3762 debug("canceling connecting query %p, belonging to %p",
3764 if (q->sock != NULL)
3765 isc_socket_cancel(q->sock, NULL,
3766 ISC_SOCKCANCEL_ALL);
3771 l = ISC_LIST_HEAD(lookup_list);
3773 n = ISC_LIST_NEXT(l, link);
3774 ISC_LIST_DEQUEUE(lookup_list, l, link);
3775 try_clear_lookup(l);
3782 * Destroy all of the libs we are using, and get everything ready for a
3786 destroy_libs(void) {
3789 dig_message_t *chase_msg;
3792 isc_result_t result;
3796 isc_socket_detach(&keep);
3797 debug("destroy_libs()");
3798 if (global_task != NULL) {
3799 debug("freeing task");
3800 isc_task_detach(&global_task);
3803 * The taskmgr_destroy() call blocks until all events are cleared
3806 if (taskmgr != NULL) {
3807 debug("freeing taskmgr");
3808 isc_taskmgr_destroy(&taskmgr);
3811 REQUIRE(sockcount == 0);
3812 REQUIRE(recvcount == 0);
3813 REQUIRE(sendcount == 0);
3815 INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
3816 INSIST(current_lookup == NULL);
3819 free_now = ISC_TRUE;
3821 lwres_conf_clear(lwctx);
3822 lwres_context_destroy(&lwctx);
3824 flush_server_list();
3829 result = dns_name_settotextfilter(NULL);
3830 check_result(result, "dns_name_settotextfilter");
3834 if (commctx != NULL) {
3835 debug("freeing commctx");
3836 isc_mempool_destroy(&commctx);
3838 if (socketmgr != NULL) {
3839 debug("freeing socketmgr");
3840 isc_socketmgr_destroy(&socketmgr);
3842 if (timermgr != NULL) {
3843 debug("freeing timermgr");
3844 isc_timermgr_destroy(&timermgr);
3847 debug("freeing key %p", key);
3848 dns_tsigkey_detach(&key);
3850 if (namebuf != NULL)
3851 isc_buffer_free(&namebuf);
3854 debug("destroy DST lib");
3856 is_dst_up = ISC_FALSE;
3859 debug("detach from entropy");
3860 isc_entropy_detach(&entp);
3864 DESTROYLOCK(&lookup_lock);
3867 debug("Destroy the messages kept for sigchase");
3868 /* Destroy the messages kept for sigchase */
3869 chase_msg = ISC_LIST_HEAD(chase_message_list);
3871 while (chase_msg != NULL) {
3872 INSIST(chase_msg->msg != NULL);
3873 dns_message_destroy(&(chase_msg->msg));
3875 chase_msg = ISC_LIST_NEXT(chase_msg, link);
3876 isc_mem_free(mctx, ptr);
3879 chase_msg = ISC_LIST_HEAD(chase_message_list2);
3881 while (chase_msg != NULL) {
3882 INSIST(chase_msg->msg != NULL);
3883 dns_message_destroy(&(chase_msg->msg));
3885 chase_msg = ISC_LIST_NEXT(chase_msg, link);
3886 isc_mem_free(mctx, ptr);
3888 if (dns_name_dynamic(&chase_name))
3889 free_name(&chase_name, mctx);
3891 if (dns_name_dynamic(&chase_current_name))
3892 free_name(&chase_current_name, mctx);
3893 if (dns_name_dynamic(&chase_authority_name))
3894 free_name(&chase_authority_name, mctx);
3897 if (dns_name_dynamic(&chase_signame))
3898 free_name(&chase_signame, mctx);
3902 debug("Removing log context");
3903 isc_log_destroy(&lctx);
3905 debug("Destroy memory");
3906 if (memdebugging != 0)
3907 isc_mem_stats(mctx, stderr);
3909 isc_mem_destroy(&mctx);
3914 initialize_idn(void) {
3916 isc_result_t result;
3918 #ifdef HAVE_SETLOCALE
3920 (void)setlocale(LC_ALL, "");
3922 /* Create configuration context. */
3923 r = idn_nameinit(1);
3924 if (r != idn_success)
3925 fatal("idn api initialization failed: %s",
3926 idn_result_tostring(r));
3928 /* Set domain name -> text post-conversion filter. */
3929 result = dns_name_settotextfilter(output_filter);
3930 check_result(result, "dns_name_settotextfilter");
3934 output_filter(isc_buffer_t *buffer, unsigned int used_org,
3935 isc_boolean_t absolute)
3937 char tmp1[MAXDLEN], tmp2[MAXDLEN];
3938 size_t fromlen, tolen;
3939 isc_boolean_t end_with_dot;
3942 * Copy contents of 'buffer' to 'tmp1', supply trailing dot
3943 * if 'absolute' is true, and terminate with NUL.
3945 fromlen = isc_buffer_usedlength(buffer) - used_org;
3946 if (fromlen >= MAXDLEN)
3947 return (ISC_R_SUCCESS);
3948 memmove(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
3949 end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE;
3950 if (absolute && !end_with_dot) {
3952 if (fromlen >= MAXDLEN)
3953 return (ISC_R_SUCCESS);
3954 tmp1[fromlen - 1] = '.';
3956 tmp1[fromlen] = '\0';
3959 * Convert contents of 'tmp1' to local encoding.
3961 if (idn_decodename(IDN_DECODE_APP, tmp1, tmp2, MAXDLEN) != idn_success)
3962 return (ISC_R_SUCCESS);
3966 * Copy the converted contents in 'tmp1' back to 'buffer'.
3967 * If we have appended trailing dot, remove it.
3969 tolen = strlen(tmp1);
3970 if (absolute && !end_with_dot && tmp1[tolen - 1] == '.')
3973 if (isc_buffer_length(buffer) < used_org + tolen)
3974 return (ISC_R_NOSPACE);
3976 isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org);
3977 memmove(isc_buffer_used(buffer), tmp1, tolen);
3978 isc_buffer_add(buffer, (unsigned int)tolen);
3980 return (ISC_R_SUCCESS);
3984 append_textname(char *name, const char *origin, size_t namesize) {
3985 size_t namelen = strlen(name);
3986 size_t originlen = strlen(origin);
3988 /* Already absolute? */
3989 if (namelen > 0 && name[namelen - 1] == '.')
3992 /* Append dot and origin */
3994 if (namelen + 1 + originlen >= namesize)
3995 return idn_buffer_overflow;
3998 name[namelen++] = '.';
3999 (void)strcpy(name + namelen, origin);
4004 idn_check_result(idn_result_t r, const char *msg) {
4005 if (r != idn_success) {
4007 fatal("%s: %s", msg, idn_result_tostring(r));
4010 #endif /* WITH_IDN */
4014 print_type(dns_rdatatype_t type)
4016 isc_buffer_t * b = NULL;
4017 isc_result_t result;
4020 result = isc_buffer_allocate(mctx, &b, 4000);
4021 check_result(result, "isc_buffer_allocate");
4023 result = dns_rdatatype_totext(type, b);
4024 check_result(result, "print_type");
4026 isc_buffer_usedregion(b, &r);
4027 r.base[r.length] = '\0';
4029 printf("%s", r.base);
4031 isc_buffer_free(&b);
4035 dump_database_section(dns_message_t *msg, int section)
4037 dns_name_t *msg_name=NULL;
4039 dns_rdataset_t *rdataset;
4042 dns_message_currentname(msg, section, &msg_name);
4044 for (rdataset = ISC_LIST_HEAD(msg_name->list); rdataset != NULL;
4045 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4046 dns_name_print(msg_name, stdout);
4048 print_rdataset(msg_name, rdataset, mctx);
4052 } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
4056 dump_database(void) {
4057 dig_message_t * msg;
4059 for (msg = ISC_LIST_HEAD(chase_message_list); msg != NULL;
4060 msg = ISC_LIST_NEXT(msg, link)) {
4061 if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
4063 dump_database_section(msg->msg, DNS_SECTION_ANSWER);
4065 if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
4067 dump_database_section(msg->msg, DNS_SECTION_AUTHORITY);
4069 if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
4071 dump_database_section(msg->msg, DNS_SECTION_ADDITIONAL);
4077 search_type(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) {
4078 dns_rdataset_t *rdataset;
4079 dns_rdata_sig_t siginfo;
4080 dns_rdata_t sigrdata = DNS_RDATA_INIT;
4081 isc_result_t result;
4083 for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
4084 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4085 if (type == dns_rdatatype_any) {
4086 if (rdataset->type != dns_rdatatype_rrsig)
4088 } else if ((type == dns_rdatatype_rrsig) &&
4089 (rdataset->type == dns_rdatatype_rrsig)) {
4090 result = dns_rdataset_first(rdataset);
4091 check_result(result, "empty rdataset");
4092 dns_rdataset_current(rdataset, &sigrdata);
4093 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4094 check_result(result, "sigrdata tostruct siginfo");
4096 if ((siginfo.covered == covers) ||
4097 (covers == dns_rdatatype_any)) {
4098 dns_rdata_reset(&sigrdata);
4099 dns_rdata_freestruct(&siginfo);
4102 dns_rdata_reset(&sigrdata);
4103 dns_rdata_freestruct(&siginfo);
4104 } else if (rdataset->type == type)
4111 chase_scanname_section(dns_message_t *msg, dns_name_t *name,
4112 dns_rdatatype_t type, dns_rdatatype_t covers,
4115 dns_rdataset_t *rdataset;
4116 dns_name_t *msg_name = NULL;
4119 dns_message_currentname(msg, section, &msg_name);
4120 if (dns_name_compare(msg_name, name) == 0) {
4121 rdataset = search_type(msg_name, type, covers);
4122 if (rdataset != NULL)
4126 } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
4133 chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers)
4135 dns_rdataset_t *rdataset = NULL;
4136 dig_message_t * msg;
4138 for (msg = ISC_LIST_HEAD(chase_message_list2); msg != NULL;
4139 msg = ISC_LIST_NEXT(msg, link)) {
4140 if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
4142 rdataset = chase_scanname_section(msg->msg, name,
4144 DNS_SECTION_ANSWER);
4145 if (rdataset != NULL)
4147 if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
4150 chase_scanname_section(msg->msg, name,
4152 DNS_SECTION_AUTHORITY);
4153 if (rdataset != NULL)
4155 if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
4158 chase_scanname_section(msg->msg, name, type,
4160 DNS_SECTION_ADDITIONAL);
4161 if (rdataset != NULL)
4169 sigchase_scanname(dns_rdatatype_t type, dns_rdatatype_t covers,
4170 isc_boolean_t * lookedup, dns_name_t *rdata_name)
4172 dig_lookup_t *lookup;
4173 isc_buffer_t *b = NULL;
4175 isc_result_t result;
4176 dns_rdataset_t * temp;
4177 dns_rdatatype_t querytype;
4179 temp = chase_scanname(rdata_name, type, covers);
4183 if (*lookedup == ISC_TRUE)
4186 lookup = clone_lookup(current_lookup, ISC_TRUE);
4187 lookup->trace_root = ISC_FALSE;
4188 lookup->new_search = ISC_TRUE;
4190 result = isc_buffer_allocate(mctx, &b, BUFSIZE);
4191 check_result(result, "isc_buffer_allocate");
4192 result = dns_name_totext(rdata_name, ISC_FALSE, b);
4193 check_result(result, "dns_name_totext");
4194 isc_buffer_usedregion(b, &r);
4195 r.base[r.length] = '\0';
4196 strlcpy(lookup->textname, (char*)r.base, sizeof(lookup->textname));
4197 isc_buffer_free(&b);
4199 if (type == dns_rdatatype_rrsig)
4204 if (querytype == 0 || querytype == 255) {
4205 printf("Error in the queried type: %d\n", querytype);
4209 lookup->rdtype = querytype;
4210 lookup->rdtypeset = ISC_TRUE;
4211 lookup->qrdtype = querytype;
4212 *lookedup = ISC_TRUE;
4214 ISC_LIST_APPEND(lookup_list, lookup, link);
4215 printf("\n\nLaunch a query to find a RRset of type ");
4217 printf(" for zone: %s\n", lookup->textname);
4222 insert_trustedkey(void *arg, dns_name_t *name, dns_rdataset_t *rdataset)
4224 isc_result_t result;
4229 if (rdataset == NULL || rdataset->type != dns_rdatatype_dnskey)
4230 return (ISC_R_SUCCESS);
4232 for (result = dns_rdataset_first(rdataset);
4233 result == ISC_R_SUCCESS;
4234 result = dns_rdataset_next(rdataset)) {
4235 dns_rdata_t rdata = DNS_RDATA_INIT;
4238 dns_rdataset_current(rdataset, &rdata);
4239 isc_buffer_init(&b, rdata.data, rdata.length);
4240 isc_buffer_add(&b, rdata.length);
4241 if (tk_list.nb_tk >= MAX_TRUSTED_KEY)
4242 return (ISC_R_SUCCESS);
4244 result = dst_key_fromdns(name, rdata.rdclass, &b, mctx, &key);
4245 if (result != ISC_R_SUCCESS)
4247 tk_list.key[tk_list.nb_tk++] = key;
4249 return (ISC_R_SUCCESS);
4257 for (i= 0; i < MAX_TRUSTED_KEY; i++) {
4258 if (tk_list.key[i] != NULL) {
4259 dst_key_free(&tk_list.key[i]);
4260 tk_list.key[i] = NULL;
4269 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
4272 removetmpkey(isc_mem_t *mctx, const char *file)
4274 char *tempnamekey = NULL;
4276 isc_result_t result;
4278 tempnamekeylen = strlen(file)+10;
4280 tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
4281 if (tempnamekey == NULL)
4282 return (ISC_R_NOMEMORY);
4284 memset(tempnamekey, 0, tempnamekeylen);
4286 strcat(tempnamekey, file);
4287 strcat(tempnamekey,".key");
4288 isc_file_remove(tempnamekey);
4290 result = isc_file_remove(tempnamekey);
4291 isc_mem_free(mctx, tempnamekey);
4296 get_trusted_key(isc_mem_t *mctx)
4298 isc_result_t result;
4299 const char *filename = NULL;
4300 dns_rdatacallbacks_t callbacks;
4302 result = isc_file_exists(trustedkey);
4303 if (result != ISC_TRUE) {
4304 result = isc_file_exists("/etc/trusted-key.key");
4305 if (result != ISC_TRUE) {
4306 result = isc_file_exists("./trusted-key.key");
4307 if (result != ISC_TRUE)
4308 return (ISC_R_FAILURE);
4310 filename = "./trusted-key.key";
4312 filename = "/etc/trusted-key.key";
4314 filename = trustedkey;
4316 if (filename == NULL) {
4317 printf("No trusted key\n");
4318 return (ISC_R_FAILURE);
4321 dns_rdatacallbacks_init_stdio(&callbacks);
4322 callbacks.add = insert_trustedkey;
4323 return (dns_master_loadfile(filename, dns_rootname, dns_rootname,
4324 current_lookup->rdclass, 0, &callbacks,
4330 nameFromString(const char *str, dns_name_t *p_ret) {
4331 size_t len = strlen(str);
4332 isc_result_t result;
4333 isc_buffer_t buffer;
4334 dns_fixedname_t fixedname;
4336 REQUIRE(p_ret != NULL);
4337 REQUIRE(str != NULL);
4339 isc_buffer_constinit(&buffer, str, len);
4340 isc_buffer_add(&buffer, len);
4342 dns_fixedname_init(&fixedname);
4343 result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer,
4344 dns_rootname, DNS_NAME_DOWNCASE, NULL);
4345 check_result(result, "nameFromString");
4347 if (dns_name_dynamic(p_ret))
4348 free_name(p_ret, mctx);
4350 result = dns_name_dup(dns_fixedname_name(&fixedname), mctx, p_ret);
4351 check_result(result, "nameFromString");
4357 prepare_lookup(dns_name_t *name)
4359 isc_result_t result;
4360 dig_lookup_t *lookup = NULL;
4364 lookup = clone_lookup(current_lookup, ISC_TRUE);
4365 lookup->trace_root = ISC_FALSE;
4366 lookup->new_search = ISC_TRUE;
4367 lookup->trace_root_sigchase = ISC_FALSE;
4369 strlcpy(lookup->textname, lookup->textnamesigchase, MXNAME);
4371 lookup->rdtype = lookup->rdtype_sigchase;
4372 lookup->rdtypeset = ISC_TRUE;
4373 lookup->qrdtype = lookup->qrdtype_sigchase;
4375 s = ISC_LIST_HEAD(lookup->my_server_list);
4377 debug("freeing server %p belonging to %p",
4380 s = ISC_LIST_NEXT(s, link);
4381 ISC_LIST_DEQUEUE(lookup->my_server_list,
4382 (dig_server_t *)ptr, link);
4383 isc_mem_free(mctx, ptr);
4387 for (result = dns_rdataset_first(chase_nsrdataset);
4388 result == ISC_R_SUCCESS;
4389 result = dns_rdataset_next(chase_nsrdataset)) {
4390 char namestr[DNS_NAME_FORMATSIZE];
4392 dns_rdata_t rdata = DNS_RDATA_INIT;
4393 dig_server_t * srv = NULL;
4394 #define __FOLLOW_GLUE__
4395 #ifdef __FOLLOW_GLUE__
4396 isc_buffer_t *b = NULL;
4397 isc_result_t result;
4399 dns_rdataset_t *rdataset = NULL;
4400 isc_boolean_t true = ISC_TRUE;
4403 memset(namestr, 0, DNS_NAME_FORMATSIZE);
4405 dns_rdataset_current(chase_nsrdataset, &rdata);
4407 result = dns_rdata_tostruct(&rdata, &ns, NULL);
4408 check_result(result, "dns_rdata_tostruct");
4410 #ifdef __FOLLOW_GLUE__
4412 result = advanced_rrsearch(&rdataset, &ns.name,
4414 dns_rdatatype_any, &true);
4415 if (result == ISC_R_SUCCESS) {
4416 for (result = dns_rdataset_first(rdataset);
4417 result == ISC_R_SUCCESS;
4418 result = dns_rdataset_next(rdataset)) {
4419 dns_rdata_t aaaa = DNS_RDATA_INIT;
4420 dns_rdataset_current(rdataset, &aaaa);
4422 result = isc_buffer_allocate(mctx, &b, 80);
4423 check_result(result, "isc_buffer_allocate");
4425 dns_rdata_totext(&aaaa, &ns.name, b);
4426 isc_buffer_usedregion(b, &r);
4427 r.base[r.length] = '\0';
4428 strlcpy(namestr, (char*)r.base,
4429 DNS_NAME_FORMATSIZE);
4430 isc_buffer_free(&b);
4431 dns_rdata_reset(&aaaa);
4434 srv = make_server(namestr, namestr);
4436 ISC_LIST_APPEND(lookup->my_server_list,
4442 result = advanced_rrsearch(&rdataset, &ns.name, dns_rdatatype_a,
4443 dns_rdatatype_any, &true);
4444 if (result == ISC_R_SUCCESS) {
4445 for (result = dns_rdataset_first(rdataset);
4446 result == ISC_R_SUCCESS;
4447 result = dns_rdataset_next(rdataset)) {
4448 dns_rdata_t a = DNS_RDATA_INIT;
4449 dns_rdataset_current(rdataset, &a);
4451 result = isc_buffer_allocate(mctx, &b, 80);
4452 check_result(result, "isc_buffer_allocate");
4454 dns_rdata_totext(&a, &ns.name, b);
4455 isc_buffer_usedregion(b, &r);
4456 r.base[r.length] = '\0';
4457 strlcpy(namestr, (char*)r.base,
4458 DNS_NAME_FORMATSIZE);
4459 isc_buffer_free(&b);
4460 dns_rdata_reset(&a);
4461 printf("ns name: %s\n", namestr);
4464 srv = make_server(namestr, namestr);
4466 ISC_LIST_APPEND(lookup->my_server_list,
4472 dns_name_format(&ns.name, namestr, sizeof(namestr));
4473 printf("ns name: ");
4474 dns_name_print(&ns.name, stdout);
4476 srv = make_server(namestr, namestr);
4478 ISC_LIST_APPEND(lookup->my_server_list, srv, link);
4481 dns_rdata_freestruct(&ns);
4482 dns_rdata_reset(&rdata);
4486 ISC_LIST_APPEND(lookup_list, lookup, link);
4487 printf("\nLaunch a query to find a RRset of type ");
4488 print_type(lookup->rdtype);
4489 printf(" for zone: %s", lookup->textname);
4490 printf(" with nameservers:");
4492 print_rdataset(name, chase_nsrdataset, mctx);
4493 return (ISC_R_SUCCESS);
4498 child_of_zone(dns_name_t * name, dns_name_t * zone_name,
4499 dns_name_t * child_name)
4501 dns_namereln_t name_reln;
4503 unsigned int nlabelsp;
4505 name_reln = dns_name_fullcompare(name, zone_name, &orderp, &nlabelsp);
4506 if (name_reln != dns_namereln_subdomain ||
4507 dns_name_countlabels(name) <= dns_name_countlabels(zone_name) + 1) {
4508 printf("\n;; ERROR : ");
4509 dns_name_print(name, stdout);
4510 printf(" is not a subdomain of: ");
4511 dns_name_print(zone_name, stdout);
4512 printf(" FAILED\n\n");
4513 return (ISC_R_FAILURE);
4516 dns_name_getlabelsequence(name,
4517 dns_name_countlabels(name) -
4518 dns_name_countlabels(zone_name) -1,
4519 dns_name_countlabels(zone_name) +1,
4521 return (ISC_R_SUCCESS);
4525 grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t *sigrdataset)
4527 isc_result_t result;
4528 dns_rdata_t sigrdata = DNS_RDATA_INIT;
4529 dns_rdata_sig_t siginfo;
4531 result = dns_rdataset_first(sigrdataset);
4532 check_result(result, "empty RRSIG dataset");
4533 dns_rdata_init(&sigrdata);
4536 dns_rdataset_current(sigrdataset, &sigrdata);
4538 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4539 check_result(result, "sigrdata tostruct siginfo");
4541 if (dns_name_compare(&siginfo.signer, zone_name) == 0) {
4542 dns_rdata_freestruct(&siginfo);
4543 dns_rdata_reset(&sigrdata);
4544 return (ISC_R_SUCCESS);
4547 dns_rdata_freestruct(&siginfo);
4548 dns_rdata_reset(&sigrdata);
4550 } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
4552 dns_rdata_reset(&sigrdata);
4554 return (ISC_R_FAILURE);
4559 initialization(dns_name_t *name)
4561 isc_result_t result;
4562 isc_boolean_t true = ISC_TRUE;
4564 chase_nsrdataset = NULL;
4565 result = advanced_rrsearch(&chase_nsrdataset, name, dns_rdatatype_ns,
4566 dns_rdatatype_any, &true);
4567 if (result != ISC_R_SUCCESS) {
4568 printf("\n;; NS RRset is missing to continue validation:"
4570 return (ISC_R_FAILURE);
4572 INSIST(chase_nsrdataset != NULL);
4573 prepare_lookup(name);
4575 dup_name(name, &chase_current_name, mctx);
4577 return (ISC_R_SUCCESS);
4582 print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset, isc_mem_t *mctx)
4584 isc_buffer_t *b = NULL;
4585 isc_result_t result;
4588 result = isc_buffer_allocate(mctx, &b, 9000);
4589 check_result(result, "isc_buffer_allocate");
4591 printrdataset(name, rdataset, b);
4593 isc_buffer_usedregion(b, &r);
4594 r.base[r.length] = '\0';
4597 printf("%s\n", r.base);
4599 isc_buffer_free(&b);
4604 dup_name(dns_name_t *source, dns_name_t *target, isc_mem_t *mctx) {
4605 isc_result_t result;
4607 if (dns_name_dynamic(target))
4608 free_name(target, mctx);
4609 result = dns_name_dup(source, mctx, target);
4610 check_result(result, "dns_name_dup");
4614 free_name(dns_name_t *name, isc_mem_t *mctx) {
4615 dns_name_free(name, mctx);
4616 dns_name_init(name, NULL);
4621 * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter
4622 * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key
4623 * and the RRset is valid
4624 * return ISC_R_NOTFOUND if not contains trusted key
4625 or if the RRset isn't valid
4626 * return ISC_R_FAILURE if problem
4630 contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset,
4631 dns_rdataset_t *sigrdataset,
4634 isc_result_t result;
4635 dns_rdata_t rdata = DNS_RDATA_INIT;
4636 dst_key_t *dnsseckey = NULL;
4639 if (name == NULL || rdataset == NULL)
4640 return (ISC_R_FAILURE);
4642 result = dns_rdataset_first(rdataset);
4643 check_result(result, "empty rdataset");
4646 dns_rdataset_current(rdataset, &rdata);
4647 INSIST(rdata.type == dns_rdatatype_dnskey);
4649 result = dns_dnssec_keyfromrdata(name, &rdata,
4651 check_result(result, "dns_dnssec_keyfromrdata");
4654 for (i = 0; i < tk_list.nb_tk; i++) {
4655 if (dst_key_compare(tk_list.key[i], dnsseckey)
4657 dns_rdata_reset(&rdata);
4659 printf(";; Ok, find a Trusted Key in the "
4660 "DNSKEY RRset: %d\n",
4661 dst_key_id(dnsseckey));
4662 if (sigchase_verify_sig_key(name, rdataset,
4667 dst_key_free(&dnsseckey);
4669 return (ISC_R_SUCCESS);
4674 dns_rdata_reset(&rdata);
4675 if (dnsseckey != NULL)
4676 dst_key_free(&dnsseckey);
4677 } while (dns_rdataset_next(rdataset) == ISC_R_SUCCESS);
4679 return (ISC_R_NOTFOUND);
4683 sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset,
4684 dns_rdataset_t *keyrdataset,
4685 dns_rdataset_t *sigrdataset,
4688 isc_result_t result;
4689 dns_rdata_t keyrdata = DNS_RDATA_INIT;
4690 dst_key_t *dnsseckey = NULL;
4692 result = dns_rdataset_first(keyrdataset);
4693 check_result(result, "empty DNSKEY dataset");
4694 dns_rdata_init(&keyrdata);
4697 dns_rdataset_current(keyrdataset, &keyrdata);
4698 INSIST(keyrdata.type == dns_rdatatype_dnskey);
4700 result = dns_dnssec_keyfromrdata(name, &keyrdata,
4702 check_result(result, "dns_dnssec_keyfromrdata");
4704 result = sigchase_verify_sig_key(name, rdataset, dnsseckey,
4706 if (result == ISC_R_SUCCESS) {
4707 dns_rdata_reset(&keyrdata);
4708 dst_key_free(&dnsseckey);
4709 return (ISC_R_SUCCESS);
4711 dst_key_free(&dnsseckey);
4712 dns_rdata_reset(&keyrdata);
4713 } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
4715 dns_rdata_reset(&keyrdata);
4717 return (ISC_R_NOTFOUND);
4721 sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset,
4722 dst_key_t *dnsseckey, dns_rdataset_t *sigrdataset,
4725 isc_result_t result;
4726 dns_rdata_t sigrdata = DNS_RDATA_INIT;
4727 dns_rdata_sig_t siginfo;
4729 result = dns_rdataset_first(sigrdataset);
4730 check_result(result, "empty RRSIG dataset");
4731 dns_rdata_init(&sigrdata);
4734 dns_rdataset_current(sigrdataset, &sigrdata);
4736 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4737 check_result(result, "sigrdata tostruct siginfo");
4740 * Test if the id of the DNSKEY is
4741 * the id of the DNSKEY signer's
4743 if (siginfo.keyid == dst_key_id(dnsseckey)) {
4745 result = dns_rdataset_first(rdataset);
4746 check_result(result, "empty DS dataset");
4748 result = dns_dnssec_verify(name, rdataset, dnsseckey,
4749 ISC_FALSE, mctx, &sigrdata);
4751 printf(";; VERIFYING ");
4752 print_type(rdataset->type);
4753 printf(" RRset for ");
4754 dns_name_print(name, stdout);
4755 printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey),
4756 isc_result_totext(result));
4758 if (result == ISC_R_SUCCESS) {
4759 dns_rdata_reset(&sigrdata);
4763 dns_rdata_freestruct(&siginfo);
4764 dns_rdata_reset(&sigrdata);
4766 } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
4768 dns_rdata_reset(&sigrdata);
4770 return (ISC_R_NOTFOUND);
4775 sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset,
4776 dns_rdataset_t *dsrdataset, isc_mem_t *mctx)
4778 isc_result_t result;
4779 dns_rdata_t keyrdata = DNS_RDATA_INIT;
4780 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
4781 dns_rdata_t dsrdata = DNS_RDATA_INIT;
4782 dns_rdata_ds_t dsinfo;
4783 dst_key_t *dnsseckey = NULL;
4784 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
4786 result = dns_rdataset_first(dsrdataset);
4787 check_result(result, "empty DSset dataset");
4789 dns_rdataset_current(dsrdataset, &dsrdata);
4791 result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL);
4792 check_result(result, "dns_rdata_tostruct for DS");
4794 result = dns_rdataset_first(keyrdataset);
4795 check_result(result, "empty KEY dataset");
4798 dns_rdataset_current(keyrdataset, &keyrdata);
4799 INSIST(keyrdata.type == dns_rdatatype_dnskey);
4801 result = dns_dnssec_keyfromrdata(name, &keyrdata,
4803 check_result(result, "dns_dnssec_keyfromrdata");
4806 * Test if the id of the DNSKEY is the
4807 * id of DNSKEY referenced by the DS
4809 if (dsinfo.key_tag == dst_key_id(dnsseckey)) {
4811 result = dns_ds_buildrdata(name, &keyrdata,
4813 dsbuf, &newdsrdata);
4814 dns_rdata_freestruct(&dsinfo);
4816 if (result != ISC_R_SUCCESS) {
4817 dns_rdata_reset(&keyrdata);
4818 dns_rdata_reset(&newdsrdata);
4819 dns_rdata_reset(&dsrdata);
4820 dst_key_free(&dnsseckey);
4821 dns_rdata_freestruct(&dsinfo);
4822 printf("Oops: impossible to build"
4828 if (dns_rdata_compare(&dsrdata,
4829 &newdsrdata) == 0) {
4830 printf(";; OK a DS valids a DNSKEY"
4832 printf(";; Now verify that this"
4833 " DNSKEY validates the "
4836 result = sigchase_verify_sig_key(name,
4839 chase_sigkeyrdataset,
4841 if (result == ISC_R_SUCCESS) {
4842 dns_rdata_reset(&keyrdata);
4843 dns_rdata_reset(&newdsrdata);
4844 dns_rdata_reset(&dsrdata);
4845 dst_key_free(&dnsseckey);
4850 printf(";; This DS is NOT the DS for"
4851 " the chasing KEY: FAILED\n");
4854 dns_rdata_reset(&newdsrdata);
4856 dst_key_free(&dnsseckey);
4857 dns_rdata_reset(&keyrdata);
4859 } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
4860 dns_rdata_reset(&dsrdata);
4862 } while (dns_rdataset_next(chase_dsrdataset) == ISC_R_SUCCESS);
4864 dns_rdata_reset(&keyrdata);
4865 dns_rdata_reset(&newdsrdata);
4866 dns_rdata_reset(&dsrdata);
4868 return (ISC_R_NOTFOUND);
4873 * take a pointer on a rdataset in parameter and try to resolv it.
4874 * the searched rrset is a rrset on 'name' with type 'type'
4875 * (and if the type is a rrsig the signature cover 'covers').
4876 * the lookedup is to known if you have already done the query on the net.
4877 * ISC_R_SUCCESS: if we found the rrset
4878 * ISC_R_NOTFOUND: we do not found the rrset in cache
4879 * and we do a query on the net
4880 * ISC_R_FAILURE: rrset not found
4883 advanced_rrsearch(dns_rdataset_t **rdataset, dns_name_t *name,
4884 dns_rdatatype_t type, dns_rdatatype_t covers,
4885 isc_boolean_t *lookedup)
4887 isc_boolean_t tmplookedup;
4889 INSIST(rdataset != NULL);
4891 if (*rdataset != NULL)
4892 return (ISC_R_SUCCESS);
4894 tmplookedup = *lookedup;
4895 if ((*rdataset = sigchase_scanname(type, covers,
4896 lookedup, name)) == NULL) {
4898 return (ISC_R_FAILURE);
4899 return (ISC_R_NOTFOUND);
4901 *lookedup = ISC_FALSE;
4902 return (ISC_R_SUCCESS);
4909 sigchase_td(dns_message_t *msg)
4911 isc_result_t result;
4912 dns_name_t *name = NULL;
4913 isc_boolean_t have_answer = ISC_FALSE;
4914 isc_boolean_t true = ISC_TRUE;
4916 if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
4918 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
4919 if (current_lookup->trace_root_sigchase) {
4920 initialization(name);
4925 if (!current_lookup->trace_root_sigchase) {
4926 result = dns_message_firstname(msg,
4927 DNS_SECTION_AUTHORITY);
4928 if (result == ISC_R_SUCCESS)
4929 dns_message_currentname(msg,
4930 DNS_SECTION_AUTHORITY,
4933 = chase_scanname_section(msg, name,
4936 DNS_SECTION_AUTHORITY);
4937 dup_name(name, &chase_authority_name, mctx);
4938 if (chase_nsrdataset != NULL) {
4939 have_delegation_ns = ISC_TRUE;
4940 printf("no response but there is a delegation"
4941 " in authority section:");
4942 dns_name_print(name, stdout);
4945 printf("no response and no delegation in "
4946 "authority section but a reference"
4948 dns_name_print(name, stdout);
4950 error_message = msg;
4953 printf(";; NO ANSWERS: %s\n",
4954 isc_result_totext(result));
4955 free_name(&chase_name, mctx);
4964 = chase_scanname_section(msg, &chase_name,
4968 DNS_SECTION_ANSWER);
4969 if (chase_rdataset != NULL)
4970 have_response = ISC_TRUE;
4973 result = advanced_rrsearch(&chase_keyrdataset,
4974 &chase_current_name,
4975 dns_rdatatype_dnskey,
4977 &chase_keylookedup);
4978 if (result == ISC_R_FAILURE) {
4979 printf("\n;; DNSKEY is missing to continue validation:"
4983 if (result == ISC_R_NOTFOUND)
4985 INSIST(chase_keyrdataset != NULL);
4986 printf("\n;; DNSKEYset:\n");
4987 print_rdataset(&chase_current_name , chase_keyrdataset, mctx);
4990 result = advanced_rrsearch(&chase_sigkeyrdataset,
4991 &chase_current_name,
4992 dns_rdatatype_rrsig,
4993 dns_rdatatype_dnskey,
4994 &chase_sigkeylookedup);
4995 if (result == ISC_R_FAILURE) {
4996 printf("\n;; RRSIG of DNSKEY is missing to continue validation:"
5000 if (result == ISC_R_NOTFOUND)
5002 INSIST(chase_sigkeyrdataset != NULL);
5003 printf("\n;; RRSIG of the DNSKEYset:\n");
5004 print_rdataset(&chase_current_name , chase_sigkeyrdataset, mctx);
5007 if (!chase_dslookedup && !chase_nslookedup) {
5008 if (!delegation_follow) {
5009 result = contains_trusted_key(&chase_current_name,
5011 chase_sigkeyrdataset,
5014 INSIST(chase_dsrdataset != NULL);
5015 INSIST(chase_sigdsrdataset != NULL);
5016 result = sigchase_verify_ds(&chase_current_name,
5022 if (result != ISC_R_SUCCESS) {
5023 printf("\n;; chain of trust can't be validated:"
5027 chase_dsrdataset = NULL;
5028 chase_sigdsrdataset = NULL;
5032 if (have_response || (!have_delegation_ns && !have_response)) {
5033 /* test if it's a grand father case */
5035 if (have_response) {
5036 result = advanced_rrsearch(&chase_sigrdataset,
5038 dns_rdatatype_rrsig,
5042 if (result == ISC_R_FAILURE) {
5043 printf("\n;; RRset is missing to continue"
5044 " validation SHOULD NOT APPEND:"
5050 result = advanced_rrsearch(&chase_sigrdataset,
5051 &chase_authority_name,
5052 dns_rdatatype_rrsig,
5055 if (result == ISC_R_FAILURE) {
5056 printf("\n;; RRSIG is missing to continue"
5057 " validation SHOULD NOT APPEND:"
5062 result = grandfather_pb_test(&chase_current_name,
5064 if (result != ISC_R_SUCCESS) {
5065 dns_name_t tmp_name;
5067 printf("\n;; We are in a Grand Father Problem:"
5068 " See 2.2.1 in RFC 3568\n");
5069 chase_rdataset = NULL;
5070 chase_sigrdataset = NULL;
5071 have_response = ISC_FALSE;
5072 have_delegation_ns = ISC_FALSE;
5074 dns_name_init(&tmp_name, NULL);
5075 result = child_of_zone(&chase_name, &chase_current_name,
5077 if (dns_name_dynamic(&chase_authority_name))
5078 free_name(&chase_authority_name, mctx);
5079 dup_name(&tmp_name, &chase_authority_name, mctx);
5080 printf(";; and we try to continue chain of trust"
5081 " validation of the zone: ");
5082 dns_name_print(&chase_authority_name, stdout);
5084 have_delegation_ns = ISC_TRUE;
5089 chase_sigrdataset = NULL;
5093 if (have_delegation_ns) {
5094 chase_nsrdataset = NULL;
5095 result = advanced_rrsearch(&chase_nsrdataset,
5096 &chase_authority_name,
5100 if (result == ISC_R_FAILURE) {
5101 printf("\n;;NSset is missing to continue validation:"
5105 if (result == ISC_R_NOTFOUND) {
5108 INSIST(chase_nsrdataset != NULL);
5110 result = advanced_rrsearch(&chase_dsrdataset,
5111 &chase_authority_name,
5115 if (result == ISC_R_FAILURE) {
5116 printf("\n;; DSset is missing to continue validation:"
5120 if (result == ISC_R_NOTFOUND)
5122 INSIST(chase_dsrdataset != NULL);
5123 printf("\n;; DSset:\n");
5124 print_rdataset(&chase_authority_name , chase_dsrdataset, mctx);
5126 result = advanced_rrsearch(&chase_sigdsrdataset,
5127 &chase_authority_name,
5128 dns_rdatatype_rrsig,
5131 if (result != ISC_R_SUCCESS) {
5132 printf("\n;; DSset is missing to continue validation:"
5136 printf("\n;; RRSIGset of DSset\n");
5137 print_rdataset(&chase_authority_name,
5138 chase_sigdsrdataset, mctx);
5139 INSIST(chase_sigdsrdataset != NULL);
5141 result = sigchase_verify_sig(&chase_authority_name,
5144 chase_sigdsrdataset, mctx);
5145 if (result != ISC_R_SUCCESS) {
5146 printf("\n;; Impossible to verify the DSset:"
5150 chase_keyrdataset = NULL;
5151 chase_sigkeyrdataset = NULL;
5154 prepare_lookup(&chase_authority_name);
5156 have_response = ISC_FALSE;
5157 have_delegation_ns = ISC_FALSE;
5158 delegation_follow = ISC_TRUE;
5159 error_message = NULL;
5160 dup_name(&chase_authority_name, &chase_current_name, mctx);
5161 free_name(&chase_authority_name, mctx);
5166 if (error_message != NULL) {
5167 dns_rdataset_t *rdataset;
5168 dns_rdataset_t *sigrdataset;
5169 dns_name_t rdata_name;
5170 isc_result_t ret = ISC_R_FAILURE;
5172 dns_name_init(&rdata_name, NULL);
5173 result = prove_nx(error_message, &chase_name,
5174 current_lookup->rdclass_sigchase,
5175 current_lookup->rdtype_sigchase, &rdata_name,
5176 &rdataset, &sigrdataset);
5177 if (rdataset == NULL || sigrdataset == NULL ||
5178 dns_name_countlabels(&rdata_name) == 0) {
5179 printf("\n;; Impossible to verify the non-existence,"
5180 " the NSEC RRset can't be validated:"
5184 ret = sigchase_verify_sig(&rdata_name, rdataset,
5187 if (ret != ISC_R_SUCCESS) {
5188 free_name(&rdata_name, mctx);
5189 printf("\n;; Impossible to verify the NSEC RR to prove"
5190 " the non-existence : FAILED\n\n");
5193 free_name(&rdata_name, mctx);
5194 if (result != ISC_R_SUCCESS) {
5195 printf("\n;; Impossible to verify the non-existence:"
5199 printf("\n;; OK the query doesn't have response but"
5200 " we have validate this fact : SUCCESS\n\n");
5206 printf(";; cleanandgo \n");
5207 if (dns_name_dynamic(&chase_current_name))
5208 free_name(&chase_current_name, mctx);
5209 if (dns_name_dynamic(&chase_authority_name))
5210 free_name(&chase_authority_name, mctx);
5215 result = advanced_rrsearch(&chase_rdataset, &chase_name,
5216 current_lookup->rdtype_sigchase,
5219 if (result == ISC_R_FAILURE) {
5220 printf("\n;; RRsig of RRset is missing to continue validation"
5221 " SHOULD NOT APPEND: FAILED\n\n");
5224 result = sigchase_verify_sig(&chase_name, chase_rdataset,
5226 chase_sigrdataset, mctx);
5227 if (result != ISC_R_SUCCESS) {
5228 printf("\n;; Impossible to verify the RRset : FAILED\n\n");
5231 print_rdataset(&chase_name , chase_rdataset, mctx);
5232 printf("DNSKEYset:\n");
5233 print_rdataset(&chase_name , chase_keyrdataset, mctx);
5234 printf("RRSIG of RRset:\n");
5235 print_rdataset(&chase_name , chase_sigrdataset, mctx);
5240 printf("\n;; The Answer:\n");
5241 print_rdataset(&chase_name , chase_rdataset, mctx);
5243 printf("\n;; FINISH : we have validate the DNSSEC chain"
5244 " of trust: SUCCESS\n\n");
5255 getneededrr(dns_message_t *msg)
5257 isc_result_t result;
5258 dns_name_t *name = NULL;
5259 dns_rdata_t sigrdata = DNS_RDATA_INIT;
5260 dns_rdata_sig_t siginfo;
5261 isc_boolean_t true = ISC_TRUE;
5263 if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
5265 printf(";; NO ANSWERS: %s\n", isc_result_totext(result));
5267 if (chase_name.ndata == NULL)
5268 return (ISC_R_ADDRNOTAVAIL);
5270 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
5273 /* What do we chase? */
5274 if (chase_rdataset == NULL) {
5275 result = advanced_rrsearch(&chase_rdataset, name,
5277 dns_rdatatype_any, &true);
5278 if (result != ISC_R_SUCCESS) {
5279 printf("\n;; No Answers: Validation FAILED\n\n");
5280 return (ISC_R_NOTFOUND);
5282 dup_name(name, &chase_name, mctx);
5283 printf(";; RRset to chase:\n");
5284 print_rdataset(&chase_name, chase_rdataset, mctx);
5286 INSIST(chase_rdataset != NULL);
5289 if (chase_sigrdataset == NULL) {
5290 result = advanced_rrsearch(&chase_sigrdataset, name,
5291 dns_rdatatype_rrsig,
5292 chase_rdataset->type,
5293 &chase_siglookedup);
5294 if (result == ISC_R_FAILURE) {
5295 printf("\n;; RRSIG is missing for continue validation:"
5297 if (dns_name_dynamic(&chase_name))
5298 free_name(&chase_name, mctx);
5299 return (ISC_R_NOTFOUND);
5301 if (result == ISC_R_NOTFOUND) {
5302 return (ISC_R_NOTFOUND);
5304 printf("\n;; RRSIG of the RRset to chase:\n");
5305 print_rdataset(&chase_name, chase_sigrdataset, mctx);
5307 INSIST(chase_sigrdataset != NULL);
5310 /* first find the DNSKEY name */
5311 result = dns_rdataset_first(chase_sigrdataset);
5312 check_result(result, "empty RRSIG dataset");
5313 dns_rdataset_current(chase_sigrdataset, &sigrdata);
5314 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
5315 check_result(result, "sigrdata tostruct siginfo");
5316 dup_name(&siginfo.signer, &chase_signame, mctx);
5317 dns_rdata_freestruct(&siginfo);
5318 dns_rdata_reset(&sigrdata);
5320 /* Do we have a key? */
5321 if (chase_keyrdataset == NULL) {
5322 result = advanced_rrsearch(&chase_keyrdataset,
5324 dns_rdatatype_dnskey,
5326 &chase_keylookedup);
5327 if (result == ISC_R_FAILURE) {
5328 printf("\n;; DNSKEY is missing to continue validation:"
5330 free_name(&chase_signame, mctx);
5331 if (dns_name_dynamic(&chase_name))
5332 free_name(&chase_name, mctx);
5333 return (ISC_R_NOTFOUND);
5335 if (result == ISC_R_NOTFOUND) {
5336 free_name(&chase_signame, mctx);
5337 return (ISC_R_NOTFOUND);
5339 printf("\n;; DNSKEYset that signs the RRset to chase:\n");
5340 print_rdataset(&chase_signame, chase_keyrdataset, mctx);
5342 INSIST(chase_keyrdataset != NULL);
5344 if (chase_sigkeyrdataset == NULL) {
5345 result = advanced_rrsearch(&chase_sigkeyrdataset,
5347 dns_rdatatype_rrsig,
5348 dns_rdatatype_dnskey,
5349 &chase_sigkeylookedup);
5350 if (result == ISC_R_FAILURE) {
5351 printf("\n;; RRSIG for DNSKEY is missing to continue"
5352 " validation : FAILED\n\n");
5353 free_name(&chase_signame, mctx);
5354 if (dns_name_dynamic(&chase_name))
5355 free_name(&chase_name, mctx);
5356 return (ISC_R_NOTFOUND);
5358 if (result == ISC_R_NOTFOUND) {
5359 free_name(&chase_signame, mctx);
5360 return (ISC_R_NOTFOUND);
5362 printf("\n;; RRSIG of the DNSKEYset that signs the "
5363 "RRset to chase:\n");
5364 print_rdataset(&chase_signame, chase_sigkeyrdataset, mctx);
5366 INSIST(chase_sigkeyrdataset != NULL);
5369 if (chase_dsrdataset == NULL) {
5370 result = advanced_rrsearch(&chase_dsrdataset, &chase_signame,
5374 if (result == ISC_R_FAILURE) {
5375 printf("\n;; WARNING There is no DS for the zone: ");
5376 dns_name_print(&chase_signame, stdout);
5379 if (result == ISC_R_NOTFOUND) {
5380 free_name(&chase_signame, mctx);
5381 return (ISC_R_NOTFOUND);
5383 if (chase_dsrdataset != NULL) {
5384 printf("\n;; DSset of the DNSKEYset\n");
5385 print_rdataset(&chase_signame, chase_dsrdataset, mctx);
5389 if (chase_dsrdataset != NULL) {
5391 * if there is no RRSIG of DS,
5392 * we don't want to search on the network
5394 result = advanced_rrsearch(&chase_sigdsrdataset,
5396 dns_rdatatype_rrsig,
5397 dns_rdatatype_ds, &true);
5398 if (result == ISC_R_FAILURE) {
5399 printf(";; WARNING : NO RRSIG DS : RRSIG DS"
5400 " should come with DS\n");
5402 * We continue even the DS couldn't be validated,
5403 * because the DNSKEY could be a Trusted Key.
5405 chase_dsrdataset = NULL;
5407 printf("\n;; RRSIG of the DSset of the DNSKEYset\n");
5408 print_rdataset(&chase_signame, chase_sigdsrdataset,
5418 sigchase_bu(dns_message_t *msg)
5420 isc_result_t result;
5423 if (tk_list.nb_tk == 0) {
5424 result = get_trusted_key(mctx);
5425 if (result != ISC_R_SUCCESS) {
5426 printf("No trusted keys present\n");
5432 ret = getneededrr(msg);
5433 if (ret == ISC_R_NOTFOUND)
5436 if (ret == ISC_R_ADDRNOTAVAIL) {
5437 /* We have no response */
5438 dns_rdataset_t *rdataset;
5439 dns_rdataset_t *sigrdataset;
5440 dns_name_t rdata_name;
5441 dns_name_t query_name;
5444 dns_name_init(&query_name, NULL);
5445 dns_name_init(&rdata_name, NULL);
5446 nameFromString(current_lookup->textname, &query_name);
5448 result = prove_nx(msg, &query_name, current_lookup->rdclass,
5449 current_lookup->rdtype, &rdata_name,
5450 &rdataset, &sigrdataset);
5451 free_name(&query_name, mctx);
5452 if (rdataset == NULL || sigrdataset == NULL ||
5453 dns_name_countlabels(&rdata_name) == 0) {
5454 printf("\n;; Impossible to verify the Non-existence,"
5455 " the NSEC RRset can't be validated: "
5461 if (result != ISC_R_SUCCESS) {
5462 printf("\n No Answers and impossible to prove the"
5463 " unsecurity : Validation FAILED\n\n");
5467 printf(";; An NSEC prove the non-existence of a answers,"
5468 " Now we want validate this NSEC\n");
5470 dup_name(&rdata_name, &chase_name, mctx);
5471 free_name(&rdata_name, mctx);
5472 chase_rdataset = rdataset;
5473 chase_sigrdataset = sigrdataset;
5474 chase_keyrdataset = NULL;
5475 chase_sigkeyrdataset = NULL;
5476 chase_dsrdataset = NULL;
5477 chase_sigdsrdataset = NULL;
5478 chase_siglookedup = ISC_FALSE;
5479 chase_keylookedup = ISC_FALSE;
5480 chase_dslookedup = ISC_FALSE;
5481 chase_sigdslookedup = ISC_FALSE;
5488 printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n");
5490 result = sigchase_verify_sig(&chase_name, chase_rdataset,
5492 chase_sigrdataset, mctx);
5493 if (result != ISC_R_SUCCESS) {
5494 free_name(&chase_name, mctx);
5495 free_name(&chase_signame, mctx);
5496 printf(";; No DNSKEY is valid to check the RRSIG"
5497 " of the RRset: FAILED\n");
5501 printf(";; OK We found DNSKEY (or more) to validate the RRset\n");
5503 result = contains_trusted_key(&chase_signame, chase_keyrdataset,
5504 chase_sigkeyrdataset, mctx);
5505 if (result == ISC_R_SUCCESS) {
5506 free_name(&chase_name, mctx);
5507 free_name(&chase_signame, mctx);
5508 printf("\n;; Ok this DNSKEY is a Trusted Key,"
5509 " DNSSEC validation is ok: SUCCESS\n\n");
5514 printf(";; Now, we are going to validate this DNSKEY by the DS\n");
5516 if (chase_dsrdataset == NULL) {
5517 free_name(&chase_name, mctx);
5518 free_name(&chase_signame, mctx);
5519 printf(";; the DNSKEY isn't trusted-key and there isn't"
5520 " DS to validate the DNSKEY: FAILED\n");
5525 result = sigchase_verify_ds(&chase_signame, chase_keyrdataset,
5526 chase_dsrdataset, mctx);
5527 if (result != ISC_R_SUCCESS) {
5528 free_name(&chase_signame, mctx);
5529 free_name(&chase_name, mctx);
5530 printf(";; ERROR no DS validates a DNSKEY in the"
5531 " DNSKEY RRset: FAILED\n");
5535 printf(";; OK this DNSKEY (validated by the DS) validates"
5536 " the RRset of the DNSKEYs, thus the DNSKEY validates"
5538 INSIST(chase_sigdsrdataset != NULL);
5540 dup_name(&chase_signame, &chase_name, mctx);
5541 free_name(&chase_signame, mctx);
5542 chase_rdataset = chase_dsrdataset;
5543 chase_sigrdataset = chase_sigdsrdataset;
5544 chase_keyrdataset = NULL;
5545 chase_sigkeyrdataset = NULL;
5546 chase_dsrdataset = NULL;
5547 chase_sigdsrdataset = NULL;
5548 chase_siglookedup = chase_keylookedup = ISC_FALSE;
5549 chase_dslookedup = chase_sigdslookedup = ISC_FALSE;
5551 printf(";; Now, we want to validate the DS : recursive call\n");
5558 sigchase(dns_message_t *msg) {
5560 if (current_lookup->do_topdown) {
5573 * return 1 if name1 < name2
5574 * 0 if name1 == name2
5575 * -1 if name1 > name2
5579 inf_name(dns_name_t *name1, dns_name_t *name2)
5583 unsigned int nblabel1;
5584 unsigned int nblabel2;
5589 nblabel1 = dns_name_countlabels(name1);
5590 nblabel2 = dns_name_countlabels(name2);
5592 if (nblabel1 >= nblabel2)
5593 min_lum_label = nblabel2;
5595 min_lum_label = nblabel1;
5598 for (i=1 ; i < min_lum_label; i++) {
5599 dns_name_getlabel(name1, nblabel1 -1 - i, &label1);
5600 dns_name_getlabel(name2, nblabel2 -1 - i, &label2);
5601 if ((ret = isc_region_compare(&label1, &label2)) != 0) {
5608 if (nblabel1 == nblabel2)
5611 if (nblabel1 < nblabel2)
5623 prove_nx_domain(dns_message_t *msg,
5625 dns_name_t *rdata_name,
5626 dns_rdataset_t **rdataset,
5627 dns_rdataset_t **sigrdataset)
5629 isc_result_t ret = ISC_R_FAILURE;
5630 isc_result_t result = ISC_R_NOTFOUND;
5631 dns_rdataset_t *nsecset = NULL;
5632 dns_rdataset_t *signsecset = NULL ;
5633 dns_rdata_t nsec = DNS_RDATA_INIT;
5634 dns_name_t *nsecname;
5635 dns_rdata_nsec_t nsecstruct;
5637 if ((result = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
5639 printf(";; nothing in authority section : impossible to"
5640 " validate the non-existence : FAILED\n");
5641 return (ISC_R_FAILURE);
5646 dns_message_currentname(msg, DNS_SECTION_AUTHORITY, &nsecname);
5647 nsecset = search_type(nsecname, dns_rdatatype_nsec,
5649 if (nsecset == NULL)
5652 printf("There is a NSEC for this zone in the"
5653 " AUTHORITY section:\n");
5654 print_rdataset(nsecname, nsecset, mctx);
5656 for (result = dns_rdataset_first(nsecset);
5657 result == ISC_R_SUCCESS;
5658 result = dns_rdataset_next(nsecset)) {
5659 dns_rdataset_current(nsecset, &nsec);
5663 = chase_scanname_section(msg, nsecname,
5664 dns_rdatatype_rrsig,
5666 DNS_SECTION_AUTHORITY);
5667 if (signsecset == NULL) {
5668 printf(";; no RRSIG NSEC in authority section:"
5669 " impossible to validate the "
5670 "non-existence: FAILED\n");
5671 return (ISC_R_FAILURE);
5674 ret = dns_rdata_tostruct(&nsec, &nsecstruct, NULL);
5675 check_result(ret,"dns_rdata_tostruct");
5677 if ((inf_name(nsecname, &nsecstruct.next) == 1 &&
5678 inf_name(name, &nsecstruct.next) == 1) ||
5679 (inf_name(name, nsecname) == 1 &&
5680 inf_name(&nsecstruct.next, name) == 1)) {
5681 dns_rdata_freestruct(&nsecstruct);
5682 *rdataset = nsecset;
5683 *sigrdataset = signsecset;
5684 dup_name(nsecname, rdata_name, mctx);
5686 return (ISC_R_SUCCESS);
5689 dns_rdata_freestruct(&nsecstruct);
5690 dns_rdata_reset(&nsec);
5692 } while (dns_message_nextname(msg, DNS_SECTION_AUTHORITY)
5696 *sigrdataset = NULL;
5698 return (ISC_R_FAILURE);
5709 prove_nx_type(dns_message_t *msg, dns_name_t *name, dns_rdataset_t *nsecset,
5710 dns_rdataclass_t class, dns_rdatatype_t type,
5711 dns_name_t *rdata_name, dns_rdataset_t **rdataset,
5712 dns_rdataset_t **sigrdataset)
5715 dns_rdataset_t *signsecset;
5716 dns_rdata_t nsec = DNS_RDATA_INIT;
5720 ret = dns_rdataset_first(nsecset);
5721 check_result(ret,"dns_rdataset_first");
5723 dns_rdataset_current(nsecset, &nsec);
5725 ret = dns_nsec_typepresent(&nsec, type);
5726 if (ret == ISC_R_SUCCESS)
5727 printf("OK the NSEC said that the type doesn't exist \n");
5729 signsecset = chase_scanname_section(msg, name,
5730 dns_rdatatype_rrsig,
5732 DNS_SECTION_AUTHORITY);
5733 if (signsecset == NULL) {
5734 printf("There isn't RRSIG NSEC for the zone \n");
5735 return (ISC_R_FAILURE);
5737 dup_name(name, rdata_name, mctx);
5738 *rdataset = nsecset;
5739 *sigrdataset = signsecset;
5751 prove_nx(dns_message_t *msg, dns_name_t *name, dns_rdataclass_t class,
5752 dns_rdatatype_t type, dns_name_t *rdata_name,
5753 dns_rdataset_t **rdataset, dns_rdataset_t **sigrdataset)
5756 dns_rdataset_t *nsecset = NULL;
5758 printf("We want to prove the non-existence of a type of rdata %d"
5759 " or of the zone: \n", type);
5761 if ((ret = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
5763 printf(";; nothing in authority section : impossible to"
5764 " validate the non-existence : FAILED\n");
5765 return (ISC_R_FAILURE);
5768 nsecset = chase_scanname_section(msg, name, dns_rdatatype_nsec,
5770 DNS_SECTION_AUTHORITY);
5771 if (nsecset != NULL) {
5772 printf("We have a NSEC for this zone :OK\n");
5773 ret = prove_nx_type(msg, name, nsecset, class,
5774 type, rdata_name, rdataset,
5776 if (ret != ISC_R_SUCCESS) {
5777 printf("prove_nx: ERROR type exist\n");
5780 printf("prove_nx: OK type does not exist\n");
5781 return (ISC_R_SUCCESS);
5784 printf("there is no NSEC for this zone: validating "
5785 "that the zone doesn't exist\n");
5786 ret = prove_nx_domain(msg, name, rdata_name,
5787 rdataset, sigrdataset);
5790 /* Never get here */