2 * Copyright (C) 2004-2009 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.304.12.16 2009/06/24 03:42:32 marka Exp $ */
22 * Notice to programmers: Do not use this code as an example of how to
23 * use the ISC library to perform DNS lookups. Dig and Host both operate
24 * on the request level, since they allow fine-tuning of output and are
25 * intended as debugging tools. As a result, they perform many of the
26 * functions which could be better handled using the dns_resolver
27 * functions in most applications.
41 #include <idn/result.h>
43 #include <idn/resconf.h>
47 #include <dns/byaddr.h>
49 #include <dns/dnssec.h>
52 #include <isc/random.h>
55 #include <dns/fixedname.h>
56 #include <dns/message.h>
58 #include <dns/rdata.h>
59 #include <dns/rdataclass.h>
60 #include <dns/rdatalist.h>
61 #include <dns/rdataset.h>
62 #include <dns/rdatastruct.h>
63 #include <dns/rdatatype.h>
64 #include <dns/result.h>
70 #include <isc/base64.h>
71 #include <isc/entropy.h>
74 #include <isc/netaddr.h>
76 #include <isc/netdb.h>
78 #include <isc/print.h>
79 #include <isc/random.h>
80 #include <isc/result.h>
81 #include <isc/string.h>
83 #include <isc/timer.h>
84 #include <isc/types.h>
87 #include <lwres/lwres.h>
88 #include <lwres/net.h>
90 #include <bind9/getaddresses.h>
94 #if ! defined(NS_INADDRSZ)
98 #if ! defined(NS_IN6ADDRSZ)
99 #define NS_IN6ADDRSZ 16
102 static lwres_context_t
*lwctx
= NULL
;
103 static lwres_conf_t
*lwconf
;
105 dig_lookuplist_t lookup_list
;
106 dig_serverlist_t server_list
;
107 dig_searchlistlist_t search_list
;
110 check_ra
= ISC_FALSE
,
111 have_ipv4
= ISC_FALSE
,
112 have_ipv6
= ISC_FALSE
,
113 specified_source
= ISC_FALSE
,
114 free_now
= ISC_FALSE
,
115 cancel_now
= ISC_FALSE
,
116 usesearch
= ISC_FALSE
,
117 showsearch
= ISC_FALSE
,
119 is_dst_up
= ISC_FALSE
;
121 unsigned int timeout
= 0;
122 unsigned int extrabytes
;
123 isc_mem_t
*mctx
= NULL
;
124 isc_taskmgr_t
*taskmgr
= NULL
;
125 isc_task_t
*global_task
= NULL
;
126 isc_timermgr_t
*timermgr
= NULL
;
127 isc_socketmgr_t
*socketmgr
= NULL
;
128 isc_sockaddr_t bind_address
;
129 isc_sockaddr_t bind_any
;
135 int lookup_counter
= 0;
138 static void initialize_idn(void);
139 static isc_result_t
output_filter(isc_buffer_t
*buffer
,
140 unsigned int used_org
,
141 isc_boolean_t absolute
);
142 static idn_result_t
append_textname(char *name
, const char *origin
,
144 static void idn_check_result(idn_result_t r
, const char *msg
);
153 *\li 0 Everything went well, including things like NXDOMAIN
155 *\li 7 Got too many RR's or Names
156 *\li 8 Couldn't open batch file
157 *\li 9 No reply from server
158 *\li 10 Internal error
162 char keynametext
[MXNAME
];
163 char keyfile
[MXNAME
] = "";
164 char keysecret
[MXNAME
] = "";
165 dns_name_t
*hmacname
= NULL
;
166 unsigned int digestbits
= 0;
167 isc_buffer_t
*namebuf
= NULL
;
168 dns_tsigkey_t
*key
= NULL
;
169 isc_boolean_t validated
= ISC_TRUE
;
170 isc_entropy_t
*entp
= NULL
;
171 isc_mempool_t
*commctx
= NULL
;
172 isc_boolean_t debugging
= ISC_FALSE
;
173 isc_boolean_t memdebugging
= ISC_FALSE
;
174 char *progname
= NULL
;
175 isc_mutex_t lookup_lock
;
176 dig_lookup_t
*current_lookup
= NULL
;
180 isc_result_t
get_trusted_key(isc_mem_t
*mctx
);
181 dns_rdataset_t
* sigchase_scanname(dns_rdatatype_t type
,
182 dns_rdatatype_t covers
,
183 isc_boolean_t
*lookedup
,
184 dns_name_t
*rdata_name
);
185 dns_rdataset_t
* chase_scanname_section(dns_message_t
*msg
,
187 dns_rdatatype_t type
,
188 dns_rdatatype_t covers
,
190 isc_result_t
advanced_rrsearch(dns_rdataset_t
**rdataset
,
192 dns_rdatatype_t type
,
193 dns_rdatatype_t covers
,
194 isc_boolean_t
*lookedup
);
195 isc_result_t
sigchase_verify_sig_key(dns_name_t
*name
,
196 dns_rdataset_t
*rdataset
,
197 dst_key_t
* dnsseckey
,
198 dns_rdataset_t
*sigrdataset
,
200 isc_result_t
sigchase_verify_sig(dns_name_t
*name
,
201 dns_rdataset_t
*rdataset
,
202 dns_rdataset_t
*keyrdataset
,
203 dns_rdataset_t
*sigrdataset
,
205 isc_result_t
sigchase_verify_ds(dns_name_t
*name
,
206 dns_rdataset_t
*keyrdataset
,
207 dns_rdataset_t
*dsrdataset
,
209 void sigchase(dns_message_t
*msg
);
210 void print_rdata(dns_rdata_t
*rdata
, isc_mem_t
*mctx
);
211 void print_rdataset(dns_name_t
*name
,
212 dns_rdataset_t
*rdataset
, isc_mem_t
*mctx
);
213 void dup_name(dns_name_t
*source
, dns_name_t
* target
,
215 void free_name(dns_name_t
*name
, isc_mem_t
*mctx
);
216 void dump_database(void);
217 void dump_database_section(dns_message_t
*msg
, int section
);
218 dns_rdataset_t
* search_type(dns_name_t
*name
, dns_rdatatype_t type
,
219 dns_rdatatype_t covers
);
220 isc_result_t
contains_trusted_key(dns_name_t
*name
,
221 dns_rdataset_t
*rdataset
,
222 dns_rdataset_t
*sigrdataset
,
224 void print_type(dns_rdatatype_t type
);
225 isc_result_t
prove_nx_domain(dns_message_t
* msg
,
227 dns_name_t
* rdata_name
,
228 dns_rdataset_t
** rdataset
,
229 dns_rdataset_t
** sigrdataset
);
230 isc_result_t
prove_nx_type(dns_message_t
* msg
, dns_name_t
*name
,
231 dns_rdataset_t
*nsec
,
232 dns_rdataclass_t
class,
233 dns_rdatatype_t type
,
234 dns_name_t
* rdata_name
,
235 dns_rdataset_t
** rdataset
,
236 dns_rdataset_t
** sigrdataset
);
237 isc_result_t
prove_nx(dns_message_t
* msg
, dns_name_t
* name
,
238 dns_rdataclass_t
class,
239 dns_rdatatype_t type
,
240 dns_name_t
* rdata_name
,
241 dns_rdataset_t
** rdataset
,
242 dns_rdataset_t
** sigrdataset
);
243 static void nameFromString(const char *str
, dns_name_t
*p_ret
);
244 int inf_name(dns_name_t
* name1
, dns_name_t
* name2
);
245 isc_result_t
opentmpkey(isc_mem_t
*mctx
, const char *file
,
246 char **tempp
, FILE **fp
);
247 isc_result_t
removetmpkey(isc_mem_t
*mctx
, const char *file
);
248 void clean_trustedkey(void);
249 void insert_trustedkey(dst_key_t
* key
);
251 isc_result_t
getneededrr(dns_message_t
*msg
);
252 void sigchase_bottom_up(dns_message_t
*msg
);
253 void sigchase_bu(dns_message_t
*msg
);
256 isc_result_t
initialization(dns_name_t
*name
);
257 isc_result_t
prepare_lookup(dns_name_t
*name
);
258 isc_result_t
grandfather_pb_test(dns_name_t
* zone_name
,
259 dns_rdataset_t
*sigrdataset
);
260 isc_result_t
child_of_zone(dns_name_t
*name
,
261 dns_name_t
*zone_name
,
262 dns_name_t
*child_name
);
263 void sigchase_td(dns_message_t
*msg
);
265 char trustedkey
[MXNAME
] = "";
267 dns_rdataset_t
*chase_rdataset
= NULL
;
268 dns_rdataset_t
*chase_sigrdataset
= NULL
;
269 dns_rdataset_t
*chase_dsrdataset
= NULL
;
270 dns_rdataset_t
*chase_sigdsrdataset
= NULL
;
271 dns_rdataset_t
*chase_keyrdataset
= NULL
;
272 dns_rdataset_t
*chase_sigkeyrdataset
= NULL
;
273 dns_rdataset_t
*chase_nsrdataset
= NULL
;
275 dns_name_t chase_name
; /* the query name */
278 * the current name is the parent name when we follow delegation
280 dns_name_t chase_current_name
;
282 * the child name is used for delegation (NS DS responses in AUTHORITY section)
284 dns_name_t chase_authority_name
;
287 dns_name_t chase_signame
;
291 isc_boolean_t chase_siglookedup
= ISC_FALSE
;
292 isc_boolean_t chase_keylookedup
= ISC_FALSE
;
293 isc_boolean_t chase_sigkeylookedup
= ISC_FALSE
;
294 isc_boolean_t chase_dslookedup
= ISC_FALSE
;
295 isc_boolean_t chase_sigdslookedup
= ISC_FALSE
;
297 isc_boolean_t chase_nslookedup
= ISC_FALSE
;
298 isc_boolean_t chase_lookedup
= ISC_FALSE
;
301 isc_boolean_t delegation_follow
= ISC_FALSE
;
302 isc_boolean_t grandfather_pb
= ISC_FALSE
;
303 isc_boolean_t have_response
= ISC_FALSE
;
304 isc_boolean_t have_delegation_ns
= ISC_FALSE
;
305 dns_message_t
* error_message
= NULL
;
308 isc_boolean_t dsvalidating
= ISC_FALSE
;
309 isc_boolean_t chase_name_dup
= ISC_FALSE
;
311 ISC_LIST(dig_message_t
) chase_message_list
;
312 ISC_LIST(dig_message_t
) chase_message_list2
;
315 #define MAX_TRUSTED_KEY 5
316 typedef struct struct_trusted_key_list
{
317 dst_key_t
* key
[MAX_TRUSTED_KEY
];
321 struct_tk_list tk_list
= { {NULL
, NULL
, NULL
, NULL
, NULL
}, 0};
325 #define DIG_MAX_ADDRESSES 20
328 * Apply and clear locks at the event level in global task.
329 * Can I get rid of these using shutdown events? XXX
331 #define LOCK_LOOKUP {\
332 debug("lock_lookup %s:%d", __FILE__, __LINE__);\
333 check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\
336 #define UNLOCK_LOOKUP {\
337 debug("unlock_lookup %s:%d", __FILE__, __LINE__);\
338 check_result(isc_mutex_unlock((&lookup_lock)),\
339 "isc_mutex_unlock");\
343 cancel_lookup(dig_lookup_t
*lookup
);
346 recv_done(isc_task_t
*task
, isc_event_t
*event
);
349 send_udp(dig_query_t
*query
);
352 connect_timeout(isc_task_t
*task
, isc_event_t
*event
);
355 launch_next_query(dig_query_t
*query
, isc_boolean_t include_question
);
359 mem_alloc(void *arg
, size_t size
) {
360 return (isc_mem_get(arg
, size
));
364 mem_free(void *arg
, void *mem
, size_t size
) {
365 isc_mem_put(arg
, mem
, size
);
369 next_token(char **stringp
, const char *delim
) {
373 res
= strsep(stringp
, delim
);
376 } while (*res
== '\0');
381 count_dots(char *string
) {
395 hex_dump(isc_buffer_t
*b
) {
399 isc_buffer_usedregion(b
, &r
);
401 printf("%d bytes\n", r
.length
);
402 for (len
= 0; len
< r
.length
; len
++) {
403 printf("%02x ", r
.base
[len
]);
412 * Append 'len' bytes of 'text' at '*p', failing with
413 * ISC_R_NOSPACE if that would advance p past 'end'.
416 append(const char *text
, int len
, char **p
, char *end
) {
418 return (ISC_R_NOSPACE
);
419 memcpy(*p
, text
, len
);
421 return (ISC_R_SUCCESS
);
425 reverse_octets(const char *in
, char **p
, char *end
) {
426 char *dot
= strchr(in
, '.');
430 result
= reverse_octets(dot
+ 1, p
, end
);
431 if (result
!= ISC_R_SUCCESS
)
433 result
= append(".", 1, p
, end
);
434 if (result
!= ISC_R_SUCCESS
)
440 return (append(in
, len
, p
, end
));
444 get_reverse(char *reverse
, size_t len
, char *value
, isc_boolean_t ip6_int
,
445 isc_boolean_t strict
)
451 addr
.family
= AF_INET6
;
452 r
= inet_pton(AF_INET6
, value
, &addr
.type
.in6
);
454 /* This is a valid IPv6 address. */
455 dns_fixedname_t fname
;
457 unsigned int options
= 0;
460 options
|= DNS_BYADDROPT_IPV6INT
;
461 dns_fixedname_init(&fname
);
462 name
= dns_fixedname_name(&fname
);
463 result
= dns_byaddr_createptrname2(&addr
, options
, name
);
464 if (result
!= ISC_R_SUCCESS
)
466 dns_name_format(name
, reverse
, len
);
467 return (ISC_R_SUCCESS
);
470 * Not a valid IPv6 address. Assume IPv4.
471 * If 'strict' is not set, construct the
472 * in-addr.arpa name by blindly reversing
473 * octets whether or not they look like integers,
474 * so that this can be used for RFC2317 names
478 char *end
= reverse
+ len
;
479 if (strict
&& inet_pton(AF_INET
, value
, &addr
.type
.in
) != 1)
480 return (DNS_R_BADDOTTEDQUAD
);
481 result
= reverse_octets(value
, &p
, end
);
482 if (result
!= ISC_R_SUCCESS
)
484 /* Append .in-addr.arpa. and a terminating NUL. */
485 result
= append(".in-addr.arpa.", 15, &p
, end
);
486 if (result
!= ISC_R_SUCCESS
)
488 return (ISC_R_SUCCESS
);
493 fatal(const char *format
, ...) {
497 fprintf(stderr
, "%s: ", progname
);
498 va_start(args
, format
);
499 vfprintf(stderr
, format
, args
);
501 fprintf(stderr
, "\n");
505 exitcode
= fatalexit
;
510 debug(const char *format
, ...) {
515 va_start(args
, format
);
516 vfprintf(stderr
, format
, args
);
518 fprintf(stderr
, "\n");
523 check_result(isc_result_t result
, const char *msg
) {
524 if (result
!= ISC_R_SUCCESS
) {
525 fatal("%s: %s", msg
, isc_result_totext(result
));
530 * Create a server structure, which is part of the lookup structure.
531 * This is little more than a linked list of servers to query in hopes
532 * of finding the answer the user is looking for
535 make_server(const char *servname
, const char *userarg
) {
538 REQUIRE(servname
!= NULL
);
540 debug("make_server(%s)", servname
);
541 srv
= isc_mem_allocate(mctx
, sizeof(struct dig_server
));
543 fatal("memory allocation failure in %s:%d",
545 strncpy(srv
->servername
, servname
, MXNAME
);
546 strncpy(srv
->userarg
, userarg
, MXNAME
);
547 srv
->servername
[MXNAME
-1] = 0;
548 srv
->userarg
[MXNAME
-1] = 0;
549 ISC_LINK_INIT(srv
, link
);
554 addr2af(int lwresaddrtype
)
558 switch (lwresaddrtype
) {
559 case LWRES_ADDRTYPE_V4
:
563 case LWRES_ADDRTYPE_V6
:
572 * Create a copy of the server list from the lwres configuration structure.
573 * The dest list must have already had ISC_LIST_INIT applied.
576 copy_server_list(lwres_conf_t
*confdata
, dig_serverlist_t
*dest
) {
577 dig_server_t
*newsrv
;
578 char tmp
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
582 debug("copy_server_list()");
583 for (i
= 0; i
< confdata
->nsnext
; i
++) {
584 af
= addr2af(confdata
->nameservers
[i
].family
);
586 if (af
== AF_INET
&& !have_ipv4
)
588 if (af
== AF_INET6
&& !have_ipv6
)
591 lwres_net_ntop(af
, confdata
->nameservers
[i
].address
,
593 newsrv
= make_server(tmp
, tmp
);
594 ISC_LINK_INIT(newsrv
, link
);
595 ISC_LIST_ENQUEUE(*dest
, newsrv
, link
);
600 flush_server_list(void) {
601 dig_server_t
*s
, *ps
;
603 debug("flush_server_list()");
604 s
= ISC_LIST_HEAD(server_list
);
607 s
= ISC_LIST_NEXT(s
, link
);
608 ISC_LIST_DEQUEUE(server_list
, ps
, link
);
609 isc_mem_free(mctx
, ps
);
614 set_nameserver(char *opt
) {
616 isc_sockaddr_t sockaddrs
[DIG_MAX_ADDRESSES
];
617 isc_netaddr_t netaddr
;
620 char tmp
[ISC_NETADDR_FORMATSIZE
];
625 result
= bind9_getaddresses(opt
, 0, sockaddrs
,
626 DIG_MAX_ADDRESSES
, &count
);
627 if (result
!= ISC_R_SUCCESS
)
628 fatal("couldn't get address for '%s': %s",
629 opt
, isc_result_totext(result
));
633 for (i
= 0; i
< count
; i
++) {
634 isc_netaddr_fromsockaddr(&netaddr
, &sockaddrs
[i
]);
635 isc_netaddr_format(&netaddr
, tmp
, sizeof(tmp
));
636 srv
= make_server(tmp
, opt
);
638 fatal("memory allocation failure");
639 ISC_LIST_APPEND(server_list
, srv
, link
);
644 add_nameserver(lwres_conf_t
*confdata
, const char *addr
, int af
) {
646 int i
= confdata
->nsnext
;
648 if (confdata
->nsnext
>= LWRES_CONFMAXNAMESERVERS
)
649 return (ISC_R_FAILURE
);
653 confdata
->nameservers
[i
].family
= LWRES_ADDRTYPE_V4
;
654 confdata
->nameservers
[i
].length
= NS_INADDRSZ
;
657 confdata
->nameservers
[i
].family
= LWRES_ADDRTYPE_V6
;
658 confdata
->nameservers
[i
].length
= NS_IN6ADDRSZ
;
661 return (ISC_R_FAILURE
);
664 if (lwres_net_pton(af
, addr
, &confdata
->nameservers
[i
].address
) == 1) {
666 return (ISC_R_SUCCESS
);
668 return (ISC_R_FAILURE
);
672 * Produce a cloned server list. The dest list must have already had
673 * ISC_LIST_INIT applied.
676 clone_server_list(dig_serverlist_t src
, dig_serverlist_t
*dest
) {
677 dig_server_t
*srv
, *newsrv
;
679 debug("clone_server_list()");
680 srv
= ISC_LIST_HEAD(src
);
681 while (srv
!= NULL
) {
682 newsrv
= make_server(srv
->servername
, srv
->userarg
);
683 ISC_LINK_INIT(newsrv
, link
);
684 ISC_LIST_ENQUEUE(*dest
, newsrv
, link
);
685 srv
= ISC_LIST_NEXT(srv
, link
);
690 * Create an empty lookup structure, which holds all the information needed
691 * to get an answer to a user's question. This structure contains two
692 * linked lists: the server list (servers to query) and the query list
693 * (outstanding queries which have been made to the listed servers).
696 make_empty_lookup(void) {
697 dig_lookup_t
*looknew
;
699 debug("make_empty_lookup()");
703 looknew
= isc_mem_allocate(mctx
, sizeof(struct dig_lookup
));
705 fatal("memory allocation failure in %s:%d",
707 looknew
->pending
= ISC_TRUE
;
708 looknew
->textname
[0] = 0;
709 looknew
->cmdline
[0] = 0;
710 looknew
->rdtype
= dns_rdatatype_a
;
711 looknew
->qrdtype
= dns_rdatatype_a
;
712 looknew
->rdclass
= dns_rdataclass_in
;
713 looknew
->rdtypeset
= ISC_FALSE
;
714 looknew
->rdclassset
= ISC_FALSE
;
715 looknew
->sendspace
= NULL
;
716 looknew
->sendmsg
= NULL
;
717 looknew
->name
= NULL
;
718 looknew
->oname
= NULL
;
719 looknew
->timer
= NULL
;
720 looknew
->xfr_q
= NULL
;
721 looknew
->current_query
= NULL
;
722 looknew
->doing_xfr
= ISC_FALSE
;
723 looknew
->ixfr_serial
= ISC_FALSE
;
724 looknew
->trace
= ISC_FALSE
;
725 looknew
->trace_root
= ISC_FALSE
;
726 looknew
->identify
= ISC_FALSE
;
727 looknew
->identify_previous_line
= ISC_FALSE
;
728 looknew
->ignore
= ISC_FALSE
;
729 looknew
->servfail_stops
= ISC_TRUE
;
730 looknew
->besteffort
= ISC_TRUE
;
731 looknew
->dnssec
= ISC_FALSE
;
732 looknew
->nsid
= ISC_FALSE
;
734 looknew
->sigchase
= ISC_FALSE
;
736 looknew
->do_topdown
= ISC_FALSE
;
737 looknew
->trace_root_sigchase
= ISC_FALSE
;
738 looknew
->rdtype_sigchaseset
= ISC_FALSE
;
739 looknew
->rdtype_sigchase
= dns_rdatatype_any
;
740 looknew
->qrdtype_sigchase
= dns_rdatatype_any
;
741 looknew
->rdclass_sigchase
= dns_rdataclass_in
;
742 looknew
->rdclass_sigchaseset
= ISC_FALSE
;
745 looknew
->udpsize
= 0;
747 looknew
->recurse
= ISC_TRUE
;
748 looknew
->aaonly
= ISC_FALSE
;
749 looknew
->adflag
= ISC_FALSE
;
750 looknew
->cdflag
= ISC_FALSE
;
751 looknew
->ns_search_only
= ISC_FALSE
;
752 looknew
->origin
= NULL
;
753 looknew
->tsigctx
= NULL
;
754 looknew
->querysig
= NULL
;
755 looknew
->retries
= tries
;
756 looknew
->nsfound
= 0;
757 looknew
->tcp_mode
= ISC_FALSE
;
758 looknew
->ip6_int
= ISC_FALSE
;
759 looknew
->comments
= ISC_TRUE
;
760 looknew
->stats
= ISC_TRUE
;
761 looknew
->section_question
= ISC_TRUE
;
762 looknew
->section_answer
= ISC_TRUE
;
763 looknew
->section_authority
= ISC_TRUE
;
764 looknew
->section_additional
= ISC_TRUE
;
765 looknew
->new_search
= ISC_FALSE
;
766 looknew
->done_as_is
= ISC_FALSE
;
767 looknew
->need_search
= ISC_FALSE
;
768 ISC_LINK_INIT(looknew
, link
);
769 ISC_LIST_INIT(looknew
->q
);
770 ISC_LIST_INIT(looknew
->my_server_list
);
775 * Clone a lookup, perhaps copying the server list. This does not clone
776 * the query list, since it will be regenerated by the setup_lookup()
777 * function, nor does it queue up the new lookup for processing.
778 * Caution: If you don't clone the servers, you MUST clone the server
779 * list separately from somewhere else, or construct it by hand.
782 clone_lookup(dig_lookup_t
*lookold
, isc_boolean_t servers
) {
783 dig_lookup_t
*looknew
;
785 debug("clone_lookup()");
789 looknew
= make_empty_lookup();
790 INSIST(looknew
!= NULL
);
791 strncpy(looknew
->textname
, lookold
->textname
, MXNAME
);
793 strncpy(looknew
->textnamesigchase
, lookold
->textnamesigchase
, MXNAME
);
795 strncpy(looknew
->cmdline
, lookold
->cmdline
, MXNAME
);
796 looknew
->textname
[MXNAME
-1] = 0;
797 looknew
->rdtype
= lookold
->rdtype
;
798 looknew
->qrdtype
= lookold
->qrdtype
;
799 looknew
->rdclass
= lookold
->rdclass
;
800 looknew
->rdtypeset
= lookold
->rdtypeset
;
801 looknew
->rdclassset
= lookold
->rdclassset
;
802 looknew
->doing_xfr
= lookold
->doing_xfr
;
803 looknew
->ixfr_serial
= lookold
->ixfr_serial
;
804 looknew
->trace
= lookold
->trace
;
805 looknew
->trace_root
= lookold
->trace_root
;
806 looknew
->identify
= lookold
->identify
;
807 looknew
->identify_previous_line
= lookold
->identify_previous_line
;
808 looknew
->ignore
= lookold
->ignore
;
809 looknew
->servfail_stops
= lookold
->servfail_stops
;
810 looknew
->besteffort
= lookold
->besteffort
;
811 looknew
->dnssec
= lookold
->dnssec
;
812 looknew
->nsid
= lookold
->nsid
;
814 looknew
->sigchase
= lookold
->sigchase
;
816 looknew
->do_topdown
= lookold
->do_topdown
;
817 looknew
->trace_root_sigchase
= lookold
->trace_root_sigchase
;
818 looknew
->rdtype_sigchaseset
= lookold
->rdtype_sigchaseset
;
819 looknew
->rdtype_sigchase
= lookold
->rdtype_sigchase
;
820 looknew
->qrdtype_sigchase
= lookold
->qrdtype_sigchase
;
821 looknew
->rdclass_sigchase
= lookold
->rdclass_sigchase
;
822 looknew
->rdclass_sigchaseset
= lookold
->rdclass_sigchaseset
;
825 looknew
->udpsize
= lookold
->udpsize
;
826 looknew
->edns
= lookold
->edns
;
827 looknew
->recurse
= lookold
->recurse
;
828 looknew
->aaonly
= lookold
->aaonly
;
829 looknew
->adflag
= lookold
->adflag
;
830 looknew
->cdflag
= lookold
->cdflag
;
831 looknew
->ns_search_only
= lookold
->ns_search_only
;
832 looknew
->tcp_mode
= lookold
->tcp_mode
;
833 looknew
->comments
= lookold
->comments
;
834 looknew
->stats
= lookold
->stats
;
835 looknew
->section_question
= lookold
->section_question
;
836 looknew
->section_answer
= lookold
->section_answer
;
837 looknew
->section_authority
= lookold
->section_authority
;
838 looknew
->section_additional
= lookold
->section_additional
;
839 looknew
->retries
= lookold
->retries
;
840 looknew
->tsigctx
= NULL
;
841 looknew
->need_search
= lookold
->need_search
;
842 looknew
->done_as_is
= lookold
->done_as_is
;
845 clone_server_list(lookold
->my_server_list
,
846 &looknew
->my_server_list
);
851 * Requeue a lookup for further processing, perhaps copying the server
852 * list. The new lookup structure is returned to the caller, and is
853 * queued for processing. If servers are not cloned in the requeue, they
854 * must be added before allowing the current event to complete, since the
855 * completion of the event may result in the next entry on the lookup
859 requeue_lookup(dig_lookup_t
*lookold
, isc_boolean_t servers
) {
860 dig_lookup_t
*looknew
;
862 debug("requeue_lookup()");
865 if (lookup_counter
> LOOKUP_LIMIT
)
866 fatal("too many lookups");
868 looknew
= clone_lookup(lookold
, servers
);
869 INSIST(looknew
!= NULL
);
871 debug("before insertion, init@%p -> %p, new@%p -> %p",
872 lookold
, lookold
->link
.next
, looknew
, looknew
->link
.next
);
873 ISC_LIST_PREPEND(lookup_list
, looknew
, link
);
874 debug("after insertion, init -> %p, new = %p, new -> %p",
875 lookold
, looknew
, looknew
->link
.next
);
881 setup_text_key(void) {
884 isc_buffer_t secretbuf
;
886 unsigned char *secretstore
;
888 debug("setup_text_key()");
889 result
= isc_buffer_allocate(mctx
, &namebuf
, MXNAME
);
890 check_result(result
, "isc_buffer_allocate");
891 dns_name_init(&keyname
, NULL
);
892 check_result(result
, "dns_name_init");
893 isc_buffer_putstr(namebuf
, keynametext
);
894 secretsize
= strlen(keysecret
) * 3 / 4;
895 secretstore
= isc_mem_allocate(mctx
, secretsize
);
896 if (secretstore
== NULL
)
897 fatal("memory allocation failure in %s:%d",
899 isc_buffer_init(&secretbuf
, secretstore
, secretsize
);
900 result
= isc_base64_decodestring(keysecret
, &secretbuf
);
901 if (result
!= ISC_R_SUCCESS
)
904 secretsize
= isc_buffer_usedlength(&secretbuf
);
906 result
= dns_name_fromtext(&keyname
, namebuf
,
907 dns_rootname
, ISC_FALSE
,
909 if (result
!= ISC_R_SUCCESS
)
912 result
= dns_tsigkey_create(&keyname
, hmacname
, secretstore
,
913 secretsize
, ISC_FALSE
, NULL
, 0, 0, mctx
,
916 if (result
!= ISC_R_SUCCESS
)
917 printf(";; Couldn't create key %s: %s\n",
918 keynametext
, isc_result_totext(result
));
920 dst_key_setbits(key
->key
, digestbits
);
922 isc_mem_free(mctx
, secretstore
);
923 dns_name_invalidate(&keyname
);
924 isc_buffer_free(&namebuf
);
928 setup_file_key(void) {
930 dst_key_t
*dstkey
= NULL
;
932 debug("setup_file_key()");
933 result
= dst_key_fromnamedfile(keyfile
, DST_TYPE_PRIVATE
| DST_TYPE_KEY
,
935 if (result
!= ISC_R_SUCCESS
) {
936 fprintf(stderr
, "Couldn't read key from %s: %s\n",
937 keyfile
, isc_result_totext(result
));
941 switch (dst_key_alg(dstkey
)) {
942 case DST_ALG_HMACMD5
:
943 hmacname
= DNS_TSIG_HMACMD5_NAME
;
945 case DST_ALG_HMACSHA1
:
946 hmacname
= DNS_TSIG_HMACSHA1_NAME
;
948 case DST_ALG_HMACSHA224
:
949 hmacname
= DNS_TSIG_HMACSHA224_NAME
;
951 case DST_ALG_HMACSHA256
:
952 hmacname
= DNS_TSIG_HMACSHA256_NAME
;
954 case DST_ALG_HMACSHA384
:
955 hmacname
= DNS_TSIG_HMACSHA384_NAME
;
957 case DST_ALG_HMACSHA512
:
958 hmacname
= DNS_TSIG_HMACSHA512_NAME
;
961 printf(";; Couldn't create key %s: bad algorithm\n",
965 result
= dns_tsigkey_createfromkey(dst_key_name(dstkey
), hmacname
,
966 dstkey
, ISC_FALSE
, NULL
, 0, 0,
968 if (result
!= ISC_R_SUCCESS
) {
969 printf(";; Couldn't create key %s: %s\n",
970 keynametext
, isc_result_totext(result
));
976 dst_key_free(&dstkey
);
979 static dig_searchlist_t
*
980 make_searchlist_entry(char *domain
) {
981 dig_searchlist_t
*search
;
982 search
= isc_mem_allocate(mctx
, sizeof(*search
));
984 fatal("memory allocation failure in %s:%d",
986 strncpy(search
->origin
, domain
, MXNAME
);
987 search
->origin
[MXNAME
-1] = 0;
988 ISC_LINK_INIT(search
, link
);
993 create_search_list(lwres_conf_t
*confdata
) {
995 dig_searchlist_t
*search
;
997 debug("create_search_list()");
998 ISC_LIST_INIT(search_list
);
1000 for (i
= 0; i
< confdata
->searchnxt
; i
++) {
1001 search
= make_searchlist_entry(confdata
->search
[i
]);
1002 ISC_LIST_APPEND(search_list
, search
, link
);
1007 * Setup the system as a whole, reading key information and resolv.conf
1011 setup_system(void) {
1012 dig_searchlist_t
*domain
= NULL
;
1013 lwres_result_t lwresult
;
1014 unsigned int lwresflags
;
1016 debug("setup_system()");
1018 lwresflags
= LWRES_CONTEXT_SERVERMODE
;
1020 lwresflags
|= LWRES_CONTEXT_USEIPV4
;
1022 lwresflags
|= LWRES_CONTEXT_USEIPV6
;
1024 lwresult
= lwres_context_create(&lwctx
, mctx
, mem_alloc
, mem_free
,
1026 if (lwresult
!= LWRES_R_SUCCESS
)
1027 fatal("lwres_context_create failed");
1029 lwresult
= lwres_conf_parse(lwctx
, RESOLV_CONF
);
1030 if (lwresult
!= LWRES_R_SUCCESS
&& lwresult
!= LWRES_R_NOTFOUND
)
1031 fatal("parse of %s failed", RESOLV_CONF
);
1033 lwconf
= lwres_conf_get(lwctx
);
1035 /* Make the search list */
1036 if (lwconf
->searchnxt
> 0)
1037 create_search_list(lwconf
);
1038 else { /* No search list. Use the domain name if any */
1039 if (lwconf
->domainname
!= NULL
) {
1040 domain
= make_searchlist_entry(lwconf
->domainname
);
1041 ISC_LIST_INITANDAPPEND(search_list
, domain
, link
);
1047 ndots
= lwconf
->ndots
;
1048 debug("ndots is %d.", ndots
);
1051 /* If user doesn't specify server use nameservers from resolv.conf. */
1052 if (ISC_LIST_EMPTY(server_list
))
1053 copy_server_list(lwconf
, &server_list
);
1055 /* If we don't find a nameserver fall back to localhost */
1056 if (ISC_LIST_EMPTY(server_list
)) {
1058 lwresult
= add_nameserver(lwconf
, "127.0.0.1", AF_INET
);
1059 if (lwresult
!= ISC_R_SUCCESS
)
1060 fatal("add_nameserver failed");
1063 lwresult
= add_nameserver(lwconf
, "::1", AF_INET6
);
1064 if (lwresult
!= ISC_R_SUCCESS
)
1065 fatal("add_nameserver failed");
1068 copy_server_list(lwconf
, &server_list
);
1075 if (keyfile
[0] != 0)
1077 else if (keysecret
[0] != 0)
1080 /* Setup the list of messages for +sigchase */
1081 ISC_LIST_INIT(chase_message_list
);
1082 ISC_LIST_INIT(chase_message_list2
);
1083 dns_name_init(&chase_name
, NULL
);
1085 dns_name_init(&chase_current_name
, NULL
);
1086 dns_name_init(&chase_authority_name
, NULL
);
1089 dns_name_init(&chase_signame
, NULL
);
1097 clear_searchlist(void) {
1098 dig_searchlist_t
*search
;
1099 while ((search
= ISC_LIST_HEAD(search_list
)) != NULL
) {
1100 ISC_LIST_UNLINK(search_list
, search
, link
);
1101 isc_mem_free(mctx
, search
);
1106 * Override the search list derived from resolv.conf by 'domain'.
1109 set_search_domain(char *domain
) {
1110 dig_searchlist_t
*search
;
1113 search
= make_searchlist_entry(domain
);
1114 ISC_LIST_APPEND(search_list
, search
, link
);
1118 * Setup the ISC and DNS libraries for use by the system.
1122 isc_result_t result
;
1124 debug("setup_libs()");
1126 result
= isc_net_probeipv4();
1127 if (result
== ISC_R_SUCCESS
)
1128 have_ipv4
= ISC_TRUE
;
1130 result
= isc_net_probeipv6();
1131 if (result
== ISC_R_SUCCESS
)
1132 have_ipv6
= ISC_TRUE
;
1133 if (!have_ipv6
&& !have_ipv4
)
1134 fatal("can't find either v4 or v6 networking");
1136 result
= isc_mem_create(0, 0, &mctx
);
1137 check_result(result
, "isc_mem_create");
1139 result
= isc_taskmgr_create(mctx
, 1, 0, &taskmgr
);
1140 check_result(result
, "isc_taskmgr_create");
1142 result
= isc_task_create(taskmgr
, 0, &global_task
);
1143 check_result(result
, "isc_task_create");
1145 result
= isc_timermgr_create(mctx
, &timermgr
);
1146 check_result(result
, "isc_timermgr_create");
1148 result
= isc_socketmgr_create(mctx
, &socketmgr
);
1149 check_result(result
, "isc_socketmgr_create");
1151 result
= isc_entropy_create(mctx
, &entp
);
1152 check_result(result
, "isc_entropy_create");
1154 result
= dst_lib_init(mctx
, entp
, 0);
1155 check_result(result
, "dst_lib_init");
1156 is_dst_up
= ISC_TRUE
;
1158 result
= isc_mempool_create(mctx
, COMMSIZE
, &commctx
);
1159 check_result(result
, "isc_mempool_create");
1160 isc_mempool_setname(commctx
, "COMMPOOL");
1162 * 6 and 2 set as reasonable parameters for 3 or 4 nameserver
1165 isc_mempool_setfreemax(commctx
, 6);
1166 isc_mempool_setfillcount(commctx
, 2);
1168 result
= isc_mutex_init(&lookup_lock
);
1169 check_result(result
, "isc_mutex_init");
1171 dns_result_register();
1175 * Add EDNS0 option record to a message. Currently, the only supported
1176 * options are UDP buffer size, the DO bit, and NSID request.
1179 add_opt(dns_message_t
*msg
, isc_uint16_t udpsize
, isc_uint16_t edns
,
1180 isc_boolean_t dnssec
, isc_boolean_t nsid
)
1182 dns_rdataset_t
*rdataset
= NULL
;
1183 dns_rdatalist_t
*rdatalist
= NULL
;
1184 dns_rdata_t
*rdata
= NULL
;
1185 isc_result_t result
;
1188 result
= dns_message_gettemprdataset(msg
, &rdataset
);
1189 check_result(result
, "dns_message_gettemprdataset");
1190 dns_rdataset_init(rdataset
);
1191 result
= dns_message_gettemprdatalist(msg
, &rdatalist
);
1192 check_result(result
, "dns_message_gettemprdatalist");
1193 result
= dns_message_gettemprdata(msg
, &rdata
);
1194 check_result(result
, "dns_message_gettemprdata");
1196 debug("setting udp size of %d", udpsize
);
1197 rdatalist
->type
= dns_rdatatype_opt
;
1198 rdatalist
->covers
= 0;
1199 rdatalist
->rdclass
= udpsize
;
1200 rdatalist
->ttl
= edns
<< 16;
1202 rdatalist
->ttl
|= DNS_MESSAGEEXTFLAG_DO
;
1204 unsigned char data
[4];
1207 isc_buffer_init(&buf
, data
, sizeof(data
));
1208 isc_buffer_putuint16(&buf
, DNS_OPT_NSID
);
1209 isc_buffer_putuint16(&buf
, 0);
1211 rdata
->length
= sizeof(data
);
1216 ISC_LIST_INIT(rdatalist
->rdata
);
1217 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1218 dns_rdatalist_tordataset(rdatalist
, rdataset
);
1219 result
= dns_message_setopt(msg
, rdataset
);
1220 check_result(result
, "dns_message_setopt");
1224 * Add a question section to a message, asking for the specified name,
1228 add_question(dns_message_t
*message
, dns_name_t
*name
,
1229 dns_rdataclass_t rdclass
, dns_rdatatype_t rdtype
)
1231 dns_rdataset_t
*rdataset
;
1232 isc_result_t result
;
1234 debug("add_question()");
1236 result
= dns_message_gettemprdataset(message
, &rdataset
);
1237 check_result(result
, "dns_message_gettemprdataset()");
1238 dns_rdataset_init(rdataset
);
1239 dns_rdataset_makequestion(rdataset
, rdclass
, rdtype
);
1240 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1244 * Check if we're done with all the queued lookups, which is true iff
1245 * all sockets, sends, and recvs are accounted for (counters == 0),
1246 * and the lookup list is empty.
1247 * If we are done, pass control back out to dighost_shutdown() (which is
1248 * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
1249 * a whole or reseed the lookup list.
1252 check_if_done(void) {
1253 debug("check_if_done()");
1254 debug("list %s", ISC_LIST_EMPTY(lookup_list
) ? "empty" : "full");
1255 if (ISC_LIST_EMPTY(lookup_list
) && current_lookup
== NULL
&&
1257 INSIST(sockcount
== 0);
1258 INSIST(recvcount
== 0);
1259 debug("shutting down");
1265 * Clear out a query when we're done with it. WARNING: This routine
1266 * WILL invalidate the query pointer.
1269 clear_query(dig_query_t
*query
) {
1270 dig_lookup_t
*lookup
;
1272 REQUIRE(query
!= NULL
);
1274 debug("clear_query(%p)", query
);
1276 lookup
= query
->lookup
;
1278 if (lookup
->current_query
== query
)
1279 lookup
->current_query
= NULL
;
1281 ISC_LIST_UNLINK(lookup
->q
, query
, link
);
1282 if (ISC_LINK_LINKED(&query
->recvbuf
, link
))
1283 ISC_LIST_DEQUEUE(query
->recvlist
, &query
->recvbuf
,
1285 if (ISC_LINK_LINKED(&query
->lengthbuf
, link
))
1286 ISC_LIST_DEQUEUE(query
->lengthlist
, &query
->lengthbuf
,
1288 INSIST(query
->recvspace
!= NULL
);
1289 if (query
->sock
!= NULL
) {
1290 isc_socket_detach(&query
->sock
);
1292 debug("sockcount=%d", sockcount
);
1294 isc_mempool_put(commctx
, query
->recvspace
);
1295 isc_buffer_invalidate(&query
->recvbuf
);
1296 isc_buffer_invalidate(&query
->lengthbuf
);
1297 if (query
->waiting_senddone
)
1298 query
->pending_free
= ISC_TRUE
;
1300 isc_mem_free(mctx
, query
);
1304 * Try and clear out a lookup if we're done with it. Return ISC_TRUE if
1305 * the lookup was successfully cleared. If ISC_TRUE is returned, the
1306 * lookup pointer has been invalidated.
1308 static isc_boolean_t
1309 try_clear_lookup(dig_lookup_t
*lookup
) {
1312 REQUIRE(lookup
!= NULL
);
1314 debug("try_clear_lookup(%p)", lookup
);
1316 if (ISC_LIST_HEAD(lookup
->q
) != NULL
) {
1318 q
= ISC_LIST_HEAD(lookup
->q
);
1320 debug("query to %s still pending", q
->servname
);
1321 q
= ISC_LIST_NEXT(q
, link
);
1328 * At this point, we know there are no queries on the lookup,
1329 * so can make it go away also.
1331 destroy_lookup(lookup
);
1336 destroy_lookup(dig_lookup_t
*lookup
) {
1341 s
= ISC_LIST_HEAD(lookup
->my_server_list
);
1343 debug("freeing server %p belonging to %p", s
, lookup
);
1345 s
= ISC_LIST_NEXT(s
, link
);
1346 ISC_LIST_DEQUEUE(lookup
->my_server_list
,
1347 (dig_server_t
*)ptr
, link
);
1348 isc_mem_free(mctx
, ptr
);
1350 if (lookup
->sendmsg
!= NULL
)
1351 dns_message_destroy(&lookup
->sendmsg
);
1352 if (lookup
->querysig
!= NULL
) {
1353 debug("freeing buffer %p", lookup
->querysig
);
1354 isc_buffer_free(&lookup
->querysig
);
1356 if (lookup
->timer
!= NULL
)
1357 isc_timer_detach(&lookup
->timer
);
1358 if (lookup
->sendspace
!= NULL
)
1359 isc_mempool_put(commctx
, lookup
->sendspace
);
1361 if (lookup
->tsigctx
!= NULL
)
1362 dst_context_destroy(&lookup
->tsigctx
);
1364 isc_mem_free(mctx
, lookup
);
1368 * If we can, start the next lookup in the queue running.
1369 * This assumes that the lookup on the head of the queue hasn't been
1370 * started yet. It also removes the lookup from the head of the queue,
1371 * setting the current_lookup pointer pointing to it.
1374 start_lookup(void) {
1375 debug("start_lookup()");
1380 * If there's a current lookup running, we really shouldn't get
1383 INSIST(current_lookup
== NULL
);
1385 current_lookup
= ISC_LIST_HEAD(lookup_list
);
1387 * Put the current lookup somewhere so cancel_all can find it
1389 if (current_lookup
!= NULL
) {
1390 ISC_LIST_DEQUEUE(lookup_list
, current_lookup
, link
);
1392 if (current_lookup
->do_topdown
&&
1393 !current_lookup
->rdtype_sigchaseset
) {
1394 dst_key_t
*trustedkey
= NULL
;
1395 isc_buffer_t
*b
= NULL
;
1397 isc_result_t result
;
1398 dns_name_t query_name
;
1399 dns_name_t
*key_name
;
1402 result
= get_trusted_key(mctx
);
1403 if (result
!= ISC_R_SUCCESS
) {
1404 printf("\n;; No trusted key, "
1405 "+sigchase option is disabled\n");
1406 current_lookup
->sigchase
= ISC_FALSE
;
1409 dns_name_init(&query_name
, NULL
);
1410 nameFromString(current_lookup
->textname
, &query_name
);
1412 for (i
= 0; i
< tk_list
.nb_tk
; i
++) {
1413 key_name
= dst_key_name(tk_list
.key
[i
]);
1415 if (dns_name_issubdomain(&query_name
,
1416 key_name
) == ISC_TRUE
)
1417 trustedkey
= tk_list
.key
[i
];
1419 * Verify temp is really the lowest
1423 if (trustedkey
== NULL
) {
1424 printf("\n;; The queried zone: ");
1425 dns_name_print(&query_name
, stdout
);
1426 printf(" isn't a subdomain of any Trusted Keys"
1427 ": +sigchase option is disable\n");
1428 current_lookup
->sigchase
= ISC_FALSE
;
1429 free_name(&query_name
, mctx
);
1432 free_name(&query_name
, mctx
);
1434 current_lookup
->rdtype_sigchase
1435 = current_lookup
->rdtype
;
1436 current_lookup
->rdtype_sigchaseset
1437 = current_lookup
->rdtypeset
;
1438 current_lookup
->rdtype
= dns_rdatatype_ns
;
1440 current_lookup
->qrdtype_sigchase
1441 = current_lookup
->qrdtype
;
1442 current_lookup
->qrdtype
= dns_rdatatype_ns
;
1444 current_lookup
->rdclass_sigchase
1445 = current_lookup
->rdclass
;
1446 current_lookup
->rdclass_sigchaseset
1447 = current_lookup
->rdclassset
;
1448 current_lookup
->rdclass
= dns_rdataclass_in
;
1450 strncpy(current_lookup
->textnamesigchase
,
1451 current_lookup
->textname
, MXNAME
);
1453 current_lookup
->trace_root_sigchase
= ISC_TRUE
;
1455 result
= isc_buffer_allocate(mctx
, &b
, BUFSIZE
);
1456 check_result(result
, "isc_buffer_allocate");
1457 result
= dns_name_totext(dst_key_name(trustedkey
),
1459 check_result(result
, "dns_name_totext");
1460 isc_buffer_usedregion(b
, &r
);
1461 r
.base
[r
.length
] = '\0';
1462 strncpy(current_lookup
->textname
, (char*)r
.base
,
1464 isc_buffer_free(&b
);
1466 nameFromString(current_lookup
->textnamesigchase
,
1469 dns_name_init(&chase_authority_name
, NULL
);
1473 setup_lookup(current_lookup
);
1474 do_lookup(current_lookup
);
1481 * If we can, clear the current lookup and start the next one running.
1482 * This calls try_clear_lookup, so may invalidate the lookup pointer.
1485 check_next_lookup(dig_lookup_t
*lookup
) {
1489 debug("check_next_lookup(%p)", lookup
);
1491 if (ISC_LIST_HEAD(lookup
->q
) != NULL
) {
1492 debug("still have a worker");
1495 if (try_clear_lookup(lookup
)) {
1496 current_lookup
= NULL
;
1502 * Create and queue a new lookup as a followup to the current lookup,
1503 * based on the supplied message and section. This is used in trace and
1504 * name server search modes to start a new lookup using servers from
1505 * NS records in a reply. Returns the number of followup lookups made.
1508 followup_lookup(dns_message_t
*msg
, dig_query_t
*query
, dns_section_t section
)
1510 dig_lookup_t
*lookup
= NULL
;
1511 dig_server_t
*srv
= NULL
;
1512 dns_rdataset_t
*rdataset
= NULL
;
1513 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1514 dns_name_t
*name
= NULL
;
1515 isc_result_t result
;
1516 isc_boolean_t success
= ISC_FALSE
;
1519 isc_boolean_t horizontal
= ISC_FALSE
, bad
= ISC_FALSE
;
1523 debug("following up %s", query
->lookup
->textname
);
1525 for (result
= dns_message_firstname(msg
, section
);
1526 result
== ISC_R_SUCCESS
;
1527 result
= dns_message_nextname(msg
, section
)) {
1529 dns_message_currentname(msg
, section
, &name
);
1531 if (section
== DNS_SECTION_AUTHORITY
) {
1533 result
= dns_message_findtype(name
, dns_rdatatype_soa
,
1535 if (result
== ISC_R_SUCCESS
)
1539 result
= dns_message_findtype(name
, dns_rdatatype_ns
, 0,
1541 if (result
!= ISC_R_SUCCESS
)
1544 debug("found NS set");
1546 if (query
->lookup
->trace
&& !query
->lookup
->trace_root
) {
1547 dns_namereln_t namereln
;
1548 unsigned int nlabels
;
1551 domain
= dns_fixedname_name(&query
->lookup
->fdomain
);
1552 namereln
= dns_name_fullcompare(name
, domain
,
1554 if (namereln
== dns_namereln_equal
) {
1556 printf(";; BAD (HORIZONTAL) REFERRAL\n");
1557 horizontal
= ISC_TRUE
;
1558 } else if (namereln
!= dns_namereln_subdomain
) {
1560 printf(";; BAD REFERRAL\n");
1566 for (result
= dns_rdataset_first(rdataset
);
1567 result
== ISC_R_SUCCESS
;
1568 result
= dns_rdataset_next(rdataset
)) {
1569 char namestr
[DNS_NAME_FORMATSIZE
];
1572 if (query
->lookup
->trace_root
&&
1573 query
->lookup
->nsfound
>= MXSERV
)
1576 dns_rdataset_current(rdataset
, &rdata
);
1578 query
->lookup
->nsfound
++;
1579 result
= dns_rdata_tostruct(&rdata
, &ns
, NULL
);
1580 check_result(result
, "dns_rdata_tostruct");
1581 dns_name_format(&ns
.name
, namestr
, sizeof(namestr
));
1582 dns_rdata_freestruct(&ns
);
1584 /* Initialize lookup if we've not yet */
1585 debug("found NS %d %s", numLookups
, namestr
);
1590 lookup
= requeue_lookup(query
->lookup
,
1592 cancel_lookup(query
->lookup
);
1593 lookup
->doing_xfr
= ISC_FALSE
;
1594 if (!lookup
->trace_root
&&
1595 section
== DNS_SECTION_ANSWER
)
1596 lookup
->trace
= ISC_FALSE
;
1598 lookup
->trace
= query
->lookup
->trace
;
1599 lookup
->ns_search_only
=
1600 query
->lookup
->ns_search_only
;
1601 lookup
->trace_root
= ISC_FALSE
;
1602 if (lookup
->ns_search_only
)
1603 lookup
->recurse
= ISC_FALSE
;
1604 dns_fixedname_init(&lookup
->fdomain
);
1605 domain
= dns_fixedname_name(&lookup
->fdomain
);
1606 dns_name_copy(name
, domain
, NULL
);
1608 srv
= make_server(namestr
, namestr
);
1609 debug("adding server %s", srv
->servername
);
1610 ISC_LIST_APPEND(lookup
->my_server_list
, srv
, link
);
1611 dns_rdata_reset(&rdata
);
1615 if (lookup
== NULL
&&
1616 section
== DNS_SECTION_ANSWER
&&
1617 (query
->lookup
->trace
|| query
->lookup
->ns_search_only
))
1618 return (followup_lookup(msg
, query
, DNS_SECTION_AUTHORITY
));
1621 * Randomize the order the nameserver will be tried.
1623 if (numLookups
> 1) {
1625 dig_serverlist_t my_server_list
;
1627 ISC_LIST_INIT(my_server_list
);
1629 for (i
= numLookups
; i
> 0; i
--) {
1632 srv
= ISC_LIST_HEAD(lookup
->my_server_list
);
1634 srv
= ISC_LIST_NEXT(srv
, link
);
1635 ISC_LIST_DEQUEUE(lookup
->my_server_list
, srv
, link
);
1636 ISC_LIST_APPEND(my_server_list
, srv
, link
);
1638 ISC_LIST_APPENDLIST(lookup
->my_server_list
,
1639 my_server_list
, link
);
1642 return (numLookups
);
1646 * Create and queue a new lookup using the next origin from the search
1647 * list, read in setup_system().
1649 * Return ISC_TRUE iff there was another searchlist entry.
1651 static isc_boolean_t
1652 next_origin(dns_message_t
*msg
, dig_query_t
*query
) {
1653 dig_lookup_t
*lookup
;
1654 dig_searchlist_t
*search
;
1660 debug("next_origin()");
1661 debug("following up %s", query
->lookup
->textname
);
1665 * We're not using a search list, so don't even think
1666 * about finding the next entry.
1669 if (query
->lookup
->origin
== NULL
&& !query
->lookup
->need_search
)
1671 * Then we just did rootorg; there's nothing left.
1674 if (query
->lookup
->origin
== NULL
&& query
->lookup
->need_search
) {
1675 lookup
= requeue_lookup(query
->lookup
, ISC_TRUE
);
1676 lookup
->origin
= ISC_LIST_HEAD(search_list
);
1677 lookup
->need_search
= ISC_FALSE
;
1679 search
= ISC_LIST_NEXT(query
->lookup
->origin
, link
);
1680 if (search
== NULL
&& query
->lookup
->done_as_is
)
1682 lookup
= requeue_lookup(query
->lookup
, ISC_TRUE
);
1683 lookup
->origin
= search
;
1685 cancel_lookup(query
->lookup
);
1690 * Insert an SOA record into the sendmessage in a lookup. Used for
1691 * creating IXFR queries.
1694 insert_soa(dig_lookup_t
*lookup
) {
1695 isc_result_t result
;
1696 dns_rdata_soa_t soa
;
1697 dns_rdata_t
*rdata
= NULL
;
1698 dns_rdatalist_t
*rdatalist
= NULL
;
1699 dns_rdataset_t
*rdataset
= NULL
;
1700 dns_name_t
*soaname
= NULL
;
1702 debug("insert_soa()");
1704 soa
.serial
= lookup
->ixfr_serial
;
1709 soa
.common
.rdclass
= lookup
->rdclass
;
1710 soa
.common
.rdtype
= dns_rdatatype_soa
;
1712 dns_name_init(&soa
.origin
, NULL
);
1713 dns_name_init(&soa
.contact
, NULL
);
1715 dns_name_clone(dns_rootname
, &soa
.origin
);
1716 dns_name_clone(dns_rootname
, &soa
.contact
);
1718 isc_buffer_init(&lookup
->rdatabuf
, lookup
->rdatastore
,
1719 sizeof(lookup
->rdatastore
));
1721 result
= dns_message_gettemprdata(lookup
->sendmsg
, &rdata
);
1722 check_result(result
, "dns_message_gettemprdata");
1724 result
= dns_rdata_fromstruct(rdata
, lookup
->rdclass
,
1725 dns_rdatatype_soa
, &soa
,
1727 check_result(result
, "isc_rdata_fromstruct");
1729 result
= dns_message_gettemprdatalist(lookup
->sendmsg
, &rdatalist
);
1730 check_result(result
, "dns_message_gettemprdatalist");
1732 result
= dns_message_gettemprdataset(lookup
->sendmsg
, &rdataset
);
1733 check_result(result
, "dns_message_gettemprdataset");
1735 dns_rdatalist_init(rdatalist
);
1736 rdatalist
->type
= dns_rdatatype_soa
;
1737 rdatalist
->rdclass
= lookup
->rdclass
;
1738 rdatalist
->covers
= 0;
1740 ISC_LIST_INIT(rdatalist
->rdata
);
1741 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1743 dns_rdataset_init(rdataset
);
1744 dns_rdatalist_tordataset(rdatalist
, rdataset
);
1746 result
= dns_message_gettempname(lookup
->sendmsg
, &soaname
);
1747 check_result(result
, "dns_message_gettempname");
1748 dns_name_init(soaname
, NULL
);
1749 dns_name_clone(lookup
->name
, soaname
);
1750 ISC_LIST_INIT(soaname
->list
);
1751 ISC_LIST_APPEND(soaname
->list
, rdataset
, link
);
1752 dns_message_addname(lookup
->sendmsg
, soaname
, DNS_SECTION_AUTHORITY
);
1756 * Setup the supplied lookup structure, making it ready to start sending
1757 * queries to servers. Create and initialize the message to be sent as
1758 * well as the query structures and buffer space for the replies. If the
1759 * server list is empty, clone it from the system default list.
1762 setup_lookup(dig_lookup_t
*lookup
) {
1763 isc_result_t result
;
1769 dns_compress_t cctx
;
1773 char utf8_textname
[MXNAME
], utf8_origin
[MXNAME
], idn_textname
[MXNAME
];
1777 result
= dns_name_settotextfilter(output_filter
);
1778 check_result(result
, "dns_name_settotextfilter");
1781 REQUIRE(lookup
!= NULL
);
1784 debug("setup_lookup(%p)", lookup
);
1786 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTRENDER
,
1788 check_result(result
, "dns_message_create");
1790 if (lookup
->new_search
) {
1791 debug("resetting lookup counter.");
1795 if (ISC_LIST_EMPTY(lookup
->my_server_list
)) {
1796 debug("cloning server list");
1797 clone_server_list(server_list
, &lookup
->my_server_list
);
1799 result
= dns_message_gettempname(lookup
->sendmsg
, &lookup
->name
);
1800 check_result(result
, "dns_message_gettempname");
1801 dns_name_init(lookup
->name
, NULL
);
1803 isc_buffer_init(&lookup
->namebuf
, lookup
->namespace,
1804 sizeof(lookup
->namespace));
1805 isc_buffer_init(&lookup
->onamebuf
, lookup
->onamespace
,
1806 sizeof(lookup
->onamespace
));
1810 * We cannot convert `textname' and `origin' separately.
1811 * `textname' doesn't contain TLD, but local mapping needs
1814 mr
= idn_encodename(IDN_LOCALCONV
| IDN_DELIMMAP
, lookup
->textname
,
1815 utf8_textname
, sizeof(utf8_textname
));
1816 idn_check_result(mr
, "convert textname to UTF-8");
1820 * If the name has too many dots, force the origin to be NULL
1821 * (which produces an absolute lookup). Otherwise, take the origin
1822 * we have if there's one in the struct already. If it's NULL,
1823 * take the first entry in the searchlist iff either usesearch
1824 * is TRUE or we got a domain line in the resolv.conf file.
1826 if (lookup
->new_search
) {
1828 if ((count_dots(utf8_textname
) >= ndots
) || !usesearch
) {
1829 lookup
->origin
= NULL
; /* Force abs lookup */
1830 lookup
->done_as_is
= ISC_TRUE
;
1831 lookup
->need_search
= usesearch
;
1832 } else if (lookup
->origin
== NULL
&& usesearch
) {
1833 lookup
->origin
= ISC_LIST_HEAD(search_list
);
1834 lookup
->need_search
= ISC_FALSE
;
1837 if ((count_dots(lookup
->textname
) >= ndots
) || !usesearch
) {
1838 lookup
->origin
= NULL
; /* Force abs lookup */
1839 lookup
->done_as_is
= ISC_TRUE
;
1840 lookup
->need_search
= usesearch
;
1841 } else if (lookup
->origin
== NULL
&& usesearch
) {
1842 lookup
->origin
= ISC_LIST_HEAD(search_list
);
1843 lookup
->need_search
= ISC_FALSE
;
1849 if (lookup
->origin
!= NULL
) {
1850 mr
= idn_encodename(IDN_LOCALCONV
| IDN_DELIMMAP
,
1851 lookup
->origin
->origin
, utf8_origin
,
1852 sizeof(utf8_origin
));
1853 idn_check_result(mr
, "convert origin to UTF-8");
1854 mr
= append_textname(utf8_textname
, utf8_origin
,
1855 sizeof(utf8_textname
));
1856 idn_check_result(mr
, "append origin to textname");
1858 mr
= idn_encodename(idnoptions
| IDN_LOCALMAP
| IDN_NAMEPREP
|
1859 IDN_IDNCONV
| IDN_LENCHECK
, utf8_textname
,
1860 idn_textname
, sizeof(idn_textname
));
1861 idn_check_result(mr
, "convert UTF-8 textname to IDN encoding");
1863 if (lookup
->origin
!= NULL
) {
1864 debug("trying origin %s", lookup
->origin
->origin
);
1865 result
= dns_message_gettempname(lookup
->sendmsg
,
1867 check_result(result
, "dns_message_gettempname");
1868 dns_name_init(lookup
->oname
, NULL
);
1869 /* XXX Helper funct to conv char* to name? */
1870 len
= strlen(lookup
->origin
->origin
);
1871 isc_buffer_init(&b
, lookup
->origin
->origin
, len
);
1872 isc_buffer_add(&b
, len
);
1873 result
= dns_name_fromtext(lookup
->oname
, &b
, dns_rootname
,
1874 ISC_FALSE
, &lookup
->onamebuf
);
1875 if (result
!= ISC_R_SUCCESS
) {
1876 dns_message_puttempname(lookup
->sendmsg
,
1878 dns_message_puttempname(lookup
->sendmsg
,
1880 fatal("'%s' is not in legal name syntax (%s)",
1881 lookup
->origin
->origin
,
1882 isc_result_totext(result
));
1884 if (lookup
->trace
&& lookup
->trace_root
) {
1885 dns_name_clone(dns_rootname
, lookup
->name
);
1887 len
= strlen(lookup
->textname
);
1888 isc_buffer_init(&b
, lookup
->textname
, len
);
1889 isc_buffer_add(&b
, len
);
1890 result
= dns_name_fromtext(lookup
->name
, &b
,
1891 lookup
->oname
, ISC_FALSE
,
1894 if (result
!= ISC_R_SUCCESS
) {
1895 dns_message_puttempname(lookup
->sendmsg
,
1897 dns_message_puttempname(lookup
->sendmsg
,
1899 fatal("'%s' is not in legal name syntax (%s)",
1900 lookup
->textname
, isc_result_totext(result
));
1902 dns_message_puttempname(lookup
->sendmsg
, &lookup
->oname
);
1906 debug("using root origin");
1907 if (lookup
->trace
&& lookup
->trace_root
)
1908 dns_name_clone(dns_rootname
, lookup
->name
);
1911 len
= strlen(idn_textname
);
1912 isc_buffer_init(&b
, idn_textname
, len
);
1913 isc_buffer_add(&b
, len
);
1914 result
= dns_name_fromtext(lookup
->name
, &b
,
1919 len
= strlen(lookup
->textname
);
1920 isc_buffer_init(&b
, lookup
->textname
, len
);
1921 isc_buffer_add(&b
, len
);
1922 result
= dns_name_fromtext(lookup
->name
, &b
,
1928 if (result
!= ISC_R_SUCCESS
) {
1929 dns_message_puttempname(lookup
->sendmsg
,
1931 isc_buffer_init(&b
, store
, MXNAME
);
1932 fatal("'%s' is not a legal name "
1933 "(%s)", lookup
->textname
,
1934 isc_result_totext(result
));
1937 dns_name_format(lookup
->name
, store
, sizeof(store
));
1938 trying(store
, lookup
);
1939 INSIST(dns_name_isabsolute(lookup
->name
));
1941 isc_random_get(&id
);
1942 lookup
->sendmsg
->id
= (unsigned short)id
& 0xFFFF;
1943 lookup
->sendmsg
->opcode
= dns_opcode_query
;
1944 lookup
->msgcounter
= 0;
1946 * If this is a trace request, completely disallow recursion, since
1947 * it's meaningless for traces.
1949 if (lookup
->trace
|| (lookup
->ns_search_only
&& !lookup
->trace_root
))
1950 lookup
->recurse
= ISC_FALSE
;
1952 if (lookup
->recurse
&&
1953 lookup
->rdtype
!= dns_rdatatype_axfr
&&
1954 lookup
->rdtype
!= dns_rdatatype_ixfr
) {
1955 debug("recursive query");
1956 lookup
->sendmsg
->flags
|= DNS_MESSAGEFLAG_RD
;
1960 if (lookup
->aaonly
) {
1962 lookup
->sendmsg
->flags
|= DNS_MESSAGEFLAG_AA
;
1965 if (lookup
->adflag
) {
1967 lookup
->sendmsg
->flags
|= DNS_MESSAGEFLAG_AD
;
1970 if (lookup
->cdflag
) {
1972 lookup
->sendmsg
->flags
|= DNS_MESSAGEFLAG_CD
;
1975 dns_message_addname(lookup
->sendmsg
, lookup
->name
,
1976 DNS_SECTION_QUESTION
);
1978 if (lookup
->trace
&& lookup
->trace_root
) {
1979 lookup
->qrdtype
= lookup
->rdtype
;
1980 lookup
->rdtype
= dns_rdatatype_ns
;
1983 if ((lookup
->rdtype
== dns_rdatatype_axfr
) ||
1984 (lookup
->rdtype
== dns_rdatatype_ixfr
)) {
1986 * Force TCP mode if we're doing an axfr.
1988 if (lookup
->rdtype
== dns_rdatatype_axfr
) {
1989 lookup
->doing_xfr
= ISC_TRUE
;
1990 lookup
->tcp_mode
= ISC_TRUE
;
1991 } else if (lookup
->tcp_mode
) {
1992 lookup
->doing_xfr
= ISC_TRUE
;
1996 add_question(lookup
->sendmsg
, lookup
->name
, lookup
->rdclass
,
2000 if (lookup
->rdtype
== dns_rdatatype_ixfr
)
2003 /* XXX Insist this? */
2004 lookup
->tsigctx
= NULL
;
2005 lookup
->querysig
= NULL
;
2007 debug("initializing keys");
2008 result
= dns_message_settsigkey(lookup
->sendmsg
, key
);
2009 check_result(result
, "dns_message_settsigkey");
2012 lookup
->sendspace
= isc_mempool_get(commctx
);
2013 if (lookup
->sendspace
== NULL
)
2014 fatal("memory allocation failure");
2016 result
= dns_compress_init(&cctx
, -1, mctx
);
2017 check_result(result
, "dns_compress_init");
2019 debug("starting to render the message");
2020 isc_buffer_init(&lookup
->renderbuf
, lookup
->sendspace
, COMMSIZE
);
2021 result
= dns_message_renderbegin(lookup
->sendmsg
, &cctx
,
2022 &lookup
->renderbuf
);
2023 check_result(result
, "dns_message_renderbegin");
2024 if (lookup
->udpsize
> 0 || lookup
->dnssec
|| lookup
->edns
> -1) {
2025 if (lookup
->udpsize
== 0)
2026 lookup
->udpsize
= 4096;
2027 if (lookup
->edns
< 0)
2029 add_opt(lookup
->sendmsg
, lookup
->udpsize
,
2030 lookup
->edns
, lookup
->dnssec
, lookup
->nsid
);
2033 result
= dns_message_rendersection(lookup
->sendmsg
,
2034 DNS_SECTION_QUESTION
, 0);
2035 check_result(result
, "dns_message_rendersection");
2036 result
= dns_message_rendersection(lookup
->sendmsg
,
2037 DNS_SECTION_AUTHORITY
, 0);
2038 check_result(result
, "dns_message_rendersection");
2039 result
= dns_message_renderend(lookup
->sendmsg
);
2040 check_result(result
, "dns_message_renderend");
2041 debug("done rendering");
2043 dns_compress_invalidate(&cctx
);
2046 * Force TCP mode if the request is larger than 512 bytes.
2048 if (isc_buffer_usedlength(&lookup
->renderbuf
) > 512)
2049 lookup
->tcp_mode
= ISC_TRUE
;
2051 lookup
->pending
= ISC_FALSE
;
2053 for (serv
= ISC_LIST_HEAD(lookup
->my_server_list
);
2055 serv
= ISC_LIST_NEXT(serv
, link
)) {
2056 query
= isc_mem_allocate(mctx
, sizeof(dig_query_t
));
2058 fatal("memory allocation failure in %s:%d",
2059 __FILE__
, __LINE__
);
2060 debug("create query %p linked to lookup %p",
2062 query
->lookup
= lookup
;
2063 query
->waiting_connect
= ISC_FALSE
;
2064 query
->waiting_senddone
= ISC_FALSE
;
2065 query
->pending_free
= ISC_FALSE
;
2066 query
->recv_made
= ISC_FALSE
;
2067 query
->first_pass
= ISC_TRUE
;
2068 query
->first_soa_rcvd
= ISC_FALSE
;
2069 query
->second_rr_rcvd
= ISC_FALSE
;
2070 query
->first_repeat_rcvd
= ISC_FALSE
;
2071 query
->warn_id
= ISC_TRUE
;
2072 query
->first_rr_serial
= 0;
2073 query
->second_rr_serial
= 0;
2074 query
->servname
= serv
->servername
;
2075 query
->userarg
= serv
->userarg
;
2076 query
->rr_count
= 0;
2077 query
->msg_count
= 0;
2078 query
->byte_count
= 0;
2079 ISC_LINK_INIT(query
, link
);
2080 ISC_LIST_INIT(query
->recvlist
);
2081 ISC_LIST_INIT(query
->lengthlist
);
2083 query
->recvspace
= isc_mempool_get(commctx
);
2084 if (query
->recvspace
== NULL
)
2085 fatal("memory allocation failure");
2087 isc_buffer_init(&query
->recvbuf
, query
->recvspace
, COMMSIZE
);
2088 isc_buffer_init(&query
->lengthbuf
, query
->lengthspace
, 2);
2089 isc_buffer_init(&query
->slbuf
, query
->slspace
, 2);
2090 query
->sendbuf
= lookup
->renderbuf
;
2092 ISC_LINK_INIT(query
, link
);
2093 ISC_LIST_ENQUEUE(lookup
->q
, query
, link
);
2095 /* XXX qrflag, print_query, etc... */
2096 if (!ISC_LIST_EMPTY(lookup
->q
) && qr
) {
2098 printmessage(ISC_LIST_HEAD(lookup
->q
), lookup
->sendmsg
,
2104 * Event handler for send completion. Track send counter, and clear out
2105 * the query if the send was canceled.
2108 send_done(isc_task_t
*_task
, isc_event_t
*event
) {
2109 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
2110 isc_buffer_t
*b
= NULL
;
2111 dig_query_t
*query
, *next
;
2114 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
2120 debug("send_done()");
2122 debug("sendcount=%d", sendcount
);
2123 INSIST(sendcount
>= 0);
2125 for (b
= ISC_LIST_HEAD(sevent
->bufferlist
);
2127 b
= ISC_LIST_HEAD(sevent
->bufferlist
))
2128 ISC_LIST_DEQUEUE(sevent
->bufferlist
, b
, link
);
2130 query
= event
->ev_arg
;
2131 query
->waiting_senddone
= ISC_FALSE
;
2134 if (l
->ns_search_only
&& !l
->trace_root
) {
2135 debug("sending next, since searching");
2136 next
= ISC_LIST_NEXT(query
, link
);
2141 isc_event_free(&event
);
2143 if (query
->pending_free
)
2144 isc_mem_free(mctx
, query
);
2151 * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
2152 * IO sockets. The cancel handlers should take care of cleaning up the
2153 * query and lookup structures
2156 cancel_lookup(dig_lookup_t
*lookup
) {
2157 dig_query_t
*query
, *next
;
2159 debug("cancel_lookup()");
2160 query
= ISC_LIST_HEAD(lookup
->q
);
2161 while (query
!= NULL
) {
2162 next
= ISC_LIST_NEXT(query
, link
);
2163 if (query
->sock
!= NULL
) {
2164 isc_socket_cancel(query
->sock
, global_task
,
2165 ISC_SOCKCANCEL_ALL
);
2172 if (lookup
->timer
!= NULL
)
2173 isc_timer_detach(&lookup
->timer
);
2174 lookup
->pending
= ISC_FALSE
;
2175 lookup
->retries
= 0;
2179 bringup_timer(dig_query_t
*query
, unsigned int default_timeout
) {
2181 unsigned int local_timeout
;
2182 isc_result_t result
;
2184 debug("bringup_timer()");
2186 * If the timer already exists, that means we're calling this
2187 * a second time (for a retry). Don't need to recreate it,
2191 if (ISC_LIST_NEXT(query
, link
) != NULL
)
2192 local_timeout
= SERVER_TIMEOUT
;
2195 local_timeout
= default_timeout
;
2197 local_timeout
= timeout
;
2199 debug("have local timeout of %d", local_timeout
);
2200 isc_interval_set(&l
->interval
, local_timeout
, 0);
2201 if (l
->timer
!= NULL
)
2202 isc_timer_detach(&l
->timer
);
2203 result
= isc_timer_create(timermgr
, isc_timertype_once
, NULL
,
2204 &l
->interval
, global_task
, connect_timeout
,
2206 check_result(result
, "isc_timer_create");
2210 force_timeout(dig_lookup_t
*l
, dig_query_t
*query
) {
2213 event
= isc_event_allocate(mctx
, query
, ISC_TIMEREVENT_IDLE
,
2215 sizeof(isc_event_t
));
2216 if (event
== NULL
) {
2217 fatal("isc_event_allocate: %s",
2218 isc_result_totext(ISC_R_NOMEMORY
));
2220 isc_task_send(global_task
, &event
);
2225 connect_done(isc_task_t
*task
, isc_event_t
*event
);
2228 * Unlike send_udp, this can't be called multiple times with the same
2229 * query. When we retry TCP, we requeue the whole lookup, which should
2233 send_tcp_connect(dig_query_t
*query
) {
2234 isc_result_t result
;
2238 debug("send_tcp_connect(%p)", query
);
2241 query
->waiting_connect
= ISC_TRUE
;
2242 query
->lookup
->current_query
= query
;
2243 result
= get_address(query
->servname
, port
, &query
->sockaddr
);
2244 if (result
== ISC_R_NOTFOUND
) {
2246 * This servname doesn't have an address. Try the next server
2247 * by triggering an immediate 'timeout' (we lie, but the effect
2250 force_timeout(l
, query
);
2254 if (specified_source
&&
2255 (isc_sockaddr_pf(&query
->sockaddr
) !=
2256 isc_sockaddr_pf(&bind_address
))) {
2257 printf(";; Skipping server %s, incompatible "
2258 "address family\n", query
->servname
);
2259 query
->waiting_connect
= ISC_FALSE
;
2260 next
= ISC_LIST_NEXT(query
, link
);
2264 printf(";; No acceptable nameservers\n");
2265 check_next_lookup(l
);
2268 send_tcp_connect(next
);
2271 INSIST(query
->sock
== NULL
);
2272 result
= isc_socket_create(socketmgr
,
2273 isc_sockaddr_pf(&query
->sockaddr
),
2274 isc_sockettype_tcp
, &query
->sock
);
2275 check_result(result
, "isc_socket_create");
2277 debug("sockcount=%d", sockcount
);
2278 if (specified_source
)
2279 result
= isc_socket_bind(query
->sock
, &bind_address
,
2280 ISC_SOCKET_REUSEADDRESS
);
2282 if ((isc_sockaddr_pf(&query
->sockaddr
) == AF_INET
) &&
2284 isc_sockaddr_any(&bind_any
);
2286 isc_sockaddr_any6(&bind_any
);
2287 result
= isc_socket_bind(query
->sock
, &bind_any
, 0);
2289 check_result(result
, "isc_socket_bind");
2290 bringup_timer(query
, TCP_TIMEOUT
);
2291 result
= isc_socket_connect(query
->sock
, &query
->sockaddr
,
2292 global_task
, connect_done
, query
);
2293 check_result(result
, "isc_socket_connect");
2295 * If we're at the endgame of a nameserver search, we need to
2296 * immediately bring up all the queries. Do it here.
2298 if (l
->ns_search_only
&& !l
->trace_root
) {
2299 debug("sending next, since searching");
2300 next
= ISC_LIST_NEXT(query
, link
);
2302 send_tcp_connect(next
);
2307 * Send a UDP packet to the remote nameserver, possible starting the
2308 * recv action as well. Also make sure that the timer is running and
2309 * is properly reset.
2312 send_udp(dig_query_t
*query
) {
2313 dig_lookup_t
*l
= NULL
;
2314 isc_result_t result
;
2316 debug("send_udp(%p)", query
);
2319 bringup_timer(query
, UDP_TIMEOUT
);
2320 l
->current_query
= query
;
2321 debug("working on lookup %p, query %p", query
->lookup
, query
);
2322 if (!query
->recv_made
) {
2323 /* XXX Check the sense of this, need assertion? */
2324 query
->waiting_connect
= ISC_FALSE
;
2325 result
= get_address(query
->servname
, port
, &query
->sockaddr
);
2326 if (result
== ISC_R_NOTFOUND
) {
2327 /* This servname doesn't have an address. */
2328 force_timeout(l
, query
);
2332 result
= isc_socket_create(socketmgr
,
2333 isc_sockaddr_pf(&query
->sockaddr
),
2334 isc_sockettype_udp
, &query
->sock
);
2335 check_result(result
, "isc_socket_create");
2337 debug("sockcount=%d", sockcount
);
2338 if (specified_source
) {
2339 result
= isc_socket_bind(query
->sock
, &bind_address
,
2340 ISC_SOCKET_REUSEADDRESS
);
2342 isc_sockaddr_anyofpf(&bind_any
,
2343 isc_sockaddr_pf(&query
->sockaddr
));
2344 result
= isc_socket_bind(query
->sock
, &bind_any
, 0);
2346 check_result(result
, "isc_socket_bind");
2348 query
->recv_made
= ISC_TRUE
;
2349 ISC_LINK_INIT(&query
->recvbuf
, link
);
2350 ISC_LIST_ENQUEUE(query
->recvlist
, &query
->recvbuf
,
2352 debug("recving with lookup=%p, query=%p, sock=%p",
2353 query
->lookup
, query
, query
->sock
);
2354 result
= isc_socket_recvv(query
->sock
, &query
->recvlist
, 1,
2355 global_task
, recv_done
, query
);
2356 check_result(result
, "isc_socket_recvv");
2358 debug("recvcount=%d", recvcount
);
2360 ISC_LIST_INIT(query
->sendlist
);
2361 ISC_LIST_ENQUEUE(query
->sendlist
, &query
->sendbuf
, link
);
2362 debug("sending a request");
2363 TIME_NOW(&query
->time_sent
);
2364 INSIST(query
->sock
!= NULL
);
2365 query
->waiting_senddone
= ISC_TRUE
;
2366 result
= isc_socket_sendtov(query
->sock
, &query
->sendlist
,
2367 global_task
, send_done
, query
,
2368 &query
->sockaddr
, NULL
);
2369 check_result(result
, "isc_socket_sendtov");
2374 * IO timeout handler, used for both connect and recv timeouts. If
2375 * retries are still allowed, either resend the UDP packet or queue a
2376 * new TCP lookup. Otherwise, cancel the lookup.
2379 connect_timeout(isc_task_t
*task
, isc_event_t
*event
) {
2380 dig_lookup_t
*l
= NULL
;
2381 dig_query_t
*query
= NULL
, *cq
;
2384 REQUIRE(event
->ev_type
== ISC_TIMEREVENT_IDLE
);
2386 debug("connect_timeout()");
2390 query
= l
->current_query
;
2391 isc_event_free(&event
);
2395 if ((query
!= NULL
) && (query
->lookup
->current_query
!= NULL
) &&
2396 (ISC_LIST_NEXT(query
->lookup
->current_query
, link
) != NULL
)) {
2397 debug("trying next server...");
2398 cq
= query
->lookup
->current_query
;
2400 send_udp(ISC_LIST_NEXT(cq
, link
));
2402 isc_socket_cancel(query
->sock
, NULL
,
2403 ISC_SOCKCANCEL_ALL
);
2404 isc_socket_detach(&query
->sock
);
2406 debug("sockcount=%d", sockcount
);
2407 send_tcp_connect(ISC_LIST_NEXT(cq
, link
));
2413 if (l
->retries
> 1) {
2416 debug("resending UDP request to first server");
2417 send_udp(ISC_LIST_HEAD(l
->q
));
2419 debug("making new TCP request, %d tries left",
2422 requeue_lookup(l
, ISC_TRUE
);
2424 check_next_lookup(l
);
2427 fputs(l
->cmdline
, stdout
);
2428 printf(";; connection timed out; no servers could be "
2431 check_next_lookup(l
);
2439 * Event handler for the TCP recv which gets the length header of TCP
2440 * packets. Start the next recv of length bytes.
2443 tcp_length_done(isc_task_t
*task
, isc_event_t
*event
) {
2444 isc_socketevent_t
*sevent
;
2445 isc_buffer_t
*b
= NULL
;
2446 isc_result_t result
;
2447 dig_query_t
*query
= NULL
;
2449 isc_uint16_t length
;
2451 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_RECVDONE
);
2456 debug("tcp_length_done()");
2459 sevent
= (isc_socketevent_t
*)event
;
2460 query
= event
->ev_arg
;
2463 INSIST(recvcount
>= 0);
2465 b
= ISC_LIST_HEAD(sevent
->bufferlist
);
2466 INSIST(b
== &query
->lengthbuf
);
2467 ISC_LIST_DEQUEUE(sevent
->bufferlist
, b
, link
);
2469 if (sevent
->result
== ISC_R_CANCELED
) {
2470 isc_event_free(&event
);
2473 check_next_lookup(l
);
2477 if (sevent
->result
!= ISC_R_SUCCESS
) {
2478 char sockstr
[ISC_SOCKADDR_FORMATSIZE
];
2479 isc_sockaddr_format(&query
->sockaddr
, sockstr
,
2481 printf(";; communications error to %s: %s\n",
2482 sockstr
, isc_result_totext(sevent
->result
));
2484 isc_socket_detach(&query
->sock
);
2486 debug("sockcount=%d", sockcount
);
2487 INSIST(sockcount
>= 0);
2488 isc_event_free(&event
);
2490 check_next_lookup(l
);
2494 length
= isc_buffer_getuint16(b
);
2496 isc_event_free(&event
);
2497 launch_next_query(query
, ISC_FALSE
);
2503 * Even though the buffer was already init'ed, we need
2504 * to redo it now, to force the length we want.
2506 isc_buffer_invalidate(&query
->recvbuf
);
2507 isc_buffer_init(&query
->recvbuf
, query
->recvspace
, length
);
2508 ENSURE(ISC_LIST_EMPTY(query
->recvlist
));
2509 ISC_LINK_INIT(&query
->recvbuf
, link
);
2510 ISC_LIST_ENQUEUE(query
->recvlist
, &query
->recvbuf
, link
);
2511 debug("recving with lookup=%p, query=%p", query
->lookup
, query
);
2512 result
= isc_socket_recvv(query
->sock
, &query
->recvlist
, length
, task
,
2514 check_result(result
, "isc_socket_recvv");
2516 debug("resubmitted recv request with length %d, recvcount=%d",
2518 isc_event_free(&event
);
2523 * For transfers that involve multiple recvs (XFR's in particular),
2524 * launch the next recv.
2527 launch_next_query(dig_query_t
*query
, isc_boolean_t include_question
) {
2528 isc_result_t result
;
2533 debug("launch_next_query()");
2535 if (!query
->lookup
->pending
) {
2536 debug("ignoring launch_next_query because !pending");
2537 isc_socket_detach(&query
->sock
);
2539 debug("sockcount=%d", sockcount
);
2540 INSIST(sockcount
>= 0);
2541 query
->waiting_connect
= ISC_FALSE
;
2544 check_next_lookup(l
);
2548 isc_buffer_clear(&query
->slbuf
);
2549 isc_buffer_clear(&query
->lengthbuf
);
2550 isc_buffer_putuint16(&query
->slbuf
, (isc_uint16_t
) query
->sendbuf
.used
);
2551 ISC_LIST_INIT(query
->sendlist
);
2552 ISC_LINK_INIT(&query
->slbuf
, link
);
2553 ISC_LIST_ENQUEUE(query
->sendlist
, &query
->slbuf
, link
);
2554 if (include_question
)
2555 ISC_LIST_ENQUEUE(query
->sendlist
, &query
->sendbuf
, link
);
2556 ISC_LINK_INIT(&query
->lengthbuf
, link
);
2557 ISC_LIST_ENQUEUE(query
->lengthlist
, &query
->lengthbuf
, link
);
2559 result
= isc_socket_recvv(query
->sock
, &query
->lengthlist
, 0,
2560 global_task
, tcp_length_done
, query
);
2561 check_result(result
, "isc_socket_recvv");
2563 debug("recvcount=%d", recvcount
);
2564 if (!query
->first_soa_rcvd
) {
2565 debug("sending a request in launch_next_query");
2566 TIME_NOW(&query
->time_sent
);
2567 query
->waiting_senddone
= ISC_TRUE
;
2568 result
= isc_socket_sendv(query
->sock
, &query
->sendlist
,
2569 global_task
, send_done
, query
);
2570 check_result(result
, "isc_socket_sendv");
2572 debug("sendcount=%d", sendcount
);
2574 query
->waiting_connect
= ISC_FALSE
;
2576 check_next_lookup(query
->lookup
);
2582 * Event handler for TCP connect complete. Make sure the connection was
2583 * successful, then pass into launch_next_query to actually send the
2587 connect_done(isc_task_t
*task
, isc_event_t
*event
) {
2588 isc_socketevent_t
*sevent
= NULL
;
2589 dig_query_t
*query
= NULL
, *next
;
2594 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_CONNECT
);
2597 debug("connect_done()");
2600 sevent
= (isc_socketevent_t
*)event
;
2601 query
= sevent
->ev_arg
;
2603 INSIST(query
->waiting_connect
);
2605 query
->waiting_connect
= ISC_FALSE
;
2607 if (sevent
->result
== ISC_R_CANCELED
) {
2608 debug("in cancel handler");
2609 isc_socket_detach(&query
->sock
);
2611 INSIST(sockcount
>= 0);
2612 debug("sockcount=%d", sockcount
);
2613 query
->waiting_connect
= ISC_FALSE
;
2614 isc_event_free(&event
);
2617 check_next_lookup(l
);
2621 if (sevent
->result
!= ISC_R_SUCCESS
) {
2622 char sockstr
[ISC_SOCKADDR_FORMATSIZE
];
2624 debug("unsuccessful connection: %s",
2625 isc_result_totext(sevent
->result
));
2626 isc_sockaddr_format(&query
->sockaddr
, sockstr
, sizeof(sockstr
));
2627 if (sevent
->result
!= ISC_R_CANCELED
)
2628 printf(";; Connection to %s(%s) for %s failed: "
2630 query
->servname
, query
->lookup
->textname
,
2631 isc_result_totext(sevent
->result
));
2632 isc_socket_detach(&query
->sock
);
2634 INSIST(sockcount
>= 0);
2635 /* XXX Clean up exitcodes */
2638 debug("sockcount=%d", sockcount
);
2639 query
->waiting_connect
= ISC_FALSE
;
2640 isc_event_free(&event
);
2642 if (l
->current_query
!= NULL
)
2643 next
= ISC_LIST_NEXT(l
->current_query
, link
);
2648 bringup_timer(next
, TCP_TIMEOUT
);
2649 send_tcp_connect(next
);
2651 check_next_lookup(l
);
2656 launch_next_query(query
, ISC_TRUE
);
2657 isc_event_free(&event
);
2662 * Check if the ongoing XFR needs more data before it's complete, using
2663 * the semantics of IXFR and AXFR protocols. Much of the complexity of
2664 * this routine comes from determining when an IXFR is complete.
2665 * ISC_FALSE means more data is on the way, and the recv has been issued.
2667 static isc_boolean_t
2668 check_for_more_data(dig_query_t
*query
, dns_message_t
*msg
,
2669 isc_socketevent_t
*sevent
)
2671 dns_rdataset_t
*rdataset
= NULL
;
2672 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2673 dns_rdata_soa_t soa
;
2674 isc_uint32_t serial
;
2675 isc_result_t result
;
2677 debug("check_for_more_data()");
2680 * By the time we're in this routine, we know we're doing
2681 * either an AXFR or IXFR. If there's no second_rr_type,
2682 * then we don't yet know which kind of answer we got back
2683 * from the server. Here, we're going to walk through the
2684 * rr's in the message, acting as necessary whenever we hit
2689 query
->byte_count
+= sevent
->n
;
2690 result
= dns_message_firstname(msg
, DNS_SECTION_ANSWER
);
2691 if (result
!= ISC_R_SUCCESS
) {
2692 puts("; Transfer failed.");
2698 dns_message_currentname(msg
, DNS_SECTION_ANSWER
,
2700 for (rdataset
= ISC_LIST_HEAD(name
->list
);
2702 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
2703 result
= dns_rdataset_first(rdataset
);
2704 if (result
!= ISC_R_SUCCESS
)
2708 dns_rdata_reset(&rdata
);
2709 dns_rdataset_current(rdataset
, &rdata
);
2711 * If this is the first rr, make sure
2714 if ((!query
->first_soa_rcvd
) &&
2715 (rdata
.type
!= dns_rdatatype_soa
)) {
2716 puts("; Transfer failed. "
2717 "Didn't start with SOA answer.");
2720 if ((!query
->second_rr_rcvd
) &&
2721 (rdata
.type
!= dns_rdatatype_soa
)) {
2722 query
->second_rr_rcvd
= ISC_TRUE
;
2723 query
->second_rr_serial
= 0;
2724 debug("got the second rr as nonsoa");
2729 * If the record is anything except an SOA
2730 * now, just continue on...
2732 if (rdata
.type
!= dns_rdatatype_soa
)
2734 /* Now we have an SOA. Work with it. */
2735 debug("got an SOA");
2736 result
= dns_rdata_tostruct(&rdata
, &soa
, NULL
);
2737 check_result(result
, "dns_rdata_tostruct");
2738 serial
= soa
.serial
;
2739 dns_rdata_freestruct(&soa
);
2740 if (!query
->first_soa_rcvd
) {
2741 query
->first_soa_rcvd
= ISC_TRUE
;
2742 query
->first_rr_serial
= serial
;
2743 debug("this is the first %d",
2744 query
->lookup
->ixfr_serial
);
2745 if (query
->lookup
->ixfr_serial
>=
2750 if (query
->lookup
->rdtype
==
2751 dns_rdatatype_axfr
) {
2752 debug("doing axfr, got second SOA");
2755 if (!query
->second_rr_rcvd
) {
2756 if (query
->first_rr_serial
== serial
) {
2757 debug("doing ixfr, got "
2761 debug("this is the second %d",
2762 query
->lookup
->ixfr_serial
);
2763 query
->second_rr_rcvd
= ISC_TRUE
;
2764 query
->second_rr_serial
= serial
;
2767 if (query
->second_rr_serial
== 0) {
2769 * If the second RR was a non-SOA
2770 * record, and we're getting any
2771 * other SOA, then this is an
2772 * AXFR, and we're done.
2774 debug("done, since axfr");
2778 * If we get to this point, we're doing an
2779 * IXFR and have to start really looking
2780 * at serial numbers.
2782 if (query
->first_rr_serial
== serial
) {
2783 debug("got a match for ixfr");
2784 if (!query
->first_repeat_rcvd
) {
2785 query
->first_repeat_rcvd
=
2789 debug("done with ixfr");
2792 debug("meaningless soa %d", serial
);
2794 result
= dns_rdataset_next(rdataset
);
2795 } while (result
== ISC_R_SUCCESS
);
2797 result
= dns_message_nextname(msg
, DNS_SECTION_ANSWER
);
2798 } while (result
== ISC_R_SUCCESS
);
2799 launch_next_query(query
, ISC_FALSE
);
2802 received(sevent
->n
, &sevent
->address
, query
);
2807 * Event handler for recv complete. Perform whatever actions are necessary,
2808 * based on the specifics of the user's request.
2811 recv_done(isc_task_t
*task
, isc_event_t
*event
) {
2812 isc_socketevent_t
*sevent
= NULL
;
2813 dig_query_t
*query
= NULL
;
2814 isc_buffer_t
*b
= NULL
;
2815 dns_message_t
*msg
= NULL
;
2817 dig_message_t
*chase_msg
= NULL
;
2818 dig_message_t
*chase_msg2
= NULL
;
2820 isc_result_t result
;
2821 dig_lookup_t
*n
, *l
;
2822 isc_boolean_t docancel
= ISC_FALSE
;
2823 isc_boolean_t match
= ISC_TRUE
;
2824 unsigned int parseflags
;
2826 unsigned int msgflags
;
2828 isc_result_t do_sigchase
= ISC_FALSE
;
2830 dns_message_t
*msg_temp
= NULL
;
2832 isc_buffer_t
*buf
= NULL
;
2838 debug("recv_done()");
2842 debug("recvcount=%d", recvcount
);
2843 INSIST(recvcount
>= 0);
2845 query
= event
->ev_arg
;
2846 debug("lookup=%p, query=%p", query
->lookup
, query
);
2850 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_RECVDONE
);
2851 sevent
= (isc_socketevent_t
*)event
;
2853 b
= ISC_LIST_HEAD(sevent
->bufferlist
);
2854 INSIST(b
== &query
->recvbuf
);
2855 ISC_LIST_DEQUEUE(sevent
->bufferlist
, &query
->recvbuf
, link
);
2857 if ((l
->tcp_mode
) && (l
->timer
!= NULL
))
2858 isc_timer_touch(l
->timer
);
2859 if ((!l
->pending
&& !l
->ns_search_only
) || cancel_now
) {
2860 debug("no longer pending. Got %s",
2861 isc_result_totext(sevent
->result
));
2862 query
->waiting_connect
= ISC_FALSE
;
2864 isc_event_free(&event
);
2866 check_next_lookup(l
);
2871 if (sevent
->result
!= ISC_R_SUCCESS
) {
2872 if (sevent
->result
== ISC_R_CANCELED
) {
2873 debug("in recv cancel handler");
2874 query
->waiting_connect
= ISC_FALSE
;
2876 printf(";; communications error: %s\n",
2877 isc_result_totext(sevent
->result
));
2878 isc_socket_detach(&query
->sock
);
2880 debug("sockcount=%d", sockcount
);
2881 INSIST(sockcount
>= 0);
2883 isc_event_free(&event
);
2885 check_next_lookup(l
);
2891 !isc_sockaddr_compare(&sevent
->address
, &query
->sockaddr
,
2892 ISC_SOCKADDR_CMPADDR
|
2893 ISC_SOCKADDR_CMPPORT
|
2894 ISC_SOCKADDR_CMPSCOPE
|
2895 ISC_SOCKADDR_CMPSCOPEZERO
)) {
2896 char buf1
[ISC_SOCKADDR_FORMATSIZE
];
2897 char buf2
[ISC_SOCKADDR_FORMATSIZE
];
2900 if (isc_sockaddr_pf(&query
->sockaddr
) == AF_INET
)
2901 isc_sockaddr_any(&any
);
2903 isc_sockaddr_any6(&any
);
2906 * We don't expect a match when the packet is
2907 * sent to 0.0.0.0, :: or to a multicast addresses.
2908 * XXXMPA broadcast needs to be handled here as well.
2910 if ((!isc_sockaddr_eqaddr(&query
->sockaddr
, &any
) &&
2911 !isc_sockaddr_ismulticast(&query
->sockaddr
)) ||
2912 isc_sockaddr_getport(&query
->sockaddr
) !=
2913 isc_sockaddr_getport(&sevent
->address
)) {
2914 isc_sockaddr_format(&sevent
->address
, buf1
,
2916 isc_sockaddr_format(&query
->sockaddr
, buf2
,
2918 printf(";; reply from unexpected source: %s,"
2919 " expected %s\n", buf1
, buf2
);
2924 result
= dns_message_peekheader(b
, &id
, &msgflags
);
2925 if (result
!= ISC_R_SUCCESS
|| l
->sendmsg
->id
!= id
) {
2928 isc_boolean_t fail
= ISC_TRUE
;
2929 if (result
== ISC_R_SUCCESS
) {
2930 if (!query
->first_soa_rcvd
||
2932 printf(";; %s: ID mismatch: "
2933 "expected ID %u, got %u\n",
2934 query
->first_soa_rcvd
?
2935 "WARNING" : "ERROR",
2936 l
->sendmsg
->id
, id
);
2937 if (query
->first_soa_rcvd
)
2939 query
->warn_id
= ISC_FALSE
;
2941 printf(";; ERROR: short "
2942 "(< header size) message\n");
2944 isc_event_free(&event
);
2946 check_next_lookup(l
);
2951 } else if (result
== ISC_R_SUCCESS
)
2952 printf(";; Warning: ID mismatch: "
2953 "expected ID %u, got %u\n", l
->sendmsg
->id
, id
);
2955 printf(";; Warning: short "
2956 "(< header size) message received\n");
2959 if (result
== ISC_R_SUCCESS
&& (msgflags
& DNS_MESSAGEFLAG_QR
) == 0)
2960 printf(";; Warning: query response not set\n");
2965 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
, &msg
);
2966 check_result(result
, "dns_message_create");
2969 if (l
->querysig
== NULL
) {
2970 debug("getting initial querysig");
2971 result
= dns_message_getquerytsig(l
->sendmsg
, mctx
,
2973 check_result(result
, "dns_message_getquerytsig");
2975 result
= dns_message_setquerytsig(msg
, l
->querysig
);
2976 check_result(result
, "dns_message_setquerytsig");
2977 result
= dns_message_settsigkey(msg
, key
);
2978 check_result(result
, "dns_message_settsigkey");
2979 msg
->tsigctx
= l
->tsigctx
;
2981 if (l
->msgcounter
!= 0)
2982 msg
->tcp_continuation
= 1;
2986 debug("before parse starts");
2987 parseflags
= DNS_MESSAGEPARSE_PRESERVEORDER
;
2990 do_sigchase
= ISC_FALSE
;
2993 do_sigchase
= ISC_TRUE
;
2996 if (l
->besteffort
) {
2997 parseflags
|= DNS_MESSAGEPARSE_BESTEFFORT
;
2998 parseflags
|= DNS_MESSAGEPARSE_IGNORETRUNCATION
;
3000 result
= dns_message_parse(msg
, b
, parseflags
);
3001 if (result
== DNS_R_RECOVERABLE
) {
3002 printf(";; Warning: Message parser reports malformed "
3003 "message packet.\n");
3004 result
= ISC_R_SUCCESS
;
3006 if (result
!= ISC_R_SUCCESS
) {
3007 printf(";; Got bad packet: %s\n", isc_result_totext(result
));
3009 query
->waiting_connect
= ISC_FALSE
;
3010 dns_message_destroy(&msg
);
3011 isc_event_free(&event
);
3014 check_next_lookup(l
);
3018 if (msg
->counts
[DNS_SECTION_QUESTION
] != 0) {
3020 for (result
= dns_message_firstname(msg
, DNS_SECTION_QUESTION
);
3021 result
== ISC_R_SUCCESS
&& match
;
3022 result
= dns_message_nextname(msg
, DNS_SECTION_QUESTION
)) {
3023 dns_name_t
*name
= NULL
;
3024 dns_rdataset_t
*rdataset
;
3026 dns_message_currentname(msg
, DNS_SECTION_QUESTION
,
3028 for (rdataset
= ISC_LIST_HEAD(name
->list
);
3030 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3031 if (l
->rdtype
!= rdataset
->type
||
3032 l
->rdclass
!= rdataset
->rdclass
||
3033 !dns_name_equal(l
->name
, name
)) {
3034 char namestr
[DNS_NAME_FORMATSIZE
];
3035 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
3036 char classbuf
[DNS_RDATACLASS_FORMATSIZE
];
3037 dns_name_format(name
, namestr
,
3039 dns_rdatatype_format(rdataset
->type
,
3042 dns_rdataclass_format(rdataset
->rdclass
,
3045 printf(";; Question section mismatch: "
3047 namestr
, typebuf
, classbuf
);
3053 dns_message_destroy(&msg
);
3055 isc_event_free(&event
);
3057 check_next_lookup(l
);
3064 if ((msg
->flags
& DNS_MESSAGEFLAG_TC
) != 0 &&
3065 !l
->ignore
&& !l
->tcp_mode
) {
3066 printf(";; Truncated, retrying in TCP mode.\n");
3067 n
= requeue_lookup(l
, ISC_TRUE
);
3068 n
->tcp_mode
= ISC_TRUE
;
3069 n
->origin
= query
->lookup
->origin
;
3070 dns_message_destroy(&msg
);
3071 isc_event_free(&event
);
3074 check_next_lookup(l
);
3078 if ((msg
->rcode
== dns_rcode_servfail
&& !l
->servfail_stops
) ||
3079 (check_ra
&& (msg
->flags
& DNS_MESSAGEFLAG_RA
) == 0 && l
->recurse
))
3081 dig_query_t
*next
= ISC_LIST_NEXT(query
, link
);
3082 if (l
->current_query
== query
)
3083 l
->current_query
= NULL
;
3085 debug("sending query %p\n", next
);
3087 send_tcp_connect(next
);
3092 * If our query is at the head of the list and there
3093 * is no next, we're the only one left, so fall
3094 * through to print the message.
3096 if ((ISC_LIST_HEAD(l
->q
) != query
) ||
3097 (ISC_LIST_NEXT(query
, link
) != NULL
)) {
3098 if( l
->comments
== ISC_TRUE
)
3099 printf(";; Got %s from %s, "
3100 "trying next server\n",
3101 msg
->rcode
== dns_rcode_servfail
?
3103 "recursion not available",
3106 check_next_lookup(l
);
3107 dns_message_destroy(&msg
);
3108 isc_event_free(&event
);
3115 result
= dns_tsig_verify(&query
->recvbuf
, msg
, NULL
, NULL
);
3116 if (result
!= ISC_R_SUCCESS
) {
3117 printf(";; Couldn't verify signature: %s\n",
3118 isc_result_totext(result
));
3119 validated
= ISC_FALSE
;
3121 l
->tsigctx
= msg
->tsigctx
;
3122 msg
->tsigctx
= NULL
;
3123 if (l
->querysig
!= NULL
) {
3124 debug("freeing querysig buffer %p", l
->querysig
);
3125 isc_buffer_free(&l
->querysig
);
3127 result
= dns_message_getquerytsig(msg
, mctx
, &l
->querysig
);
3128 check_result(result
,"dns_message_getquerytsig");
3131 extrabytes
= isc_buffer_remaininglength(b
);
3133 debug("after parse");
3134 if (l
->doing_xfr
&& l
->xfr_q
== NULL
) {
3137 * Once we are in the XFR message, increase
3138 * the timeout to much longer, so brief network
3139 * outages won't cause the XFR to abort
3141 if (timeout
!= INT_MAX
&& l
->timer
!= NULL
) {
3142 unsigned int local_timeout
;
3146 local_timeout
= TCP_TIMEOUT
* 4;
3148 local_timeout
= UDP_TIMEOUT
* 4;
3150 if (timeout
< (INT_MAX
/ 4))
3151 local_timeout
= timeout
* 4;
3153 local_timeout
= INT_MAX
;
3155 debug("have local timeout of %d", local_timeout
);
3156 isc_interval_set(&l
->interval
, local_timeout
, 0);
3157 result
= isc_timer_reset(l
->timer
,
3162 check_result(result
, "isc_timer_reset");
3166 if (!l
->doing_xfr
|| l
->xfr_q
== query
) {
3167 if (msg
->rcode
!= dns_rcode_noerror
&&
3168 (l
->origin
!= NULL
|| l
->need_search
)) {
3169 if (!next_origin(msg
, query
) || showsearch
) {
3170 printmessage(query
, msg
, ISC_TRUE
);
3171 received(b
->used
, &sevent
->address
, query
);
3173 } else if (!l
->trace
&& !l
->ns_search_only
) {
3177 printmessage(query
, msg
, ISC_TRUE
);
3178 } else if (l
->trace
) {
3180 int count
= msg
->counts
[DNS_SECTION_ANSWER
];
3182 debug("in TRACE code");
3183 if (!l
->ns_search_only
)
3184 printmessage(query
, msg
, ISC_TRUE
);
3186 l
->rdtype
= l
->qrdtype
;
3187 if (l
->trace_root
|| (l
->ns_search_only
&& count
> 0)) {
3189 l
->rdtype
= dns_rdatatype_soa
;
3190 n
= followup_lookup(msg
, query
,
3191 DNS_SECTION_ANSWER
);
3192 l
->trace_root
= ISC_FALSE
;
3193 } else if (count
== 0)
3194 n
= followup_lookup(msg
, query
,
3195 DNS_SECTION_AUTHORITY
);
3197 docancel
= ISC_TRUE
;
3199 debug("in NSSEARCH code");
3201 if (l
->trace_root
) {
3203 * This is the initial NS query.
3207 l
->rdtype
= dns_rdatatype_soa
;
3208 n
= followup_lookup(msg
, query
,
3209 DNS_SECTION_ANSWER
);
3211 docancel
= ISC_TRUE
;
3212 l
->trace_root
= ISC_FALSE
;
3217 printmessage(query
, msg
, ISC_TRUE
);
3221 chase_msg
= isc_mem_allocate(mctx
,
3222 sizeof(dig_message_t
));
3223 if (chase_msg
== NULL
) {
3224 fatal("Memory allocation failure in %s:%d",
3225 __FILE__
, __LINE__
);
3227 ISC_LIST_INITANDAPPEND(chase_message_list
, chase_msg
,
3229 if (dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
,
3230 &msg_temp
) != ISC_R_SUCCESS
) {
3231 fatal("dns_message_create in %s:%d",
3232 __FILE__
, __LINE__
);
3235 isc_buffer_usedregion(b
, &r
);
3236 result
= isc_buffer_allocate(mctx
, &buf
, r
.length
);
3238 check_result(result
, "isc_buffer_allocate");
3239 result
= isc_buffer_copyregion(buf
, &r
);
3240 check_result(result
, "isc_buffer_copyregion");
3242 result
= dns_message_parse(msg_temp
, buf
, 0);
3244 isc_buffer_free(&buf
);
3245 chase_msg
->msg
= msg_temp
;
3247 chase_msg2
= isc_mem_allocate(mctx
,
3248 sizeof(dig_message_t
));
3249 if (chase_msg2
== NULL
) {
3250 fatal("Memory allocation failure in %s:%d",
3251 __FILE__
, __LINE__
);
3253 ISC_LIST_INITANDAPPEND(chase_message_list2
, chase_msg2
,
3255 chase_msg2
->msg
= msg
;
3261 if (l
->sigchase
&& ISC_LIST_EMPTY(lookup_list
)) {
3267 debug("still pending.");
3269 if (query
!= l
->xfr_q
) {
3270 dns_message_destroy(&msg
);
3271 isc_event_free(&event
);
3272 query
->waiting_connect
= ISC_FALSE
;
3277 docancel
= check_for_more_data(query
, msg
, sevent
);
3279 dns_message_destroy(&msg
);
3282 check_next_lookup(l
);
3286 if (msg
->rcode
== dns_rcode_noerror
|| l
->origin
== NULL
) {
3291 received(b
->used
, &sevent
->address
, query
);
3294 if (!query
->lookup
->ns_search_only
)
3295 query
->lookup
->pending
= ISC_FALSE
;
3296 if (!query
->lookup
->ns_search_only
||
3297 query
->lookup
->trace_root
|| docancel
) {
3301 dns_message_destroy(&msg
);
3306 check_next_lookup(l
);
3314 dns_message_destroy(&msg
);
3316 isc_event_free(&event
);
3321 isc_buffer_invalidate(&query
->recvbuf
);
3322 isc_buffer_init(&query
->recvbuf
, query
->recvspace
, COMMSIZE
);
3323 ISC_LIST_ENQUEUE(query
->recvlist
, &query
->recvbuf
, link
);
3324 result
= isc_socket_recvv(query
->sock
, &query
->recvlist
, 1,
3325 global_task
, recv_done
, query
);
3326 check_result(result
, "isc_socket_recvv");
3328 isc_event_free(&event
);
3334 * Turn a name into an address, using system-supplied routines. This is
3335 * used in looking up server names, etc... and needs to use system-supplied
3336 * routines, since they may be using a non-DNS system for these lookups.
3339 get_address(char *host
, in_port_t port
, isc_sockaddr_t
*sockaddr
) {
3341 isc_result_t result
;
3344 result
= bind9_getaddresses(host
, port
, sockaddr
, 1, &count
);
3346 if (result
!= ISC_R_SUCCESS
)
3351 return (ISC_R_SUCCESS
);
3355 * Initiate either a TCP or UDP lookup
3358 do_lookup(dig_lookup_t
*lookup
) {
3360 REQUIRE(lookup
!= NULL
);
3362 debug("do_lookup()");
3363 lookup
->pending
= ISC_TRUE
;
3364 if (lookup
->tcp_mode
)
3365 send_tcp_connect(ISC_LIST_HEAD(lookup
->q
));
3367 send_udp(ISC_LIST_HEAD(lookup
->q
));
3371 * Start everything in action upon task startup.
3374 onrun_callback(isc_task_t
*task
, isc_event_t
*event
) {
3377 isc_event_free(&event
);
3384 * Make everything on the lookup queue go away. Mainly used by the
3389 dig_lookup_t
*l
, *n
;
3390 dig_query_t
*q
, *nq
;
3392 debug("cancel_all()");
3399 cancel_now
= ISC_TRUE
;
3400 if (current_lookup
!= NULL
) {
3401 if (current_lookup
->timer
!= NULL
)
3402 isc_timer_detach(¤t_lookup
->timer
);
3403 q
= ISC_LIST_HEAD(current_lookup
->q
);
3405 debug("canceling query %p, belonging to %p",
3407 nq
= ISC_LIST_NEXT(q
, link
);
3408 if (q
->sock
!= NULL
) {
3409 isc_socket_cancel(q
->sock
, NULL
,
3410 ISC_SOCKCANCEL_ALL
);
3417 l
= ISC_LIST_HEAD(lookup_list
);
3419 n
= ISC_LIST_NEXT(l
, link
);
3420 ISC_LIST_DEQUEUE(lookup_list
, l
, link
);
3421 try_clear_lookup(l
);
3428 * Destroy all of the libs we are using, and get everything ready for a
3432 destroy_libs(void) {
3435 dig_message_t
*chase_msg
;
3438 isc_result_t result
;
3441 debug("destroy_libs()");
3442 if (global_task
!= NULL
) {
3443 debug("freeing task");
3444 isc_task_detach(&global_task
);
3447 * The taskmgr_destroy() call blocks until all events are cleared
3450 if (taskmgr
!= NULL
) {
3451 debug("freeing taskmgr");
3452 isc_taskmgr_destroy(&taskmgr
);
3455 REQUIRE(sockcount
== 0);
3456 REQUIRE(recvcount
== 0);
3457 REQUIRE(sendcount
== 0);
3459 INSIST(ISC_LIST_HEAD(lookup_list
) == NULL
);
3460 INSIST(current_lookup
== NULL
);
3463 free_now
= ISC_TRUE
;
3465 lwres_conf_clear(lwctx
);
3466 lwres_context_destroy(&lwctx
);
3468 flush_server_list();
3473 result
= dns_name_settotextfilter(NULL
);
3474 check_result(result
, "dns_name_settotextfilter");
3478 if (commctx
!= NULL
) {
3479 debug("freeing commctx");
3480 isc_mempool_destroy(&commctx
);
3482 if (socketmgr
!= NULL
) {
3483 debug("freeing socketmgr");
3484 isc_socketmgr_destroy(&socketmgr
);
3486 if (timermgr
!= NULL
) {
3487 debug("freeing timermgr");
3488 isc_timermgr_destroy(&timermgr
);
3491 debug("freeing key %p", key
);
3492 dns_tsigkey_detach(&key
);
3494 if (namebuf
!= NULL
)
3495 isc_buffer_free(&namebuf
);
3498 debug("destroy DST lib");
3500 is_dst_up
= ISC_FALSE
;
3503 debug("detach from entropy");
3504 isc_entropy_detach(&entp
);
3508 DESTROYLOCK(&lookup_lock
);
3511 debug("Destroy the messages kept for sigchase");
3512 /* Destroy the messages kept for sigchase */
3513 chase_msg
= ISC_LIST_HEAD(chase_message_list
);
3515 while (chase_msg
!= NULL
) {
3516 INSIST(chase_msg
->msg
!= NULL
);
3517 dns_message_destroy(&(chase_msg
->msg
));
3519 chase_msg
= ISC_LIST_NEXT(chase_msg
, link
);
3520 isc_mem_free(mctx
, ptr
);
3523 chase_msg
= ISC_LIST_HEAD(chase_message_list2
);
3525 while (chase_msg
!= NULL
) {
3526 INSIST(chase_msg
->msg
!= NULL
);
3527 dns_message_destroy(&(chase_msg
->msg
));
3529 chase_msg
= ISC_LIST_NEXT(chase_msg
, link
);
3530 isc_mem_free(mctx
, ptr
);
3532 if (dns_name_dynamic(&chase_name
))
3533 free_name(&chase_name
, mctx
);
3535 if (dns_name_dynamic(&chase_current_name
))
3536 free_name(&chase_current_name
, mctx
);
3537 if (dns_name_dynamic(&chase_authority_name
))
3538 free_name(&chase_authority_name
, mctx
);
3541 if (dns_name_dynamic(&chase_signame
))
3542 free_name(&chase_signame
, mctx
);
3545 debug("Destroy memory");
3548 if (memdebugging
!= 0)
3549 isc_mem_stats(mctx
, stderr
);
3551 isc_mem_destroy(&mctx
);
3556 initialize_idn(void) {
3558 isc_result_t result
;
3560 #ifdef HAVE_SETLOCALE
3562 (void)setlocale(LC_ALL
, "");
3564 /* Create configuration context. */
3565 r
= idn_nameinit(1);
3566 if (r
!= idn_success
)
3567 fatal("idn api initialization failed: %s",
3568 idn_result_tostring(r
));
3570 /* Set domain name -> text post-conversion filter. */
3571 result
= dns_name_settotextfilter(output_filter
);
3572 check_result(result
, "dns_name_settotextfilter");
3576 output_filter(isc_buffer_t
*buffer
, unsigned int used_org
,
3577 isc_boolean_t absolute
)
3579 char tmp1
[MAXDLEN
], tmp2
[MAXDLEN
];
3580 size_t fromlen
, tolen
;
3581 isc_boolean_t end_with_dot
;
3584 * Copy contents of 'buffer' to 'tmp1', supply trailing dot
3585 * if 'absolute' is true, and terminate with NUL.
3587 fromlen
= isc_buffer_usedlength(buffer
) - used_org
;
3588 if (fromlen
>= MAXDLEN
)
3589 return (ISC_R_SUCCESS
);
3590 memcpy(tmp1
, (char *)isc_buffer_base(buffer
) + used_org
, fromlen
);
3591 end_with_dot
= (tmp1
[fromlen
- 1] == '.') ? ISC_TRUE
: ISC_FALSE
;
3592 if (absolute
&& !end_with_dot
) {
3594 if (fromlen
>= MAXDLEN
)
3595 return (ISC_R_SUCCESS
);
3596 tmp1
[fromlen
- 1] = '.';
3598 tmp1
[fromlen
] = '\0';
3601 * Convert contents of 'tmp1' to local encoding.
3603 if (idn_decodename(IDN_DECODE_APP
, tmp1
, tmp2
, MAXDLEN
) != idn_success
)
3604 return (ISC_R_SUCCESS
);
3608 * Copy the converted contents in 'tmp1' back to 'buffer'.
3609 * If we have appended trailing dot, remove it.
3611 tolen
= strlen(tmp1
);
3612 if (absolute
&& !end_with_dot
&& tmp1
[tolen
- 1] == '.')
3615 if (isc_buffer_length(buffer
) < used_org
+ tolen
)
3616 return (ISC_R_NOSPACE
);
3618 isc_buffer_subtract(buffer
, isc_buffer_usedlength(buffer
) - used_org
);
3619 memcpy(isc_buffer_used(buffer
), tmp1
, tolen
);
3620 isc_buffer_add(buffer
, tolen
);
3622 return (ISC_R_SUCCESS
);
3626 append_textname(char *name
, const char *origin
, size_t namesize
) {
3627 size_t namelen
= strlen(name
);
3628 size_t originlen
= strlen(origin
);
3630 /* Already absolute? */
3631 if (namelen
> 0 && name
[namelen
- 1] == '.')
3634 /* Append dot and origin */
3636 if (namelen
+ 1 + originlen
>= namesize
)
3637 return idn_buffer_overflow
;
3639 name
[namelen
++] = '.';
3640 (void)strcpy(name
+ namelen
, origin
);
3645 idn_check_result(idn_result_t r
, const char *msg
) {
3646 if (r
!= idn_success
) {
3648 fatal("%s: %s", msg
, idn_result_tostring(r
));
3651 #endif /* WITH_IDN */
3655 print_type(dns_rdatatype_t type
)
3657 isc_buffer_t
* b
= NULL
;
3658 isc_result_t result
;
3661 result
= isc_buffer_allocate(mctx
, &b
, 4000);
3662 check_result(result
, "isc_buffer_allocate");
3664 result
= dns_rdatatype_totext(type
, b
);
3665 check_result(result
, "print_type");
3667 isc_buffer_usedregion(b
, &r
);
3668 r
.base
[r
.length
] = '\0';
3670 printf("%s", r
.base
);
3672 isc_buffer_free(&b
);
3676 dump_database_section(dns_message_t
*msg
, int section
)
3678 dns_name_t
*msg_name
=NULL
;
3680 dns_rdataset_t
*rdataset
;
3683 dns_message_currentname(msg
, section
, &msg_name
);
3685 for (rdataset
= ISC_LIST_HEAD(msg_name
->list
); rdataset
!= NULL
;
3686 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3687 dns_name_print(msg_name
, stdout
);
3689 print_rdataset(msg_name
, rdataset
, mctx
);
3693 } while (dns_message_nextname(msg
, section
) == ISC_R_SUCCESS
);
3697 dump_database(void) {
3698 dig_message_t
* msg
;
3700 for (msg
= ISC_LIST_HEAD(chase_message_list
); msg
!= NULL
;
3701 msg
= ISC_LIST_NEXT(msg
, link
)) {
3702 if (dns_message_firstname(msg
->msg
, DNS_SECTION_ANSWER
)
3704 dump_database_section(msg
->msg
, DNS_SECTION_ANSWER
);
3706 if (dns_message_firstname(msg
->msg
, DNS_SECTION_AUTHORITY
)
3708 dump_database_section(msg
->msg
, DNS_SECTION_AUTHORITY
);
3710 if (dns_message_firstname(msg
->msg
, DNS_SECTION_ADDITIONAL
)
3712 dump_database_section(msg
->msg
, DNS_SECTION_ADDITIONAL
);
3718 search_type(dns_name_t
*name
, dns_rdatatype_t type
, dns_rdatatype_t covers
) {
3719 dns_rdataset_t
*rdataset
;
3720 dns_rdata_sig_t siginfo
;
3721 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
3722 isc_result_t result
;
3724 for (rdataset
= ISC_LIST_HEAD(name
->list
); rdataset
!= NULL
;
3725 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3726 if (type
== dns_rdatatype_any
) {
3727 if (rdataset
->type
!= dns_rdatatype_rrsig
)
3729 } else if ((type
== dns_rdatatype_rrsig
) &&
3730 (rdataset
->type
== dns_rdatatype_rrsig
)) {
3731 result
= dns_rdataset_first(rdataset
);
3732 check_result(result
, "empty rdataset");
3733 dns_rdataset_current(rdataset
, &sigrdata
);
3734 result
= dns_rdata_tostruct(&sigrdata
, &siginfo
, NULL
);
3735 check_result(result
, "sigrdata tostruct siginfo");
3737 if ((siginfo
.covered
== covers
) ||
3738 (covers
== dns_rdatatype_any
)) {
3739 dns_rdata_reset(&sigrdata
);
3740 dns_rdata_freestruct(&siginfo
);
3743 dns_rdata_reset(&sigrdata
);
3744 dns_rdata_freestruct(&siginfo
);
3745 } else if (rdataset
->type
== type
)
3752 chase_scanname_section(dns_message_t
*msg
, dns_name_t
*name
,
3753 dns_rdatatype_t type
, dns_rdatatype_t covers
,
3756 dns_rdataset_t
*rdataset
;
3757 dns_name_t
*msg_name
= NULL
;
3760 dns_message_currentname(msg
, section
, &msg_name
);
3761 if (dns_name_compare(msg_name
, name
) == 0) {
3762 rdataset
= search_type(msg_name
, type
, covers
);
3763 if (rdataset
!= NULL
)
3767 } while (dns_message_nextname(msg
, section
) == ISC_R_SUCCESS
);
3774 chase_scanname(dns_name_t
*name
, dns_rdatatype_t type
, dns_rdatatype_t covers
)
3776 dns_rdataset_t
*rdataset
= NULL
;
3777 dig_message_t
* msg
;
3779 for (msg
= ISC_LIST_HEAD(chase_message_list2
); msg
!= NULL
;
3780 msg
= ISC_LIST_NEXT(msg
, link
)) {
3781 if (dns_message_firstname(msg
->msg
, DNS_SECTION_ANSWER
)
3783 rdataset
= chase_scanname_section(msg
->msg
, name
,
3785 DNS_SECTION_ANSWER
);
3786 if (rdataset
!= NULL
)
3788 if (dns_message_firstname(msg
->msg
, DNS_SECTION_AUTHORITY
)
3791 chase_scanname_section(msg
->msg
, name
,
3793 DNS_SECTION_AUTHORITY
);
3794 if (rdataset
!= NULL
)
3796 if (dns_message_firstname(msg
->msg
, DNS_SECTION_ADDITIONAL
)
3799 chase_scanname_section(msg
->msg
, name
, type
,
3801 DNS_SECTION_ADDITIONAL
);
3802 if (rdataset
!= NULL
)
3810 sigchase_scanname(dns_rdatatype_t type
, dns_rdatatype_t covers
,
3811 isc_boolean_t
* lookedup
, dns_name_t
*rdata_name
)
3813 dig_lookup_t
*lookup
;
3814 isc_buffer_t
*b
= NULL
;
3816 isc_result_t result
;
3817 dns_rdataset_t
* temp
;
3818 dns_rdatatype_t querytype
;
3820 temp
= chase_scanname(rdata_name
, type
, covers
);
3824 if (*lookedup
== ISC_TRUE
)
3827 lookup
= clone_lookup(current_lookup
, ISC_TRUE
);
3828 lookup
->trace_root
= ISC_FALSE
;
3829 lookup
->new_search
= ISC_TRUE
;
3831 result
= isc_buffer_allocate(mctx
, &b
, BUFSIZE
);
3832 check_result(result
, "isc_buffer_allocate");
3833 result
= dns_name_totext(rdata_name
, ISC_FALSE
, b
);
3834 check_result(result
, "dns_name_totext");
3835 isc_buffer_usedregion(b
, &r
);
3836 r
.base
[r
.length
] = '\0';
3837 strcpy(lookup
->textname
, (char*)r
.base
);
3838 isc_buffer_free(&b
);
3840 if (type
== dns_rdatatype_rrsig
)
3845 if (querytype
== 0 || querytype
== 255) {
3846 printf("Error in the queried type: %d\n", querytype
);
3850 lookup
->rdtype
= querytype
;
3851 lookup
->rdtypeset
= ISC_TRUE
;
3852 lookup
->qrdtype
= querytype
;
3853 *lookedup
= ISC_TRUE
;
3855 ISC_LIST_APPEND(lookup_list
, lookup
, link
);
3856 printf("\n\nLaunch a query to find a RRset of type ");
3858 printf(" for zone: %s\n", lookup
->textname
);
3863 insert_trustedkey(dst_key_t
* key
)
3867 if (tk_list
.nb_tk
>= MAX_TRUSTED_KEY
)
3870 tk_list
.key
[tk_list
.nb_tk
++] = key
;
3879 for (i
= 0; i
< MAX_TRUSTED_KEY
; i
++) {
3880 if (tk_list
.key
[i
] != NULL
) {
3881 dst_key_free(&tk_list
.key
[i
]);
3882 tk_list
.key
[i
] = NULL
;
3891 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
3894 removetmpkey(isc_mem_t
*mctx
, const char *file
)
3896 char *tempnamekey
= NULL
;
3898 isc_result_t result
;
3900 tempnamekeylen
= strlen(file
)+10;
3902 tempnamekey
= isc_mem_allocate(mctx
, tempnamekeylen
);
3903 if (tempnamekey
== NULL
)
3904 return (ISC_R_NOMEMORY
);
3906 memset(tempnamekey
, 0, tempnamekeylen
);
3908 strcat(tempnamekey
, file
);
3909 strcat(tempnamekey
,".key");
3910 isc_file_remove(tempnamekey
);
3912 result
= isc_file_remove(tempnamekey
);
3913 isc_mem_free(mctx
, tempnamekey
);
3918 opentmpkey(isc_mem_t
*mctx
, const char *file
, char **tempp
, FILE **fp
) {
3920 isc_result_t result
;
3921 char *tempname
= NULL
;
3922 char *tempnamekey
= NULL
;
3930 tempnamelen
= strlen(file
) + 20;
3931 tempname
= isc_mem_allocate(mctx
, tempnamelen
);
3932 if (tempname
== NULL
)
3933 return (ISC_R_NOMEMORY
);
3934 memset(tempname
, 0, tempnamelen
);
3936 result
= isc_file_mktemplate(file
, tempname
, tempnamelen
);
3937 if (result
!= ISC_R_SUCCESS
)
3943 if (cp
== tempname
) {
3944 isc_mem_free(mctx
, tempname
);
3945 return (ISC_R_FAILURE
);
3949 while (cp
>= tempname
&& *cp
== 'X') {
3950 isc_random_get(&which
);
3951 *cp
= alphnum
[which
% (sizeof(alphnum
) - 1)];
3955 tempnamekeylen
= tempnamelen
+5;
3956 tempnamekey
= isc_mem_allocate(mctx
, tempnamekeylen
);
3957 if (tempnamekey
== NULL
)
3958 return (ISC_R_NOMEMORY
);
3960 memset(tempnamekey
, 0, tempnamekeylen
);
3961 strncpy(tempnamekey
, tempname
, tempnamelen
);
3962 strcat(tempnamekey
,".key");
3965 if (isc_file_exists(tempnamekey
)) {
3966 isc_mem_free(mctx
, tempnamekey
);
3967 isc_mem_free(mctx
, tempname
);
3971 if ((f
= fopen(tempnamekey
, "w")) == NULL
) {
3972 printf("get_trusted_key(): trusted key not found %s\n",
3974 return (ISC_R_FAILURE
);
3978 isc_mem_free(mctx
, tempnamekey
);
3981 return (ISC_R_SUCCESS
);
3984 isc_mem_free(mctx
, tempname
);
3991 get_trusted_key(isc_mem_t
*mctx
)
3993 isc_result_t result
;
3994 const char *filename
= NULL
;
3995 char *filetemp
= NULL
;
3998 dst_key_t
*key
= NULL
;
4000 result
= isc_file_exists(trustedkey
);
4001 if (result
!= ISC_TRUE
) {
4002 result
= isc_file_exists("/etc/trusted-key.key");
4003 if (result
!= ISC_TRUE
) {
4004 result
= isc_file_exists("./trusted-key.key");
4005 if (result
!= ISC_TRUE
)
4006 return (ISC_R_FAILURE
);
4008 filename
= "./trusted-key.key";
4010 filename
= "/etc/trusted-key.key";
4012 filename
= trustedkey
;
4014 if (filename
== NULL
) {
4015 printf("No trusted key\n");
4016 return (ISC_R_FAILURE
);
4019 if ((fp
= fopen(filename
, "r")) == NULL
) {
4020 printf("get_trusted_key(): trusted key not found %s\n",
4022 return (ISC_R_FAILURE
);
4024 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
4025 result
= opentmpkey(mctx
,"tmp_file", &filetemp
, &fptemp
);
4026 if (result
!= ISC_R_SUCCESS
) {
4028 return (ISC_R_FAILURE
);
4030 if (fputs(buf
, fptemp
) < 0) {
4033 return (ISC_R_FAILURE
);
4036 result
= dst_key_fromnamedfile(filetemp
, DST_TYPE_PUBLIC
,
4038 removetmpkey(mctx
, filetemp
);
4039 isc_mem_free(mctx
, filetemp
);
4040 if (result
!= ISC_R_SUCCESS
) {
4042 return (ISC_R_FAILURE
);
4044 insert_trustedkey(key
);
4046 dst_key_tofile(key
, DST_TYPE_PUBLIC
,"/tmp");
4050 return (ISC_R_SUCCESS
);
4055 nameFromString(const char *str
, dns_name_t
*p_ret
) {
4056 size_t len
= strlen(str
);
4057 isc_result_t result
;
4058 isc_buffer_t buffer
;
4059 dns_fixedname_t fixedname
;
4061 REQUIRE(p_ret
!= NULL
);
4062 REQUIRE(str
!= NULL
);
4064 isc_buffer_init(&buffer
, str
, len
);
4065 isc_buffer_add(&buffer
, len
);
4067 dns_fixedname_init(&fixedname
);
4068 result
= dns_name_fromtext(dns_fixedname_name(&fixedname
), &buffer
,
4069 dns_rootname
, ISC_TRUE
, NULL
);
4070 check_result(result
, "nameFromString");
4072 if (dns_name_dynamic(p_ret
))
4073 free_name(p_ret
, mctx
);
4075 result
= dns_name_dup(dns_fixedname_name(&fixedname
), mctx
, p_ret
);
4076 check_result(result
, "nameFromString");
4082 prepare_lookup(dns_name_t
*name
)
4084 isc_result_t result
;
4085 dig_lookup_t
*lookup
= NULL
;
4089 lookup
= clone_lookup(current_lookup
, ISC_TRUE
);
4090 lookup
->trace_root
= ISC_FALSE
;
4091 lookup
->new_search
= ISC_TRUE
;
4092 lookup
->trace_root_sigchase
= ISC_FALSE
;
4094 strncpy(lookup
->textname
, lookup
->textnamesigchase
, MXNAME
);
4096 lookup
->rdtype
= lookup
->rdtype_sigchase
;
4097 lookup
->rdtypeset
= ISC_TRUE
;
4098 lookup
->qrdtype
= lookup
->qrdtype_sigchase
;
4100 s
= ISC_LIST_HEAD(lookup
->my_server_list
);
4102 debug("freeing server %p belonging to %p",
4105 s
= ISC_LIST_NEXT(s
, link
);
4106 ISC_LIST_DEQUEUE(lookup
->my_server_list
,
4107 (dig_server_t
*)ptr
, link
);
4108 isc_mem_free(mctx
, ptr
);
4112 for (result
= dns_rdataset_first(chase_nsrdataset
);
4113 result
== ISC_R_SUCCESS
;
4114 result
= dns_rdataset_next(chase_nsrdataset
)) {
4115 char namestr
[DNS_NAME_FORMATSIZE
];
4117 dns_rdata_t rdata
= DNS_RDATA_INIT
;
4118 dig_server_t
* srv
= NULL
;
4119 #define __FOLLOW_GLUE__
4120 #ifdef __FOLLOW_GLUE__
4121 isc_buffer_t
*b
= NULL
;
4122 isc_result_t result
;
4124 dns_rdataset_t
*rdataset
= NULL
;
4125 isc_boolean_t
true = ISC_TRUE
;
4128 memset(namestr
, 0, DNS_NAME_FORMATSIZE
);
4130 dns_rdataset_current(chase_nsrdataset
, &rdata
);
4132 result
= dns_rdata_tostruct(&rdata
, &ns
, NULL
);
4133 check_result(result
, "dns_rdata_tostruct");
4135 #ifdef __FOLLOW_GLUE__
4137 result
= advanced_rrsearch(&rdataset
, &ns
.name
,
4139 dns_rdatatype_any
, &true);
4140 if (result
== ISC_R_SUCCESS
) {
4141 for (result
= dns_rdataset_first(rdataset
);
4142 result
== ISC_R_SUCCESS
;
4143 result
= dns_rdataset_next(rdataset
)) {
4144 dns_rdata_t aaaa
= DNS_RDATA_INIT
;
4145 dns_rdataset_current(rdataset
, &aaaa
);
4147 result
= isc_buffer_allocate(mctx
, &b
, 80);
4148 check_result(result
, "isc_buffer_allocate");
4150 dns_rdata_totext(&aaaa
, &ns
.name
, b
);
4151 isc_buffer_usedregion(b
, &r
);
4152 r
.base
[r
.length
] = '\0';
4153 strncpy(namestr
, (char*)r
.base
,
4154 DNS_NAME_FORMATSIZE
);
4155 isc_buffer_free(&b
);
4156 dns_rdata_reset(&aaaa
);
4159 srv
= make_server(namestr
, namestr
);
4161 ISC_LIST_APPEND(lookup
->my_server_list
,
4167 result
= advanced_rrsearch(&rdataset
, &ns
.name
, dns_rdatatype_a
,
4168 dns_rdatatype_any
, &true);
4169 if (result
== ISC_R_SUCCESS
) {
4170 for (result
= dns_rdataset_first(rdataset
);
4171 result
== ISC_R_SUCCESS
;
4172 result
= dns_rdataset_next(rdataset
)) {
4173 dns_rdata_t a
= DNS_RDATA_INIT
;
4174 dns_rdataset_current(rdataset
, &a
);
4176 result
= isc_buffer_allocate(mctx
, &b
, 80);
4177 check_result(result
, "isc_buffer_allocate");
4179 dns_rdata_totext(&a
, &ns
.name
, b
);
4180 isc_buffer_usedregion(b
, &r
);
4181 r
.base
[r
.length
] = '\0';
4182 strncpy(namestr
, (char*)r
.base
,
4183 DNS_NAME_FORMATSIZE
);
4184 isc_buffer_free(&b
);
4185 dns_rdata_reset(&a
);
4186 printf("ns name: %s\n", namestr
);
4189 srv
= make_server(namestr
, namestr
);
4191 ISC_LIST_APPEND(lookup
->my_server_list
,
4197 dns_name_format(&ns
.name
, namestr
, sizeof(namestr
));
4198 printf("ns name: ");
4199 dns_name_print(&ns
.name
, stdout
);
4201 srv
= make_server(namestr
, namestr
);
4203 ISC_LIST_APPEND(lookup
->my_server_list
, srv
, link
);
4206 dns_rdata_freestruct(&ns
);
4207 dns_rdata_reset(&rdata
);
4211 ISC_LIST_APPEND(lookup_list
, lookup
, link
);
4212 printf("\nLaunch a query to find a RRset of type ");
4213 print_type(lookup
->rdtype
);
4214 printf(" for zone: %s", lookup
->textname
);
4215 printf(" with nameservers:");
4217 print_rdataset(name
, chase_nsrdataset
, mctx
);
4218 return (ISC_R_SUCCESS
);
4223 child_of_zone(dns_name_t
* name
, dns_name_t
* zone_name
,
4224 dns_name_t
* child_name
)
4226 dns_namereln_t name_reln
;
4228 unsigned int nlabelsp
;
4230 name_reln
= dns_name_fullcompare(name
, zone_name
, &orderp
, &nlabelsp
);
4231 if (name_reln
!= dns_namereln_subdomain
||
4232 dns_name_countlabels(name
) <= dns_name_countlabels(zone_name
) + 1) {
4233 printf("\n;; ERROR : ");
4234 dns_name_print(name
, stdout
);
4235 printf(" is not a subdomain of: ");
4236 dns_name_print(zone_name
, stdout
);
4237 printf(" FAILED\n\n");
4238 return (ISC_R_FAILURE
);
4241 dns_name_getlabelsequence(name
,
4242 dns_name_countlabels(name
) -
4243 dns_name_countlabels(zone_name
) -1,
4244 dns_name_countlabels(zone_name
) +1,
4246 return (ISC_R_SUCCESS
);
4250 grandfather_pb_test(dns_name_t
*zone_name
, dns_rdataset_t
*sigrdataset
)
4252 isc_result_t result
;
4253 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
4254 dns_rdata_sig_t siginfo
;
4256 result
= dns_rdataset_first(sigrdataset
);
4257 check_result(result
, "empty RRSIG dataset");
4258 dns_rdata_init(&sigrdata
);
4261 dns_rdataset_current(sigrdataset
, &sigrdata
);
4263 result
= dns_rdata_tostruct(&sigrdata
, &siginfo
, NULL
);
4264 check_result(result
, "sigrdata tostruct siginfo");
4266 if (dns_name_compare(&siginfo
.signer
, zone_name
) == 0) {
4267 dns_rdata_freestruct(&siginfo
);
4268 dns_rdata_reset(&sigrdata
);
4269 return (ISC_R_SUCCESS
);
4272 dns_rdata_freestruct(&siginfo
);
4273 dns_rdata_reset(&sigrdata
);
4275 } while (dns_rdataset_next(chase_sigkeyrdataset
) == ISC_R_SUCCESS
);
4277 dns_rdata_reset(&sigrdata
);
4279 return (ISC_R_FAILURE
);
4284 initialization(dns_name_t
*name
)
4286 isc_result_t result
;
4287 isc_boolean_t
true = ISC_TRUE
;
4289 chase_nsrdataset
= NULL
;
4290 result
= advanced_rrsearch(&chase_nsrdataset
, name
, dns_rdatatype_ns
,
4291 dns_rdatatype_any
, &true);
4292 if (result
!= ISC_R_SUCCESS
) {
4293 printf("\n;; NS RRset is missing to continue validation:"
4295 return (ISC_R_FAILURE
);
4297 INSIST(chase_nsrdataset
!= NULL
);
4298 prepare_lookup(name
);
4300 dup_name(name
, &chase_current_name
, mctx
);
4302 return (ISC_R_SUCCESS
);
4307 print_rdataset(dns_name_t
*name
, dns_rdataset_t
*rdataset
, isc_mem_t
*mctx
)
4309 isc_buffer_t
*b
= NULL
;
4310 isc_result_t result
;
4313 result
= isc_buffer_allocate(mctx
, &b
, 9000);
4314 check_result(result
, "isc_buffer_allocate");
4316 printrdataset(name
, rdataset
, b
);
4318 isc_buffer_usedregion(b
, &r
);
4319 r
.base
[r
.length
] = '\0';
4322 printf("%s\n", r
.base
);
4324 isc_buffer_free(&b
);
4329 dup_name(dns_name_t
*source
, dns_name_t
*target
, isc_mem_t
*mctx
) {
4330 isc_result_t result
;
4332 if (dns_name_dynamic(target
))
4333 free_name(target
, mctx
);
4334 result
= dns_name_dup(source
, mctx
, target
);
4335 check_result(result
, "dns_name_dup");
4339 free_name(dns_name_t
*name
, isc_mem_t
*mctx
) {
4340 dns_name_free(name
, mctx
);
4341 dns_name_init(name
, NULL
);
4346 * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter
4347 * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key
4348 * and the RRset is valid
4349 * return ISC_R_NOTFOUND if not contains trusted key
4350 or if the RRset isn't valid
4351 * return ISC_R_FAILURE if problem
4355 contains_trusted_key(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
4356 dns_rdataset_t
*sigrdataset
,
4359 isc_result_t result
;
4360 dns_rdata_t rdata
= DNS_RDATA_INIT
;
4361 dst_key_t
*trustedKey
= NULL
;
4362 dst_key_t
*dnsseckey
= NULL
;
4365 if (name
== NULL
|| rdataset
== NULL
)
4366 return (ISC_R_FAILURE
);
4368 result
= dns_rdataset_first(rdataset
);
4369 check_result(result
, "empty rdataset");
4372 dns_rdataset_current(rdataset
, &rdata
);
4373 INSIST(rdata
.type
== dns_rdatatype_dnskey
);
4375 result
= dns_dnssec_keyfromrdata(name
, &rdata
,
4377 check_result(result
, "dns_dnssec_keyfromrdata");
4380 for (i
= 0; i
< tk_list
.nb_tk
; i
++) {
4381 if (dst_key_compare(tk_list
.key
[i
], dnsseckey
)
4383 dns_rdata_reset(&rdata
);
4385 printf(";; Ok, find a Trusted Key in the "
4386 "DNSKEY RRset: %d\n",
4387 dst_key_id(dnsseckey
));
4388 if (sigchase_verify_sig_key(name
, rdataset
,
4393 dst_key_free(&dnsseckey
);
4395 return (ISC_R_SUCCESS
);
4400 dns_rdata_reset(&rdata
);
4401 if (dnsseckey
!= NULL
)
4402 dst_key_free(&dnsseckey
);
4403 } while (dns_rdataset_next(rdataset
) == ISC_R_SUCCESS
);
4405 if (trustedKey
!= NULL
)
4406 dst_key_free(&trustedKey
);
4409 return (ISC_R_NOTFOUND
);
4413 sigchase_verify_sig(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
4414 dns_rdataset_t
*keyrdataset
,
4415 dns_rdataset_t
*sigrdataset
,
4418 isc_result_t result
;
4419 dns_rdata_t keyrdata
= DNS_RDATA_INIT
;
4420 dst_key_t
*dnsseckey
= NULL
;
4422 result
= dns_rdataset_first(keyrdataset
);
4423 check_result(result
, "empty DNSKEY dataset");
4424 dns_rdata_init(&keyrdata
);
4427 dns_rdataset_current(keyrdataset
, &keyrdata
);
4428 INSIST(keyrdata
.type
== dns_rdatatype_dnskey
);
4430 result
= dns_dnssec_keyfromrdata(name
, &keyrdata
,
4432 check_result(result
, "dns_dnssec_keyfromrdata");
4434 result
= sigchase_verify_sig_key(name
, rdataset
, dnsseckey
,
4436 if (result
== ISC_R_SUCCESS
) {
4437 dns_rdata_reset(&keyrdata
);
4438 dst_key_free(&dnsseckey
);
4439 return (ISC_R_SUCCESS
);
4441 dst_key_free(&dnsseckey
);
4442 dns_rdata_reset(&keyrdata
);
4443 } while (dns_rdataset_next(chase_keyrdataset
) == ISC_R_SUCCESS
);
4445 dns_rdata_reset(&keyrdata
);
4447 return (ISC_R_NOTFOUND
);
4451 sigchase_verify_sig_key(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
4452 dst_key_t
*dnsseckey
, dns_rdataset_t
*sigrdataset
,
4455 isc_result_t result
;
4456 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
4457 dns_rdata_sig_t siginfo
;
4459 result
= dns_rdataset_first(sigrdataset
);
4460 check_result(result
, "empty RRSIG dataset");
4461 dns_rdata_init(&sigrdata
);
4464 dns_rdataset_current(sigrdataset
, &sigrdata
);
4466 result
= dns_rdata_tostruct(&sigrdata
, &siginfo
, NULL
);
4467 check_result(result
, "sigrdata tostruct siginfo");
4470 * Test if the id of the DNSKEY is
4471 * the id of the DNSKEY signer's
4473 if (siginfo
.keyid
== dst_key_id(dnsseckey
)) {
4475 result
= dns_rdataset_first(rdataset
);
4476 check_result(result
, "empty DS dataset");
4478 result
= dns_dnssec_verify(name
, rdataset
, dnsseckey
,
4479 ISC_FALSE
, mctx
, &sigrdata
);
4481 printf(";; VERIFYING ");
4482 print_type(rdataset
->type
);
4483 printf(" RRset for ");
4484 dns_name_print(name
, stdout
);
4485 printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey
),
4486 isc_result_totext(result
));
4488 if (result
== ISC_R_SUCCESS
) {
4489 dns_rdata_reset(&sigrdata
);
4493 dns_rdata_freestruct(&siginfo
);
4494 dns_rdata_reset(&sigrdata
);
4496 } while (dns_rdataset_next(chase_sigkeyrdataset
) == ISC_R_SUCCESS
);
4498 dns_rdata_reset(&sigrdata
);
4500 return (ISC_R_NOTFOUND
);
4505 sigchase_verify_ds(dns_name_t
*name
, dns_rdataset_t
*keyrdataset
,
4506 dns_rdataset_t
*dsrdataset
, isc_mem_t
*mctx
)
4508 isc_result_t result
;
4509 dns_rdata_t keyrdata
= DNS_RDATA_INIT
;
4510 dns_rdata_t newdsrdata
= DNS_RDATA_INIT
;
4511 dns_rdata_t dsrdata
= DNS_RDATA_INIT
;
4512 dns_rdata_ds_t dsinfo
;
4513 dst_key_t
*dnsseckey
= NULL
;
4514 unsigned char dsbuf
[DNS_DS_BUFFERSIZE
];
4516 result
= dns_rdataset_first(dsrdataset
);
4517 check_result(result
, "empty DSset dataset");
4519 dns_rdataset_current(dsrdataset
, &dsrdata
);
4521 result
= dns_rdata_tostruct(&dsrdata
, &dsinfo
, NULL
);
4522 check_result(result
, "dns_rdata_tostruct for DS");
4524 result
= dns_rdataset_first(keyrdataset
);
4525 check_result(result
, "empty KEY dataset");
4528 dns_rdataset_current(keyrdataset
, &keyrdata
);
4529 INSIST(keyrdata
.type
== dns_rdatatype_dnskey
);
4531 result
= dns_dnssec_keyfromrdata(name
, &keyrdata
,
4533 check_result(result
, "dns_dnssec_keyfromrdata");
4536 * Test if the id of the DNSKEY is the
4537 * id of DNSKEY referenced by the DS
4539 if (dsinfo
.key_tag
== dst_key_id(dnsseckey
)) {
4541 result
= dns_ds_buildrdata(name
, &keyrdata
,
4543 dsbuf
, &newdsrdata
);
4544 dns_rdata_freestruct(&dsinfo
);
4546 if (result
!= ISC_R_SUCCESS
) {
4547 dns_rdata_reset(&keyrdata
);
4548 dns_rdata_reset(&newdsrdata
);
4549 dns_rdata_reset(&dsrdata
);
4550 dst_key_free(&dnsseckey
);
4551 dns_rdata_freestruct(&dsinfo
);
4552 printf("Oops: impossible to build"
4558 if (dns_rdata_compare(&dsrdata
,
4559 &newdsrdata
) == 0) {
4560 printf(";; OK a DS valids a DNSKEY"
4562 printf(";; Now verify that this"
4563 " DNSKEY validates the "
4566 result
= sigchase_verify_sig_key(name
,
4569 chase_sigkeyrdataset
,
4571 if (result
== ISC_R_SUCCESS
) {
4572 dns_rdata_reset(&keyrdata
);
4573 dns_rdata_reset(&newdsrdata
);
4574 dns_rdata_reset(&dsrdata
);
4575 dst_key_free(&dnsseckey
);
4580 printf(";; This DS is NOT the DS for"
4581 " the chasing KEY: FAILED\n");
4584 dns_rdata_reset(&newdsrdata
);
4586 dst_key_free(&dnsseckey
);
4587 dns_rdata_reset(&keyrdata
);
4589 } while (dns_rdataset_next(chase_keyrdataset
) == ISC_R_SUCCESS
);
4590 dns_rdata_reset(&dsrdata
);
4592 } while (dns_rdataset_next(chase_dsrdataset
) == ISC_R_SUCCESS
);
4594 dns_rdata_reset(&keyrdata
);
4595 dns_rdata_reset(&newdsrdata
);
4596 dns_rdata_reset(&dsrdata
);
4598 return (ISC_R_NOTFOUND
);
4603 * take a pointer on a rdataset in parameter and try to resolv it.
4604 * the searched rrset is a rrset on 'name' with type 'type'
4605 * (and if the type is a rrsig the signature cover 'covers').
4606 * the lookedup is to known if you have already done the query on the net.
4607 * ISC_R_SUCCESS: if we found the rrset
4608 * ISC_R_NOTFOUND: we do not found the rrset in cache
4609 * and we do a query on the net
4610 * ISC_R_FAILURE: rrset not found
4613 advanced_rrsearch(dns_rdataset_t
**rdataset
, dns_name_t
*name
,
4614 dns_rdatatype_t type
, dns_rdatatype_t covers
,
4615 isc_boolean_t
*lookedup
)
4617 isc_boolean_t tmplookedup
;
4619 INSIST(rdataset
!= NULL
);
4621 if (*rdataset
!= NULL
)
4622 return (ISC_R_SUCCESS
);
4624 tmplookedup
= *lookedup
;
4625 if ((*rdataset
= sigchase_scanname(type
, covers
,
4626 lookedup
, name
)) == NULL
) {
4628 return (ISC_R_FAILURE
);
4629 return (ISC_R_NOTFOUND
);
4631 *lookedup
= ISC_FALSE
;
4632 return (ISC_R_SUCCESS
);
4639 sigchase_td(dns_message_t
*msg
)
4641 isc_result_t result
;
4642 dns_name_t
*name
= NULL
;
4643 isc_boolean_t have_answer
= ISC_FALSE
;
4644 isc_boolean_t
true = ISC_TRUE
;
4646 if ((result
= dns_message_firstname(msg
, DNS_SECTION_ANSWER
))
4648 dns_message_currentname(msg
, DNS_SECTION_ANSWER
, &name
);
4649 if (current_lookup
->trace_root_sigchase
) {
4650 initialization(name
);
4655 if (!current_lookup
->trace_root_sigchase
) {
4656 result
= dns_message_firstname(msg
,
4657 DNS_SECTION_AUTHORITY
);
4658 if (result
== ISC_R_SUCCESS
)
4659 dns_message_currentname(msg
,
4660 DNS_SECTION_AUTHORITY
,
4663 = chase_scanname_section(msg
, name
,
4666 DNS_SECTION_AUTHORITY
);
4667 dup_name(name
, &chase_authority_name
, mctx
);
4668 if (chase_nsrdataset
!= NULL
) {
4669 have_delegation_ns
= ISC_TRUE
;
4670 printf("no response but there is a delegation"
4671 " in authority section:");
4672 dns_name_print(name
, stdout
);
4675 printf("no response and no delegation in "
4676 "authority section but a reference"
4678 dns_name_print(name
, stdout
);
4680 error_message
= msg
;
4683 printf(";; NO ANSWERS: %s\n",
4684 isc_result_totext(result
));
4685 free_name(&chase_name
, mctx
);
4694 = chase_scanname_section(msg
, &chase_name
,
4698 DNS_SECTION_ANSWER
);
4699 if (chase_rdataset
!= NULL
)
4700 have_response
= ISC_TRUE
;
4703 result
= advanced_rrsearch(&chase_keyrdataset
,
4704 &chase_current_name
,
4705 dns_rdatatype_dnskey
,
4707 &chase_keylookedup
);
4708 if (result
== ISC_R_FAILURE
) {
4709 printf("\n;; DNSKEY is missing to continue validation:"
4713 if (result
== ISC_R_NOTFOUND
)
4715 INSIST(chase_keyrdataset
!= NULL
);
4716 printf("\n;; DNSKEYset:\n");
4717 print_rdataset(&chase_current_name
, chase_keyrdataset
, mctx
);
4720 result
= advanced_rrsearch(&chase_sigkeyrdataset
,
4721 &chase_current_name
,
4722 dns_rdatatype_rrsig
,
4723 dns_rdatatype_dnskey
,
4724 &chase_sigkeylookedup
);
4725 if (result
== ISC_R_FAILURE
) {
4726 printf("\n;; RRSIG of DNSKEY is missing to continue validation:"
4730 if (result
== ISC_R_NOTFOUND
)
4732 INSIST(chase_sigkeyrdataset
!= NULL
);
4733 printf("\n;; RRSIG of the DNSKEYset:\n");
4734 print_rdataset(&chase_current_name
, chase_sigkeyrdataset
, mctx
);
4737 if (!chase_dslookedup
&& !chase_nslookedup
) {
4738 if (!delegation_follow
) {
4739 result
= contains_trusted_key(&chase_current_name
,
4741 chase_sigkeyrdataset
,
4744 INSIST(chase_dsrdataset
!= NULL
);
4745 INSIST(chase_sigdsrdataset
!= NULL
);
4746 result
= sigchase_verify_ds(&chase_current_name
,
4752 if (result
!= ISC_R_SUCCESS
) {
4753 printf("\n;; chain of trust can't be validated:"
4757 chase_dsrdataset
= NULL
;
4758 chase_sigdsrdataset
= NULL
;
4762 if (have_response
|| (!have_delegation_ns
&& !have_response
)) {
4763 /* test if it's a grand father case */
4765 if (have_response
) {
4766 result
= advanced_rrsearch(&chase_sigrdataset
,
4768 dns_rdatatype_rrsig
,
4772 if (result
== ISC_R_FAILURE
) {
4773 printf("\n;; RRset is missing to continue"
4774 " validation SHOULD NOT APPEND:"
4780 result
= advanced_rrsearch(&chase_sigrdataset
,
4781 &chase_authority_name
,
4782 dns_rdatatype_rrsig
,
4785 if (result
== ISC_R_FAILURE
) {
4786 printf("\n;; RRSIG is missing to continue"
4787 " validation SHOULD NOT APPEND:"
4792 result
= grandfather_pb_test(&chase_current_name
,
4794 if (result
!= ISC_R_SUCCESS
) {
4795 dns_name_t tmp_name
;
4797 printf("\n;; We are in a Grand Father Problem:"
4798 " See 2.2.1 in RFC 3568\n");
4799 chase_rdataset
= NULL
;
4800 chase_sigrdataset
= NULL
;
4801 have_response
= ISC_FALSE
;
4802 have_delegation_ns
= ISC_FALSE
;
4804 dns_name_init(&tmp_name
, NULL
);
4805 result
= child_of_zone(&chase_name
, &chase_current_name
,
4807 if (dns_name_dynamic(&chase_authority_name
))
4808 free_name(&chase_authority_name
, mctx
);
4809 dup_name(&tmp_name
, &chase_authority_name
, mctx
);
4810 printf(";; and we try to continue chain of trust"
4811 " validation of the zone: ");
4812 dns_name_print(&chase_authority_name
, stdout
);
4814 have_delegation_ns
= ISC_TRUE
;
4819 chase_sigrdataset
= NULL
;
4823 if (have_delegation_ns
) {
4824 chase_nsrdataset
= NULL
;
4825 result
= advanced_rrsearch(&chase_nsrdataset
,
4826 &chase_authority_name
,
4830 if (result
== ISC_R_FAILURE
) {
4831 printf("\n;;NSset is missing to continue validation:"
4835 if (result
== ISC_R_NOTFOUND
) {
4838 INSIST(chase_nsrdataset
!= NULL
);
4840 result
= advanced_rrsearch(&chase_dsrdataset
,
4841 &chase_authority_name
,
4845 if (result
== ISC_R_FAILURE
) {
4846 printf("\n;; DSset is missing to continue validation:"
4850 if (result
== ISC_R_NOTFOUND
)
4852 INSIST(chase_dsrdataset
!= NULL
);
4853 printf("\n;; DSset:\n");
4854 print_rdataset(&chase_authority_name
, chase_dsrdataset
, mctx
);
4856 result
= advanced_rrsearch(&chase_sigdsrdataset
,
4857 &chase_authority_name
,
4858 dns_rdatatype_rrsig
,
4861 if (result
!= ISC_R_SUCCESS
) {
4862 printf("\n;; DSset is missing to continue validation:"
4866 printf("\n;; RRSIGset of DSset\n");
4867 print_rdataset(&chase_authority_name
,
4868 chase_sigdsrdataset
, mctx
);
4869 INSIST(chase_sigdsrdataset
!= NULL
);
4871 result
= sigchase_verify_sig(&chase_authority_name
,
4874 chase_sigdsrdataset
, mctx
);
4875 if (result
!= ISC_R_SUCCESS
) {
4876 printf("\n;; Impossible to verify the DSset:"
4880 chase_keyrdataset
= NULL
;
4881 chase_sigkeyrdataset
= NULL
;
4884 prepare_lookup(&chase_authority_name
);
4886 have_response
= ISC_FALSE
;
4887 have_delegation_ns
= ISC_FALSE
;
4888 delegation_follow
= ISC_TRUE
;
4889 error_message
= NULL
;
4890 dup_name(&chase_authority_name
, &chase_current_name
, mctx
);
4891 free_name(&chase_authority_name
, mctx
);
4896 if (error_message
!= NULL
) {
4897 dns_rdataset_t
*rdataset
;
4898 dns_rdataset_t
*sigrdataset
;
4899 dns_name_t rdata_name
;
4900 isc_result_t ret
= ISC_R_FAILURE
;
4902 dns_name_init(&rdata_name
, NULL
);
4903 result
= prove_nx(error_message
, &chase_name
,
4904 current_lookup
->rdclass_sigchase
,
4905 current_lookup
->rdtype_sigchase
, &rdata_name
,
4906 &rdataset
, &sigrdataset
);
4907 if (rdataset
== NULL
|| sigrdataset
== NULL
||
4908 dns_name_countlabels(&rdata_name
) == 0) {
4909 printf("\n;; Impossible to verify the non-existence,"
4910 " the NSEC RRset can't be validated:"
4914 ret
= sigchase_verify_sig(&rdata_name
, rdataset
,
4917 if (ret
!= ISC_R_SUCCESS
) {
4918 free_name(&rdata_name
, mctx
);
4919 printf("\n;; Impossible to verify the NSEC RR to prove"
4920 " the non-existence : FAILED\n\n");
4923 free_name(&rdata_name
, mctx
);
4924 if (result
!= ISC_R_SUCCESS
) {
4925 printf("\n;; Impossible to verify the non-existence:"
4929 printf("\n;; OK the query doesn't have response but"
4930 " we have validate this fact : SUCCESS\n\n");
4936 printf(";; cleanandgo \n");
4937 if (dns_name_dynamic(&chase_current_name
))
4938 free_name(&chase_current_name
, mctx
);
4939 if (dns_name_dynamic(&chase_authority_name
))
4940 free_name(&chase_authority_name
, mctx
);
4945 result
= advanced_rrsearch(&chase_rdataset
, &chase_name
,
4946 current_lookup
->rdtype_sigchase
,
4949 if (result
== ISC_R_FAILURE
) {
4950 printf("\n;; RRsig of RRset is missing to continue validation"
4951 " SHOULD NOT APPEND: FAILED\n\n");
4954 result
= sigchase_verify_sig(&chase_name
, chase_rdataset
,
4956 chase_sigrdataset
, mctx
);
4957 if (result
!= ISC_R_SUCCESS
) {
4958 printf("\n;; Impossible to verify the RRset : FAILED\n\n");
4961 print_rdataset(&chase_name , chase_rdataset, mctx);
4962 printf("DNSKEYset:\n");
4963 print_rdataset(&chase_name , chase_keyrdataset, mctx);
4964 printf("RRSIG of RRset:\n");
4965 print_rdataset(&chase_name , chase_sigrdataset, mctx);
4970 printf("\n;; The Answer:\n");
4971 print_rdataset(&chase_name
, chase_rdataset
, mctx
);
4973 printf("\n;; FINISH : we have validate the DNSSEC chain"
4974 " of trust: SUCCESS\n\n");
4985 getneededrr(dns_message_t
*msg
)
4987 isc_result_t result
;
4988 dns_name_t
*name
= NULL
;
4989 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
4990 dns_rdata_sig_t siginfo
;
4991 isc_boolean_t
true = ISC_TRUE
;
4993 if ((result
= dns_message_firstname(msg
, DNS_SECTION_ANSWER
))
4995 printf(";; NO ANSWERS: %s\n", isc_result_totext(result
));
4997 if (chase_name
.ndata
== NULL
)
4998 return (ISC_R_ADDRNOTAVAIL
);
5000 dns_message_currentname(msg
, DNS_SECTION_ANSWER
, &name
);
5003 /* What do we chase? */
5004 if (chase_rdataset
== NULL
) {
5005 result
= advanced_rrsearch(&chase_rdataset
, name
,
5007 dns_rdatatype_any
, &true);
5008 if (result
!= ISC_R_SUCCESS
) {
5009 printf("\n;; No Answers: Validation FAILED\n\n");
5010 return (ISC_R_NOTFOUND
);
5012 dup_name(name
, &chase_name
, mctx
);
5013 printf(";; RRset to chase:\n");
5014 print_rdataset(&chase_name
, chase_rdataset
, mctx
);
5016 INSIST(chase_rdataset
!= NULL
);
5019 if (chase_sigrdataset
== NULL
) {
5020 result
= advanced_rrsearch(&chase_sigrdataset
, name
,
5021 dns_rdatatype_rrsig
,
5022 chase_rdataset
->type
,
5023 &chase_siglookedup
);
5024 if (result
== ISC_R_FAILURE
) {
5025 printf("\n;; RRSIG is missing for continue validation:"
5027 if (dns_name_dynamic(&chase_name
))
5028 free_name(&chase_name
, mctx
);
5029 return (ISC_R_NOTFOUND
);
5031 if (result
== ISC_R_NOTFOUND
) {
5032 return (ISC_R_NOTFOUND
);
5034 printf("\n;; RRSIG of the RRset to chase:\n");
5035 print_rdataset(&chase_name
, chase_sigrdataset
, mctx
);
5037 INSIST(chase_sigrdataset
!= NULL
);
5040 /* first find the DNSKEY name */
5041 result
= dns_rdataset_first(chase_sigrdataset
);
5042 check_result(result
, "empty RRSIG dataset");
5043 dns_rdataset_current(chase_sigrdataset
, &sigrdata
);
5044 result
= dns_rdata_tostruct(&sigrdata
, &siginfo
, NULL
);
5045 check_result(result
, "sigrdata tostruct siginfo");
5046 dup_name(&siginfo
.signer
, &chase_signame
, mctx
);
5047 dns_rdata_freestruct(&siginfo
);
5048 dns_rdata_reset(&sigrdata
);
5050 /* Do we have a key? */
5051 if (chase_keyrdataset
== NULL
) {
5052 result
= advanced_rrsearch(&chase_keyrdataset
,
5054 dns_rdatatype_dnskey
,
5056 &chase_keylookedup
);
5057 if (result
== ISC_R_FAILURE
) {
5058 printf("\n;; DNSKEY is missing to continue validation:"
5060 free_name(&chase_signame
, mctx
);
5061 if (dns_name_dynamic(&chase_name
))
5062 free_name(&chase_name
, mctx
);
5063 return (ISC_R_NOTFOUND
);
5065 if (result
== ISC_R_NOTFOUND
) {
5066 free_name(&chase_signame
, mctx
);
5067 return (ISC_R_NOTFOUND
);
5069 printf("\n;; DNSKEYset that signs the RRset to chase:\n");
5070 print_rdataset(&chase_signame
, chase_keyrdataset
, mctx
);
5072 INSIST(chase_keyrdataset
!= NULL
);
5074 if (chase_sigkeyrdataset
== NULL
) {
5075 result
= advanced_rrsearch(&chase_sigkeyrdataset
,
5077 dns_rdatatype_rrsig
,
5078 dns_rdatatype_dnskey
,
5079 &chase_sigkeylookedup
);
5080 if (result
== ISC_R_FAILURE
) {
5081 printf("\n;; RRSIG for DNSKEY is missing to continue"
5082 " validation : FAILED\n\n");
5083 free_name(&chase_signame
, mctx
);
5084 if (dns_name_dynamic(&chase_name
))
5085 free_name(&chase_name
, mctx
);
5086 return (ISC_R_NOTFOUND
);
5088 if (result
== ISC_R_NOTFOUND
) {
5089 free_name(&chase_signame
, mctx
);
5090 return (ISC_R_NOTFOUND
);
5092 printf("\n;; RRSIG of the DNSKEYset that signs the "
5093 "RRset to chase:\n");
5094 print_rdataset(&chase_signame
, chase_sigkeyrdataset
, mctx
);
5096 INSIST(chase_sigkeyrdataset
!= NULL
);
5099 if (chase_dsrdataset
== NULL
) {
5100 result
= advanced_rrsearch(&chase_dsrdataset
, &chase_signame
,
5104 if (result
== ISC_R_FAILURE
) {
5105 printf("\n;; WARNING There is no DS for the zone: ");
5106 dns_name_print(&chase_signame
, stdout
);
5109 if (result
== ISC_R_NOTFOUND
) {
5110 free_name(&chase_signame
, mctx
);
5111 return (ISC_R_NOTFOUND
);
5113 if (chase_dsrdataset
!= NULL
) {
5114 printf("\n;; DSset of the DNSKEYset\n");
5115 print_rdataset(&chase_signame
, chase_dsrdataset
, mctx
);
5119 if (chase_dsrdataset
!= NULL
) {
5121 * if there is no RRSIG of DS,
5122 * we don't want to search on the network
5124 result
= advanced_rrsearch(&chase_sigdsrdataset
,
5126 dns_rdatatype_rrsig
,
5127 dns_rdatatype_ds
, &true);
5128 if (result
== ISC_R_FAILURE
) {
5129 printf(";; WARNING : NO RRSIG DS : RRSIG DS"
5130 " should come with DS\n");
5132 * We continue even the DS couldn't be validated,
5133 * because the DNSKEY could be a Trusted Key.
5135 chase_dsrdataset
= NULL
;
5137 printf("\n;; RRSIG of the DSset of the DNSKEYset\n");
5138 print_rdataset(&chase_signame
, chase_sigdsrdataset
,
5148 sigchase_bu(dns_message_t
*msg
)
5150 isc_result_t result
;
5153 if (tk_list
.nb_tk
== 0) {
5154 result
= get_trusted_key(mctx
);
5155 if (result
!= ISC_R_SUCCESS
) {
5156 printf("No trusted keys present\n");
5162 ret
= getneededrr(msg
);
5163 if (ret
== ISC_R_NOTFOUND
)
5166 if (ret
== ISC_R_ADDRNOTAVAIL
) {
5167 /* We have no response */
5168 dns_rdataset_t
*rdataset
;
5169 dns_rdataset_t
*sigrdataset
;
5170 dns_name_t rdata_name
;
5171 dns_name_t query_name
;
5174 dns_name_init(&query_name
, NULL
);
5175 dns_name_init(&rdata_name
, NULL
);
5176 nameFromString(current_lookup
->textname
, &query_name
);
5178 result
= prove_nx(msg
, &query_name
, current_lookup
->rdclass
,
5179 current_lookup
->rdtype
, &rdata_name
,
5180 &rdataset
, &sigrdataset
);
5181 free_name(&query_name
, mctx
);
5182 if (rdataset
== NULL
|| sigrdataset
== NULL
||
5183 dns_name_countlabels(&rdata_name
) == 0) {
5184 printf("\n;; Impossible to verify the Non-existence,"
5185 " the NSEC RRset can't be validated: "
5191 if (result
!= ISC_R_SUCCESS
) {
5192 printf("\n No Answers and impossible to prove the"
5193 " unsecurity : Validation FAILED\n\n");
5197 printf(";; An NSEC prove the non-existence of a answers,"
5198 " Now we want validate this NSEC\n");
5200 dup_name(&rdata_name
, &chase_name
, mctx
);
5201 free_name(&rdata_name
, mctx
);
5202 chase_rdataset
= rdataset
;
5203 chase_sigrdataset
= sigrdataset
;
5204 chase_keyrdataset
= NULL
;
5205 chase_sigkeyrdataset
= NULL
;
5206 chase_dsrdataset
= NULL
;
5207 chase_sigdsrdataset
= NULL
;
5208 chase_siglookedup
= ISC_FALSE
;
5209 chase_keylookedup
= ISC_FALSE
;
5210 chase_dslookedup
= ISC_FALSE
;
5211 chase_sigdslookedup
= ISC_FALSE
;
5218 printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n");
5220 result
= sigchase_verify_sig(&chase_name
, chase_rdataset
,
5222 chase_sigrdataset
, mctx
);
5223 if (result
!= ISC_R_SUCCESS
) {
5224 free_name(&chase_name
, mctx
);
5225 free_name(&chase_signame
, mctx
);
5226 printf(";; No DNSKEY is valid to check the RRSIG"
5227 " of the RRset: FAILED\n");
5231 printf(";; OK We found DNSKEY (or more) to validate the RRset\n");
5233 result
= contains_trusted_key(&chase_signame
, chase_keyrdataset
,
5234 chase_sigkeyrdataset
, mctx
);
5235 if (result
== ISC_R_SUCCESS
) {
5236 free_name(&chase_name
, mctx
);
5237 free_name(&chase_signame
, mctx
);
5238 printf("\n;; Ok this DNSKEY is a Trusted Key,"
5239 " DNSSEC validation is ok: SUCCESS\n\n");
5244 printf(";; Now, we are going to validate this DNSKEY by the DS\n");
5246 if (chase_dsrdataset
== NULL
) {
5247 free_name(&chase_name
, mctx
);
5248 free_name(&chase_signame
, mctx
);
5249 printf(";; the DNSKEY isn't trusted-key and there isn't"
5250 " DS to validate the DNSKEY: FAILED\n");
5255 result
= sigchase_verify_ds(&chase_signame
, chase_keyrdataset
,
5256 chase_dsrdataset
, mctx
);
5257 if (result
!= ISC_R_SUCCESS
) {
5258 free_name(&chase_signame
, mctx
);
5259 free_name(&chase_name
, mctx
);
5260 printf(";; ERROR no DS validates a DNSKEY in the"
5261 " DNSKEY RRset: FAILED\n");
5265 printf(";; OK this DNSKEY (validated by the DS) validates"
5266 " the RRset of the DNSKEYs, thus the DNSKEY validates"
5268 INSIST(chase_sigdsrdataset
!= NULL
);
5270 dup_name(&chase_signame
, &chase_name
, mctx
);
5271 free_name(&chase_signame
, mctx
);
5272 chase_rdataset
= chase_dsrdataset
;
5273 chase_sigrdataset
= chase_sigdsrdataset
;
5274 chase_keyrdataset
= NULL
;
5275 chase_sigkeyrdataset
= NULL
;
5276 chase_dsrdataset
= NULL
;
5277 chase_sigdsrdataset
= NULL
;
5278 chase_siglookedup
= chase_keylookedup
= ISC_FALSE
;
5279 chase_dslookedup
= chase_sigdslookedup
= ISC_FALSE
;
5281 printf(";; Now, we want to validate the DS : recursive call\n");
5288 sigchase(dns_message_t
*msg
) {
5290 if (current_lookup
->do_topdown
) {
5303 * return 1 if name1 < name2
5304 * 0 if name1 == name2
5305 * -1 if name1 > name2
5309 inf_name(dns_name_t
*name1
, dns_name_t
*name2
)
5313 unsigned int nblabel1
;
5314 unsigned int nblabel2
;
5319 nblabel1
= dns_name_countlabels(name1
);
5320 nblabel2
= dns_name_countlabels(name2
);
5322 if (nblabel1
>= nblabel2
)
5323 min_lum_label
= nblabel2
;
5325 min_lum_label
= nblabel1
;
5328 for (i
=1 ; i
< min_lum_label
; i
++) {
5329 dns_name_getlabel(name1
, nblabel1
-1 - i
, &label1
);
5330 dns_name_getlabel(name2
, nblabel2
-1 - i
, &label2
);
5331 if ((ret
= isc_region_compare(&label1
, &label2
)) != 0) {
5338 if (nblabel1
== nblabel2
)
5341 if (nblabel1
< nblabel2
)
5353 prove_nx_domain(dns_message_t
*msg
,
5355 dns_name_t
*rdata_name
,
5356 dns_rdataset_t
**rdataset
,
5357 dns_rdataset_t
**sigrdataset
)
5359 isc_result_t ret
= ISC_R_FAILURE
;
5360 isc_result_t result
= ISC_R_NOTFOUND
;
5361 dns_rdataset_t
*nsecset
= NULL
;
5362 dns_rdataset_t
*signsecset
= NULL
;
5363 dns_rdata_t nsec
= DNS_RDATA_INIT
;
5364 dns_name_t
*nsecname
;
5365 dns_rdata_nsec_t nsecstruct
;
5367 if ((result
= dns_message_firstname(msg
, DNS_SECTION_AUTHORITY
))
5369 printf(";; nothing in authority section : impossible to"
5370 " validate the non-existence : FAILED\n");
5371 return (ISC_R_FAILURE
);
5376 dns_message_currentname(msg
, DNS_SECTION_AUTHORITY
, &nsecname
);
5377 nsecset
= search_type(nsecname
, dns_rdatatype_nsec
,
5379 if (nsecset
== NULL
)
5382 printf("There is a NSEC for this zone in the"
5383 " AUTHORITY section:\n");
5384 print_rdataset(nsecname
, nsecset
, mctx
);
5386 for (result
= dns_rdataset_first(nsecset
);
5387 result
== ISC_R_SUCCESS
;
5388 result
= dns_rdataset_next(nsecset
)) {
5389 dns_rdataset_current(nsecset
, &nsec
);
5393 = chase_scanname_section(msg
, nsecname
,
5394 dns_rdatatype_rrsig
,
5396 DNS_SECTION_AUTHORITY
);
5397 if (signsecset
== NULL
) {
5398 printf(";; no RRSIG NSEC in authority section:"
5399 " impossible to validate the "
5400 "non-existence: FAILED\n");
5401 return (ISC_R_FAILURE
);
5404 ret
= dns_rdata_tostruct(&nsec
, &nsecstruct
, NULL
);
5405 check_result(ret
,"dns_rdata_tostruct");
5407 if ((inf_name(nsecname
, &nsecstruct
.next
) == 1 &&
5408 inf_name(name
, &nsecstruct
.next
) == 1) ||
5409 (inf_name(name
, nsecname
) == 1 &&
5410 inf_name(&nsecstruct
.next
, name
) == 1)) {
5411 dns_rdata_freestruct(&nsecstruct
);
5412 *rdataset
= nsecset
;
5413 *sigrdataset
= signsecset
;
5414 dup_name(nsecname
, rdata_name
, mctx
);
5416 return (ISC_R_SUCCESS
);
5419 dns_rdata_freestruct(&nsecstruct
);
5420 dns_rdata_reset(&nsec
);
5422 } while (dns_message_nextname(msg
, DNS_SECTION_AUTHORITY
)
5426 *sigrdataset
= NULL
;
5428 return (ISC_R_FAILURE
);
5439 prove_nx_type(dns_message_t
*msg
, dns_name_t
*name
, dns_rdataset_t
*nsecset
,
5440 dns_rdataclass_t
class, dns_rdatatype_t type
,
5441 dns_name_t
*rdata_name
, dns_rdataset_t
**rdataset
,
5442 dns_rdataset_t
**sigrdataset
)
5445 dns_rdataset_t
*signsecset
;
5446 dns_rdata_t nsec
= DNS_RDATA_INIT
;
5450 ret
= dns_rdataset_first(nsecset
);
5451 check_result(ret
,"dns_rdataset_first");
5453 dns_rdataset_current(nsecset
, &nsec
);
5455 ret
= dns_nsec_typepresent(&nsec
, type
);
5456 if (ret
== ISC_R_SUCCESS
)
5457 printf("OK the NSEC said that the type doesn't exist \n");
5459 signsecset
= chase_scanname_section(msg
, name
,
5460 dns_rdatatype_rrsig
,
5462 DNS_SECTION_AUTHORITY
);
5463 if (signsecset
== NULL
) {
5464 printf("There isn't RRSIG NSEC for the zone \n");
5465 return (ISC_R_FAILURE
);
5467 dup_name(name
, rdata_name
, mctx
);
5468 *rdataset
= nsecset
;
5469 *sigrdataset
= signsecset
;
5481 prove_nx(dns_message_t
*msg
, dns_name_t
*name
, dns_rdataclass_t
class,
5482 dns_rdatatype_t type
, dns_name_t
*rdata_name
,
5483 dns_rdataset_t
**rdataset
, dns_rdataset_t
**sigrdataset
)
5486 dns_rdataset_t
*nsecset
= NULL
;
5488 printf("We want to prove the non-existence of a type of rdata %d"
5489 " or of the zone: \n", type
);
5491 if ((ret
= dns_message_firstname(msg
, DNS_SECTION_AUTHORITY
))
5493 printf(";; nothing in authority section : impossible to"
5494 " validate the non-existence : FAILED\n");
5495 return (ISC_R_FAILURE
);
5498 nsecset
= chase_scanname_section(msg
, name
, dns_rdatatype_nsec
,
5500 DNS_SECTION_AUTHORITY
);
5501 if (nsecset
!= NULL
) {
5502 printf("We have a NSEC for this zone :OK\n");
5503 ret
= prove_nx_type(msg
, name
, nsecset
, class,
5504 type
, rdata_name
, rdataset
,
5506 if (ret
!= ISC_R_SUCCESS
) {
5507 printf("prove_nx: ERROR type exist\n");
5510 printf("prove_nx: OK type does not exist\n");
5511 return (ISC_R_SUCCESS
);
5514 printf("there is no NSEC for this zone: validating "
5515 "that the zone doesn't exist\n");
5516 ret
= prove_nx_domain(msg
, name
, rdata_name
,
5517 rdataset
, sigrdataset
);
5520 /* Never get here */