2 * Copyright (C) 2004-2008 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.259.18.43.10.3 2008/07/23 23:16:43 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
, ...) {
496 fprintf(stderr
, "%s: ", progname
);
497 va_start(args
, format
);
498 vfprintf(stderr
, format
, args
);
500 fprintf(stderr
, "\n");
504 exitcode
= fatalexit
;
509 debug(const char *format
, ...) {
513 va_start(args
, format
);
514 vfprintf(stderr
, format
, args
);
516 fprintf(stderr
, "\n");
521 check_result(isc_result_t result
, const char *msg
) {
522 if (result
!= ISC_R_SUCCESS
) {
523 fatal("%s: %s", msg
, isc_result_totext(result
));
528 * Create a server structure, which is part of the lookup structure.
529 * This is little more than a linked list of servers to query in hopes
530 * of finding the answer the user is looking for
533 make_server(const char *servname
, const char *userarg
) {
536 REQUIRE(servname
!= NULL
);
538 debug("make_server(%s)", servname
);
539 srv
= isc_mem_allocate(mctx
, sizeof(struct dig_server
));
541 fatal("memory allocation failure in %s:%d",
543 strncpy(srv
->servername
, servname
, MXNAME
);
544 strncpy(srv
->userarg
, userarg
, MXNAME
);
545 srv
->servername
[MXNAME
-1] = 0;
546 srv
->userarg
[MXNAME
-1] = 0;
547 ISC_LINK_INIT(srv
, link
);
552 addr2af(int lwresaddrtype
)
556 switch (lwresaddrtype
) {
557 case LWRES_ADDRTYPE_V4
:
561 case LWRES_ADDRTYPE_V6
:
570 * Create a copy of the server list from the lwres configuration structure.
571 * The dest list must have already had ISC_LIST_INIT applied.
574 copy_server_list(lwres_conf_t
*confdata
, dig_serverlist_t
*dest
) {
575 dig_server_t
*newsrv
;
576 char tmp
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
580 debug("copy_server_list()");
581 for (i
= 0; i
< confdata
->nsnext
; i
++) {
582 af
= addr2af(confdata
->nameservers
[i
].family
);
584 lwres_net_ntop(af
, confdata
->nameservers
[i
].address
,
586 newsrv
= make_server(tmp
, tmp
);
587 ISC_LINK_INIT(newsrv
, link
);
588 ISC_LIST_ENQUEUE(*dest
, newsrv
, link
);
593 flush_server_list(void) {
594 dig_server_t
*s
, *ps
;
596 debug("flush_server_list()");
597 s
= ISC_LIST_HEAD(server_list
);
600 s
= ISC_LIST_NEXT(s
, link
);
601 ISC_LIST_DEQUEUE(server_list
, ps
, link
);
602 isc_mem_free(mctx
, ps
);
607 set_nameserver(char *opt
) {
609 isc_sockaddr_t sockaddrs
[DIG_MAX_ADDRESSES
];
610 isc_netaddr_t netaddr
;
613 char tmp
[ISC_NETADDR_FORMATSIZE
];
618 result
= bind9_getaddresses(opt
, 0, sockaddrs
,
619 DIG_MAX_ADDRESSES
, &count
);
620 if (result
!= ISC_R_SUCCESS
)
621 fatal("couldn't get address for '%s': %s",
622 opt
, isc_result_totext(result
));
626 for (i
= 0; i
< count
; i
++) {
627 isc_netaddr_fromsockaddr(&netaddr
, &sockaddrs
[i
]);
628 isc_netaddr_format(&netaddr
, tmp
, sizeof(tmp
));
629 srv
= make_server(tmp
, opt
);
631 fatal("memory allocation failure");
632 ISC_LIST_APPEND(server_list
, srv
, link
);
637 add_nameserver(lwres_conf_t
*confdata
, const char *addr
, int af
) {
639 int i
= confdata
->nsnext
;
641 if (confdata
->nsnext
>= LWRES_CONFMAXNAMESERVERS
)
642 return (ISC_R_FAILURE
);
646 confdata
->nameservers
[i
].family
= LWRES_ADDRTYPE_V4
;
647 confdata
->nameservers
[i
].length
= NS_INADDRSZ
;
650 confdata
->nameservers
[i
].family
= LWRES_ADDRTYPE_V6
;
651 confdata
->nameservers
[i
].length
= NS_IN6ADDRSZ
;
654 return (ISC_R_FAILURE
);
657 if (lwres_net_pton(af
, addr
, &confdata
->nameservers
[i
].address
) == 1) {
659 return (ISC_R_SUCCESS
);
661 return (ISC_R_FAILURE
);
665 * Produce a cloned server list. The dest list must have already had
666 * ISC_LIST_INIT applied.
669 clone_server_list(dig_serverlist_t src
, dig_serverlist_t
*dest
) {
670 dig_server_t
*srv
, *newsrv
;
672 debug("clone_server_list()");
673 srv
= ISC_LIST_HEAD(src
);
674 while (srv
!= NULL
) {
675 newsrv
= make_server(srv
->servername
, srv
->userarg
);
676 ISC_LINK_INIT(newsrv
, link
);
677 ISC_LIST_ENQUEUE(*dest
, newsrv
, link
);
678 srv
= ISC_LIST_NEXT(srv
, link
);
683 * Create an empty lookup structure, which holds all the information needed
684 * to get an answer to a user's question. This structure contains two
685 * linked lists: the server list (servers to query) and the query list
686 * (outstanding queries which have been made to the listed servers).
689 make_empty_lookup(void) {
690 dig_lookup_t
*looknew
;
692 debug("make_empty_lookup()");
696 looknew
= isc_mem_allocate(mctx
, sizeof(struct dig_lookup
));
698 fatal("memory allocation failure in %s:%d",
700 looknew
->pending
= ISC_TRUE
;
701 looknew
->textname
[0] = 0;
702 looknew
->cmdline
[0] = 0;
703 looknew
->rdtype
= dns_rdatatype_a
;
704 looknew
->qrdtype
= dns_rdatatype_a
;
705 looknew
->rdclass
= dns_rdataclass_in
;
706 looknew
->rdtypeset
= ISC_FALSE
;
707 looknew
->rdclassset
= ISC_FALSE
;
708 looknew
->sendspace
= NULL
;
709 looknew
->sendmsg
= NULL
;
710 looknew
->name
= NULL
;
711 looknew
->oname
= NULL
;
712 looknew
->timer
= NULL
;
713 looknew
->xfr_q
= NULL
;
714 looknew
->current_query
= NULL
;
715 looknew
->doing_xfr
= ISC_FALSE
;
716 looknew
->ixfr_serial
= ISC_FALSE
;
717 looknew
->trace
= ISC_FALSE
;
718 looknew
->trace_root
= ISC_FALSE
;
719 looknew
->identify
= ISC_FALSE
;
720 looknew
->identify_previous_line
= ISC_FALSE
;
721 looknew
->ignore
= ISC_FALSE
;
722 looknew
->servfail_stops
= ISC_TRUE
;
723 looknew
->besteffort
= ISC_TRUE
;
724 looknew
->dnssec
= ISC_FALSE
;
726 looknew
->sigchase
= ISC_FALSE
;
728 looknew
->do_topdown
= ISC_FALSE
;
729 looknew
->trace_root_sigchase
= ISC_FALSE
;
730 looknew
->rdtype_sigchaseset
= ISC_FALSE
;
731 looknew
->rdtype_sigchase
= dns_rdatatype_any
;
732 looknew
->qrdtype_sigchase
= dns_rdatatype_any
;
733 looknew
->rdclass_sigchase
= dns_rdataclass_in
;
734 looknew
->rdclass_sigchaseset
= ISC_FALSE
;
737 looknew
->udpsize
= 0;
739 looknew
->recurse
= ISC_TRUE
;
740 looknew
->aaonly
= ISC_FALSE
;
741 looknew
->adflag
= ISC_FALSE
;
742 looknew
->cdflag
= ISC_FALSE
;
743 looknew
->ns_search_only
= ISC_FALSE
;
744 looknew
->origin
= NULL
;
745 looknew
->tsigctx
= NULL
;
746 looknew
->querysig
= NULL
;
747 looknew
->retries
= tries
;
748 looknew
->nsfound
= 0;
749 looknew
->tcp_mode
= ISC_FALSE
;
750 looknew
->ip6_int
= ISC_FALSE
;
751 looknew
->comments
= ISC_TRUE
;
752 looknew
->stats
= ISC_TRUE
;
753 looknew
->section_question
= ISC_TRUE
;
754 looknew
->section_answer
= ISC_TRUE
;
755 looknew
->section_authority
= ISC_TRUE
;
756 looknew
->section_additional
= ISC_TRUE
;
757 looknew
->new_search
= ISC_FALSE
;
758 looknew
->done_as_is
= ISC_FALSE
;
759 looknew
->need_search
= ISC_FALSE
;
760 ISC_LINK_INIT(looknew
, link
);
761 ISC_LIST_INIT(looknew
->q
);
762 ISC_LIST_INIT(looknew
->my_server_list
);
767 * Clone a lookup, perhaps copying the server list. This does not clone
768 * the query list, since it will be regenerated by the setup_lookup()
769 * function, nor does it queue up the new lookup for processing.
770 * Caution: If you don't clone the servers, you MUST clone the server
771 * list seperately from somewhere else, or construct it by hand.
774 clone_lookup(dig_lookup_t
*lookold
, isc_boolean_t servers
) {
775 dig_lookup_t
*looknew
;
777 debug("clone_lookup()");
781 looknew
= make_empty_lookup();
782 INSIST(looknew
!= NULL
);
783 strncpy(looknew
->textname
, lookold
->textname
, MXNAME
);
785 strncpy(looknew
->textnamesigchase
, lookold
->textnamesigchase
, MXNAME
);
787 strncpy(looknew
->cmdline
, lookold
->cmdline
, MXNAME
);
788 looknew
->textname
[MXNAME
-1] = 0;
789 looknew
->rdtype
= lookold
->rdtype
;
790 looknew
->qrdtype
= lookold
->qrdtype
;
791 looknew
->rdclass
= lookold
->rdclass
;
792 looknew
->rdtypeset
= lookold
->rdtypeset
;
793 looknew
->rdclassset
= lookold
->rdclassset
;
794 looknew
->doing_xfr
= lookold
->doing_xfr
;
795 looknew
->ixfr_serial
= lookold
->ixfr_serial
;
796 looknew
->trace
= lookold
->trace
;
797 looknew
->trace_root
= lookold
->trace_root
;
798 looknew
->identify
= lookold
->identify
;
799 looknew
->identify_previous_line
= lookold
->identify_previous_line
;
800 looknew
->ignore
= lookold
->ignore
;
801 looknew
->servfail_stops
= lookold
->servfail_stops
;
802 looknew
->besteffort
= lookold
->besteffort
;
803 looknew
->dnssec
= lookold
->dnssec
;
805 looknew
->sigchase
= lookold
->sigchase
;
807 looknew
->do_topdown
= lookold
->do_topdown
;
808 looknew
->trace_root_sigchase
= lookold
->trace_root_sigchase
;
809 looknew
->rdtype_sigchaseset
= lookold
->rdtype_sigchaseset
;
810 looknew
->rdtype_sigchase
= lookold
->rdtype_sigchase
;
811 looknew
->qrdtype_sigchase
= lookold
->qrdtype_sigchase
;
812 looknew
->rdclass_sigchase
= lookold
->rdclass_sigchase
;
813 looknew
->rdclass_sigchaseset
= lookold
->rdclass_sigchaseset
;
816 looknew
->udpsize
= lookold
->udpsize
;
817 looknew
->edns
= lookold
->edns
;
818 looknew
->recurse
= lookold
->recurse
;
819 looknew
->aaonly
= lookold
->aaonly
;
820 looknew
->adflag
= lookold
->adflag
;
821 looknew
->cdflag
= lookold
->cdflag
;
822 looknew
->ns_search_only
= lookold
->ns_search_only
;
823 looknew
->tcp_mode
= lookold
->tcp_mode
;
824 looknew
->comments
= lookold
->comments
;
825 looknew
->stats
= lookold
->stats
;
826 looknew
->section_question
= lookold
->section_question
;
827 looknew
->section_answer
= lookold
->section_answer
;
828 looknew
->section_authority
= lookold
->section_authority
;
829 looknew
->section_additional
= lookold
->section_additional
;
830 looknew
->retries
= lookold
->retries
;
831 looknew
->tsigctx
= NULL
;
832 looknew
->need_search
= lookold
->need_search
;
833 looknew
->done_as_is
= lookold
->done_as_is
;
836 clone_server_list(lookold
->my_server_list
,
837 &looknew
->my_server_list
);
842 * Requeue a lookup for further processing, perhaps copying the server
843 * list. The new lookup structure is returned to the caller, and is
844 * queued for processing. If servers are not cloned in the requeue, they
845 * must be added before allowing the current event to complete, since the
846 * completion of the event may result in the next entry on the lookup
850 requeue_lookup(dig_lookup_t
*lookold
, isc_boolean_t servers
) {
851 dig_lookup_t
*looknew
;
853 debug("requeue_lookup()");
856 if (lookup_counter
> LOOKUP_LIMIT
)
857 fatal("too many lookups");
859 looknew
= clone_lookup(lookold
, servers
);
860 INSIST(looknew
!= NULL
);
862 debug("before insertion, init@%p -> %p, new@%p -> %p",
863 lookold
, lookold
->link
.next
, looknew
, looknew
->link
.next
);
864 ISC_LIST_PREPEND(lookup_list
, looknew
, link
);
865 debug("after insertion, init -> %p, new = %p, new -> %p",
866 lookold
, looknew
, looknew
->link
.next
);
872 setup_text_key(void) {
875 isc_buffer_t secretbuf
;
877 unsigned char *secretstore
;
879 debug("setup_text_key()");
880 result
= isc_buffer_allocate(mctx
, &namebuf
, MXNAME
);
881 check_result(result
, "isc_buffer_allocate");
882 dns_name_init(&keyname
, NULL
);
883 check_result(result
, "dns_name_init");
884 isc_buffer_putstr(namebuf
, keynametext
);
885 secretsize
= strlen(keysecret
) * 3 / 4;
886 secretstore
= isc_mem_allocate(mctx
, secretsize
);
887 if (secretstore
== NULL
)
888 fatal("memory allocation failure in %s:%d",
890 isc_buffer_init(&secretbuf
, secretstore
, secretsize
);
891 result
= isc_base64_decodestring(keysecret
, &secretbuf
);
892 if (result
!= ISC_R_SUCCESS
)
895 secretsize
= isc_buffer_usedlength(&secretbuf
);
897 result
= dns_name_fromtext(&keyname
, namebuf
,
898 dns_rootname
, ISC_FALSE
,
900 if (result
!= ISC_R_SUCCESS
)
903 result
= dns_tsigkey_create(&keyname
, hmacname
, secretstore
,
904 secretsize
, ISC_FALSE
, NULL
, 0, 0, mctx
,
907 if (result
!= ISC_R_SUCCESS
)
908 printf(";; Couldn't create key %s: %s\n",
909 keynametext
, isc_result_totext(result
));
911 dst_key_setbits(key
->key
, digestbits
);
913 isc_mem_free(mctx
, secretstore
);
914 dns_name_invalidate(&keyname
);
915 isc_buffer_free(&namebuf
);
919 setup_file_key(void) {
921 dst_key_t
*dstkey
= NULL
;
923 debug("setup_file_key()");
924 result
= dst_key_fromnamedfile(keyfile
, DST_TYPE_PRIVATE
| DST_TYPE_KEY
,
926 if (result
!= ISC_R_SUCCESS
) {
927 fprintf(stderr
, "Couldn't read key from %s: %s\n",
928 keyfile
, isc_result_totext(result
));
932 switch (dst_key_alg(dstkey
)) {
933 case DST_ALG_HMACMD5
:
934 hmacname
= DNS_TSIG_HMACMD5_NAME
;
936 case DST_ALG_HMACSHA1
:
937 hmacname
= DNS_TSIG_HMACSHA1_NAME
;
939 case DST_ALG_HMACSHA224
:
940 hmacname
= DNS_TSIG_HMACSHA224_NAME
;
942 case DST_ALG_HMACSHA256
:
943 hmacname
= DNS_TSIG_HMACSHA256_NAME
;
945 case DST_ALG_HMACSHA384
:
946 hmacname
= DNS_TSIG_HMACSHA384_NAME
;
948 case DST_ALG_HMACSHA512
:
949 hmacname
= DNS_TSIG_HMACSHA512_NAME
;
952 printf(";; Couldn't create key %s: bad algorithm\n",
956 result
= dns_tsigkey_createfromkey(dst_key_name(dstkey
), hmacname
,
957 dstkey
, ISC_FALSE
, NULL
, 0, 0,
959 if (result
!= ISC_R_SUCCESS
) {
960 printf(";; Couldn't create key %s: %s\n",
961 keynametext
, isc_result_totext(result
));
967 dst_key_free(&dstkey
);
970 static dig_searchlist_t
*
971 make_searchlist_entry(char *domain
) {
972 dig_searchlist_t
*search
;
973 search
= isc_mem_allocate(mctx
, sizeof(*search
));
975 fatal("memory allocation failure in %s:%d",
977 strncpy(search
->origin
, domain
, MXNAME
);
978 search
->origin
[MXNAME
-1] = 0;
979 ISC_LINK_INIT(search
, link
);
984 create_search_list(lwres_conf_t
*confdata
) {
986 dig_searchlist_t
*search
;
988 debug("create_search_list()");
989 ISC_LIST_INIT(search_list
);
991 for (i
= 0; i
< confdata
->searchnxt
; i
++) {
992 search
= make_searchlist_entry(confdata
->search
[i
]);
993 ISC_LIST_APPEND(search_list
, search
, link
);
998 * Setup the system as a whole, reading key information and resolv.conf
1002 setup_system(void) {
1003 dig_searchlist_t
*domain
= NULL
;
1004 lwres_result_t lwresult
;
1006 debug("setup_system()");
1008 lwresult
= lwres_context_create(&lwctx
, mctx
, mem_alloc
, mem_free
, 1);
1009 if (lwresult
!= LWRES_R_SUCCESS
)
1010 fatal("lwres_context_create failed");
1012 lwresult
= lwres_conf_parse(lwctx
, RESOLV_CONF
);
1013 if (lwresult
!= LWRES_R_SUCCESS
&& lwresult
!= LWRES_R_NOTFOUND
)
1014 fatal("parse of %s failed", RESOLV_CONF
);
1016 lwconf
= lwres_conf_get(lwctx
);
1018 /* Make the search list */
1019 if (lwconf
->searchnxt
> 0)
1020 create_search_list(lwconf
);
1021 else { /* No search list. Use the domain name if any */
1022 if (lwconf
->domainname
!= NULL
) {
1023 domain
= make_searchlist_entry(lwconf
->domainname
);
1024 ISC_LIST_INITANDAPPEND(search_list
, domain
, link
);
1030 ndots
= lwconf
->ndots
;
1031 debug("ndots is %d.", ndots
);
1034 /* If we don't find a nameserver fall back to localhost */
1035 if (lwconf
->nsnext
== 0) {
1037 lwresult
= add_nameserver(lwconf
, "127.0.0.1", AF_INET
);
1038 if (lwresult
!= ISC_R_SUCCESS
)
1039 fatal("add_nameserver failed");
1042 lwresult
= add_nameserver(lwconf
, "::1", AF_INET6
);
1043 if (lwresult
!= ISC_R_SUCCESS
)
1044 fatal("add_nameserver failed");
1048 if (ISC_LIST_EMPTY(server_list
))
1049 copy_server_list(lwconf
, &server_list
);
1055 if (keyfile
[0] != 0)
1057 else if (keysecret
[0] != 0)
1060 /* Setup the list of messages for +sigchase */
1061 ISC_LIST_INIT(chase_message_list
);
1062 ISC_LIST_INIT(chase_message_list2
);
1063 dns_name_init(&chase_name
, NULL
);
1065 dns_name_init(&chase_current_name
, NULL
);
1066 dns_name_init(&chase_authority_name
, NULL
);
1069 dns_name_init(&chase_signame
, NULL
);
1077 clear_searchlist(void) {
1078 dig_searchlist_t
*search
;
1079 while ((search
= ISC_LIST_HEAD(search_list
)) != NULL
) {
1080 ISC_LIST_UNLINK(search_list
, search
, link
);
1081 isc_mem_free(mctx
, search
);
1086 * Override the search list derived from resolv.conf by 'domain'.
1089 set_search_domain(char *domain
) {
1090 dig_searchlist_t
*search
;
1093 search
= make_searchlist_entry(domain
);
1094 ISC_LIST_APPEND(search_list
, search
, link
);
1098 * Setup the ISC and DNS libraries for use by the system.
1102 isc_result_t result
;
1104 debug("setup_libs()");
1106 result
= isc_net_probeipv4();
1107 if (result
== ISC_R_SUCCESS
)
1108 have_ipv4
= ISC_TRUE
;
1110 result
= isc_net_probeipv6();
1111 if (result
== ISC_R_SUCCESS
)
1112 have_ipv6
= ISC_TRUE
;
1113 if (!have_ipv6
&& !have_ipv4
)
1114 fatal("can't find either v4 or v6 networking");
1116 result
= isc_mem_create(0, 0, &mctx
);
1117 check_result(result
, "isc_mem_create");
1119 result
= isc_taskmgr_create(mctx
, 1, 0, &taskmgr
);
1120 check_result(result
, "isc_taskmgr_create");
1122 result
= isc_task_create(taskmgr
, 0, &global_task
);
1123 check_result(result
, "isc_task_create");
1125 result
= isc_timermgr_create(mctx
, &timermgr
);
1126 check_result(result
, "isc_timermgr_create");
1128 result
= isc_socketmgr_create(mctx
, &socketmgr
);
1129 check_result(result
, "isc_socketmgr_create");
1131 result
= isc_entropy_create(mctx
, &entp
);
1132 check_result(result
, "isc_entropy_create");
1134 result
= dst_lib_init(mctx
, entp
, 0);
1135 check_result(result
, "dst_lib_init");
1136 is_dst_up
= ISC_TRUE
;
1138 result
= isc_mempool_create(mctx
, COMMSIZE
, &commctx
);
1139 check_result(result
, "isc_mempool_create");
1140 isc_mempool_setname(commctx
, "COMMPOOL");
1142 * 6 and 2 set as reasonable parameters for 3 or 4 nameserver
1145 isc_mempool_setfreemax(commctx
, 6);
1146 isc_mempool_setfillcount(commctx
, 2);
1148 result
= isc_mutex_init(&lookup_lock
);
1149 check_result(result
, "isc_mutex_init");
1151 dns_result_register();
1155 * Add EDNS0 option record to a message. Currently, the only supported
1156 * options are UDP buffer size and the DO bit.
1159 add_opt(dns_message_t
*msg
, isc_uint16_t udpsize
, isc_uint16_t edns
,
1160 isc_boolean_t dnssec
)
1162 dns_rdataset_t
*rdataset
= NULL
;
1163 dns_rdatalist_t
*rdatalist
= NULL
;
1164 dns_rdata_t
*rdata
= NULL
;
1165 isc_result_t result
;
1168 result
= dns_message_gettemprdataset(msg
, &rdataset
);
1169 check_result(result
, "dns_message_gettemprdataset");
1170 dns_rdataset_init(rdataset
);
1171 result
= dns_message_gettemprdatalist(msg
, &rdatalist
);
1172 check_result(result
, "dns_message_gettemprdatalist");
1173 result
= dns_message_gettemprdata(msg
, &rdata
);
1174 check_result(result
, "dns_message_gettemprdata");
1176 debug("setting udp size of %d", udpsize
);
1177 rdatalist
->type
= dns_rdatatype_opt
;
1178 rdatalist
->covers
= 0;
1179 rdatalist
->rdclass
= udpsize
;
1180 rdatalist
->ttl
= edns
<< 16;
1182 rdatalist
->ttl
|= DNS_MESSAGEEXTFLAG_DO
;
1185 ISC_LIST_INIT(rdatalist
->rdata
);
1186 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1187 dns_rdatalist_tordataset(rdatalist
, rdataset
);
1188 result
= dns_message_setopt(msg
, rdataset
);
1189 check_result(result
, "dns_message_setopt");
1193 * Add a question section to a message, asking for the specified name,
1197 add_question(dns_message_t
*message
, dns_name_t
*name
,
1198 dns_rdataclass_t rdclass
, dns_rdatatype_t rdtype
)
1200 dns_rdataset_t
*rdataset
;
1201 isc_result_t result
;
1203 debug("add_question()");
1205 result
= dns_message_gettemprdataset(message
, &rdataset
);
1206 check_result(result
, "dns_message_gettemprdataset()");
1207 dns_rdataset_init(rdataset
);
1208 dns_rdataset_makequestion(rdataset
, rdclass
, rdtype
);
1209 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1213 * Check if we're done with all the queued lookups, which is true iff
1214 * all sockets, sends, and recvs are accounted for (counters == 0),
1215 * and the lookup list is empty.
1216 * If we are done, pass control back out to dighost_shutdown() (which is
1217 * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
1218 * a whole or reseed the lookup list.
1221 check_if_done(void) {
1222 debug("check_if_done()");
1223 debug("list %s", ISC_LIST_EMPTY(lookup_list
) ? "empty" : "full");
1224 if (ISC_LIST_EMPTY(lookup_list
) && current_lookup
== NULL
&&
1226 INSIST(sockcount
== 0);
1227 INSIST(recvcount
== 0);
1228 debug("shutting down");
1234 * Clear out a query when we're done with it. WARNING: This routine
1235 * WILL invalidate the query pointer.
1238 clear_query(dig_query_t
*query
) {
1239 dig_lookup_t
*lookup
;
1241 REQUIRE(query
!= NULL
);
1243 debug("clear_query(%p)", query
);
1245 lookup
= query
->lookup
;
1247 if (lookup
->current_query
== query
)
1248 lookup
->current_query
= NULL
;
1250 ISC_LIST_UNLINK(lookup
->q
, query
, link
);
1251 if (ISC_LINK_LINKED(&query
->recvbuf
, link
))
1252 ISC_LIST_DEQUEUE(query
->recvlist
, &query
->recvbuf
,
1254 if (ISC_LINK_LINKED(&query
->lengthbuf
, link
))
1255 ISC_LIST_DEQUEUE(query
->lengthlist
, &query
->lengthbuf
,
1257 INSIST(query
->recvspace
!= NULL
);
1258 if (query
->sock
!= NULL
) {
1259 isc_socket_detach(&query
->sock
);
1261 debug("sockcount=%d", sockcount
);
1263 isc_mempool_put(commctx
, query
->recvspace
);
1264 isc_buffer_invalidate(&query
->recvbuf
);
1265 isc_buffer_invalidate(&query
->lengthbuf
);
1266 if (query
->waiting_senddone
)
1267 query
->pending_free
= ISC_TRUE
;
1269 isc_mem_free(mctx
, query
);
1273 * Try and clear out a lookup if we're done with it. Return ISC_TRUE if
1274 * the lookup was successfully cleared. If ISC_TRUE is returned, the
1275 * lookup pointer has been invalidated.
1277 static isc_boolean_t
1278 try_clear_lookup(dig_lookup_t
*lookup
) {
1281 REQUIRE(lookup
!= NULL
);
1283 debug("try_clear_lookup(%p)", lookup
);
1285 if (ISC_LIST_HEAD(lookup
->q
) != NULL
) {
1287 q
= ISC_LIST_HEAD(lookup
->q
);
1289 debug("query to %s still pending", q
->servname
);
1290 q
= ISC_LIST_NEXT(q
, link
);
1297 * At this point, we know there are no queries on the lookup,
1298 * so can make it go away also.
1300 destroy_lookup(lookup
);
1305 destroy_lookup(dig_lookup_t
*lookup
) {
1310 s
= ISC_LIST_HEAD(lookup
->my_server_list
);
1312 debug("freeing server %p belonging to %p", s
, lookup
);
1314 s
= ISC_LIST_NEXT(s
, link
);
1315 ISC_LIST_DEQUEUE(lookup
->my_server_list
,
1316 (dig_server_t
*)ptr
, link
);
1317 isc_mem_free(mctx
, ptr
);
1319 if (lookup
->sendmsg
!= NULL
)
1320 dns_message_destroy(&lookup
->sendmsg
);
1321 if (lookup
->querysig
!= NULL
) {
1322 debug("freeing buffer %p", lookup
->querysig
);
1323 isc_buffer_free(&lookup
->querysig
);
1325 if (lookup
->timer
!= NULL
)
1326 isc_timer_detach(&lookup
->timer
);
1327 if (lookup
->sendspace
!= NULL
)
1328 isc_mempool_put(commctx
, lookup
->sendspace
);
1330 if (lookup
->tsigctx
!= NULL
)
1331 dst_context_destroy(&lookup
->tsigctx
);
1333 isc_mem_free(mctx
, lookup
);
1337 * If we can, start the next lookup in the queue running.
1338 * This assumes that the lookup on the head of the queue hasn't been
1339 * started yet. It also removes the lookup from the head of the queue,
1340 * setting the current_lookup pointer pointing to it.
1343 start_lookup(void) {
1344 debug("start_lookup()");
1349 * If there's a current lookup running, we really shouldn't get
1352 INSIST(current_lookup
== NULL
);
1354 current_lookup
= ISC_LIST_HEAD(lookup_list
);
1356 * Put the current lookup somewhere so cancel_all can find it
1358 if (current_lookup
!= NULL
) {
1359 ISC_LIST_DEQUEUE(lookup_list
, current_lookup
, link
);
1361 if (current_lookup
->do_topdown
&&
1362 !current_lookup
->rdtype_sigchaseset
) {
1363 dst_key_t
*trustedkey
= NULL
;
1364 isc_buffer_t
*b
= NULL
;
1366 isc_result_t result
;
1367 dns_name_t query_name
;
1368 dns_name_t
*key_name
;
1371 result
= get_trusted_key(mctx
);
1372 if (result
!= ISC_R_SUCCESS
) {
1373 printf("\n;; No trusted key, "
1374 "+sigchase option is disabled\n");
1375 current_lookup
->sigchase
= ISC_FALSE
;
1378 dns_name_init(&query_name
, NULL
);
1379 nameFromString(current_lookup
->textname
, &query_name
);
1381 for (i
= 0; i
< tk_list
.nb_tk
; i
++) {
1382 key_name
= dst_key_name(tk_list
.key
[i
]);
1384 if (dns_name_issubdomain(&query_name
,
1385 key_name
) == ISC_TRUE
)
1386 trustedkey
= tk_list
.key
[i
];
1388 * Verifier que la temp est bien la plus basse
1392 if (trustedkey
== NULL
) {
1393 printf("\n;; The queried zone: ");
1394 dns_name_print(&query_name
, stdout
);
1395 printf(" isn't a subdomain of any Trusted Keys"
1396 ": +sigchase option is disable\n");
1397 current_lookup
->sigchase
= ISC_FALSE
;
1398 free_name(&query_name
, mctx
);
1401 free_name(&query_name
, mctx
);
1403 current_lookup
->rdtype_sigchase
1404 = current_lookup
->rdtype
;
1405 current_lookup
->rdtype_sigchaseset
1406 = current_lookup
->rdtypeset
;
1407 current_lookup
->rdtype
= dns_rdatatype_ns
;
1409 current_lookup
->qrdtype_sigchase
1410 = current_lookup
->qrdtype
;
1411 current_lookup
->qrdtype
= dns_rdatatype_ns
;
1413 current_lookup
->rdclass_sigchase
1414 = current_lookup
->rdclass
;
1415 current_lookup
->rdclass_sigchaseset
1416 = current_lookup
->rdclassset
;
1417 current_lookup
->rdclass
= dns_rdataclass_in
;
1419 strncpy(current_lookup
->textnamesigchase
,
1420 current_lookup
->textname
, MXNAME
);
1422 current_lookup
->trace_root_sigchase
= ISC_TRUE
;
1424 result
= isc_buffer_allocate(mctx
, &b
, BUFSIZE
);
1425 check_result(result
, "isc_buffer_allocate");
1426 result
= dns_name_totext(dst_key_name(trustedkey
),
1428 check_result(result
, "dns_name_totext");
1429 isc_buffer_usedregion(b
, &r
);
1430 r
.base
[r
.length
] = '\0';
1431 strncpy(current_lookup
->textname
, (char*)r
.base
,
1433 isc_buffer_free(&b
);
1435 nameFromString(current_lookup
->textnamesigchase
,
1438 dns_name_init(&chase_authority_name
, NULL
);
1442 setup_lookup(current_lookup
);
1443 do_lookup(current_lookup
);
1450 * If we can, clear the current lookup and start the next one running.
1451 * This calls try_clear_lookup, so may invalidate the lookup pointer.
1454 check_next_lookup(dig_lookup_t
*lookup
) {
1458 debug("check_next_lookup(%p)", lookup
);
1460 if (ISC_LIST_HEAD(lookup
->q
) != NULL
) {
1461 debug("still have a worker");
1464 if (try_clear_lookup(lookup
)) {
1465 current_lookup
= NULL
;
1471 * Create and queue a new lookup as a followup to the current lookup,
1472 * based on the supplied message and section. This is used in trace and
1473 * name server search modes to start a new lookup using servers from
1474 * NS records in a reply. Returns the number of followup lookups made.
1477 followup_lookup(dns_message_t
*msg
, dig_query_t
*query
, dns_section_t section
)
1479 dig_lookup_t
*lookup
= NULL
;
1480 dig_server_t
*srv
= NULL
;
1481 dns_rdataset_t
*rdataset
= NULL
;
1482 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1483 dns_name_t
*name
= NULL
;
1484 isc_result_t result
;
1485 isc_boolean_t success
= ISC_FALSE
;
1488 isc_boolean_t horizontal
= ISC_FALSE
, bad
= ISC_FALSE
;
1492 debug("following up %s", query
->lookup
->textname
);
1494 for (result
= dns_message_firstname(msg
, section
);
1495 result
== ISC_R_SUCCESS
;
1496 result
= dns_message_nextname(msg
, section
)) {
1498 dns_message_currentname(msg
, section
, &name
);
1500 if (section
== DNS_SECTION_AUTHORITY
) {
1502 result
= dns_message_findtype(name
, dns_rdatatype_soa
,
1504 if (result
== ISC_R_SUCCESS
)
1508 result
= dns_message_findtype(name
, dns_rdatatype_ns
, 0,
1510 if (result
!= ISC_R_SUCCESS
)
1513 debug("found NS set");
1515 if (query
->lookup
->trace
&& !query
->lookup
->trace_root
) {
1516 dns_namereln_t namereln
;
1517 unsigned int nlabels
;
1520 domain
= dns_fixedname_name(&query
->lookup
->fdomain
);
1521 namereln
= dns_name_fullcompare(name
, domain
,
1523 if (namereln
== dns_namereln_equal
) {
1525 printf(";; BAD (HORIZONTAL) REFERRAL\n");
1526 horizontal
= ISC_TRUE
;
1527 } else if (namereln
!= dns_namereln_subdomain
) {
1529 printf(";; BAD REFERRAL\n");
1535 for (result
= dns_rdataset_first(rdataset
);
1536 result
== ISC_R_SUCCESS
;
1537 result
= dns_rdataset_next(rdataset
)) {
1538 char namestr
[DNS_NAME_FORMATSIZE
];
1541 if (query
->lookup
->trace_root
&&
1542 query
->lookup
->nsfound
>= MXSERV
)
1545 dns_rdataset_current(rdataset
, &rdata
);
1547 query
->lookup
->nsfound
++;
1548 (void)dns_rdata_tostruct(&rdata
, &ns
, NULL
);
1549 dns_name_format(&ns
.name
, namestr
, sizeof(namestr
));
1550 dns_rdata_freestruct(&ns
);
1552 /* Initialize lookup if we've not yet */
1553 debug("found NS %d %s", numLookups
, namestr
);
1558 lookup
= requeue_lookup(query
->lookup
,
1560 cancel_lookup(query
->lookup
);
1561 lookup
->doing_xfr
= ISC_FALSE
;
1562 if (!lookup
->trace_root
&&
1563 section
== DNS_SECTION_ANSWER
)
1564 lookup
->trace
= ISC_FALSE
;
1566 lookup
->trace
= query
->lookup
->trace
;
1567 lookup
->ns_search_only
=
1568 query
->lookup
->ns_search_only
;
1569 lookup
->trace_root
= ISC_FALSE
;
1570 if (lookup
->ns_search_only
)
1571 lookup
->recurse
= ISC_FALSE
;
1572 dns_fixedname_init(&lookup
->fdomain
);
1573 domain
= dns_fixedname_name(&lookup
->fdomain
);
1574 dns_name_copy(name
, domain
, NULL
);
1576 srv
= make_server(namestr
, namestr
);
1577 debug("adding server %s", srv
->servername
);
1578 ISC_LIST_APPEND(lookup
->my_server_list
, srv
, link
);
1579 dns_rdata_reset(&rdata
);
1583 if (lookup
== NULL
&&
1584 section
== DNS_SECTION_ANSWER
&&
1585 (query
->lookup
->trace
|| query
->lookup
->ns_search_only
))
1586 return (followup_lookup(msg
, query
, DNS_SECTION_AUTHORITY
));
1589 * Randomize the order the nameserver will be tried.
1591 if (numLookups
> 1) {
1593 dig_serverlist_t my_server_list
;
1595 ISC_LIST_INIT(my_server_list
);
1597 for (i
= numLookups
; i
> 0; i
--) {
1600 srv
= ISC_LIST_HEAD(lookup
->my_server_list
);
1602 srv
= ISC_LIST_NEXT(srv
, link
);
1603 ISC_LIST_DEQUEUE(lookup
->my_server_list
, srv
, link
);
1604 ISC_LIST_APPEND(my_server_list
, srv
, link
);
1606 ISC_LIST_APPENDLIST(lookup
->my_server_list
,
1607 my_server_list
, link
);
1610 return (numLookups
);
1614 * Create and queue a new lookup using the next origin from the search
1615 * list, read in setup_system().
1617 * Return ISC_TRUE iff there was another searchlist entry.
1619 static isc_boolean_t
1620 next_origin(dns_message_t
*msg
, dig_query_t
*query
) {
1621 dig_lookup_t
*lookup
;
1622 dig_searchlist_t
*search
;
1628 debug("next_origin()");
1629 debug("following up %s", query
->lookup
->textname
);
1633 * We're not using a search list, so don't even think
1634 * about finding the next entry.
1637 if (query
->lookup
->origin
== NULL
&& !query
->lookup
->need_search
)
1639 * Then we just did rootorg; there's nothing left.
1642 if (query
->lookup
->origin
== NULL
&& query
->lookup
->need_search
) {
1643 lookup
= requeue_lookup(query
->lookup
, ISC_TRUE
);
1644 lookup
->origin
= ISC_LIST_HEAD(search_list
);
1645 lookup
->need_search
= ISC_FALSE
;
1647 search
= ISC_LIST_NEXT(query
->lookup
->origin
, link
);
1648 if (search
== NULL
&& query
->lookup
->done_as_is
)
1650 lookup
= requeue_lookup(query
->lookup
, ISC_TRUE
);
1651 lookup
->origin
= search
;
1653 cancel_lookup(query
->lookup
);
1658 * Insert an SOA record into the sendmessage in a lookup. Used for
1659 * creating IXFR queries.
1662 insert_soa(dig_lookup_t
*lookup
) {
1663 isc_result_t result
;
1664 dns_rdata_soa_t soa
;
1665 dns_rdata_t
*rdata
= NULL
;
1666 dns_rdatalist_t
*rdatalist
= NULL
;
1667 dns_rdataset_t
*rdataset
= NULL
;
1668 dns_name_t
*soaname
= NULL
;
1670 debug("insert_soa()");
1672 soa
.serial
= lookup
->ixfr_serial
;
1677 soa
.common
.rdclass
= lookup
->rdclass
;
1678 soa
.common
.rdtype
= dns_rdatatype_soa
;
1680 dns_name_init(&soa
.origin
, NULL
);
1681 dns_name_init(&soa
.contact
, NULL
);
1683 dns_name_clone(dns_rootname
, &soa
.origin
);
1684 dns_name_clone(dns_rootname
, &soa
.contact
);
1686 isc_buffer_init(&lookup
->rdatabuf
, lookup
->rdatastore
,
1687 sizeof(lookup
->rdatastore
));
1689 result
= dns_message_gettemprdata(lookup
->sendmsg
, &rdata
);
1690 check_result(result
, "dns_message_gettemprdata");
1692 result
= dns_rdata_fromstruct(rdata
, lookup
->rdclass
,
1693 dns_rdatatype_soa
, &soa
,
1695 check_result(result
, "isc_rdata_fromstruct");
1697 result
= dns_message_gettemprdatalist(lookup
->sendmsg
, &rdatalist
);
1698 check_result(result
, "dns_message_gettemprdatalist");
1700 result
= dns_message_gettemprdataset(lookup
->sendmsg
, &rdataset
);
1701 check_result(result
, "dns_message_gettemprdataset");
1703 dns_rdatalist_init(rdatalist
);
1704 rdatalist
->type
= dns_rdatatype_soa
;
1705 rdatalist
->rdclass
= lookup
->rdclass
;
1706 rdatalist
->covers
= 0;
1708 ISC_LIST_INIT(rdatalist
->rdata
);
1709 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1711 dns_rdataset_init(rdataset
);
1712 dns_rdatalist_tordataset(rdatalist
, rdataset
);
1714 result
= dns_message_gettempname(lookup
->sendmsg
, &soaname
);
1715 check_result(result
, "dns_message_gettempname");
1716 dns_name_init(soaname
, NULL
);
1717 dns_name_clone(lookup
->name
, soaname
);
1718 ISC_LIST_INIT(soaname
->list
);
1719 ISC_LIST_APPEND(soaname
->list
, rdataset
, link
);
1720 dns_message_addname(lookup
->sendmsg
, soaname
, DNS_SECTION_AUTHORITY
);
1724 * Setup the supplied lookup structure, making it ready to start sending
1725 * queries to servers. Create and initialize the message to be sent as
1726 * well as the query structures and buffer space for the replies. If the
1727 * server list is empty, clone it from the system default list.
1730 setup_lookup(dig_lookup_t
*lookup
) {
1731 isc_result_t result
;
1737 dns_compress_t cctx
;
1741 char utf8_textname
[MXNAME
], utf8_origin
[MXNAME
], idn_textname
[MXNAME
];
1745 result
= dns_name_settotextfilter(output_filter
);
1746 check_result(result
, "dns_name_settotextfilter");
1749 REQUIRE(lookup
!= NULL
);
1752 debug("setup_lookup(%p)", lookup
);
1754 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTRENDER
,
1756 check_result(result
, "dns_message_create");
1758 if (lookup
->new_search
) {
1759 debug("resetting lookup counter.");
1763 if (ISC_LIST_EMPTY(lookup
->my_server_list
)) {
1764 debug("cloning server list");
1765 clone_server_list(server_list
, &lookup
->my_server_list
);
1767 result
= dns_message_gettempname(lookup
->sendmsg
, &lookup
->name
);
1768 check_result(result
, "dns_message_gettempname");
1769 dns_name_init(lookup
->name
, NULL
);
1771 isc_buffer_init(&lookup
->namebuf
, lookup
->namespace,
1772 sizeof(lookup
->namespace));
1773 isc_buffer_init(&lookup
->onamebuf
, lookup
->onamespace
,
1774 sizeof(lookup
->onamespace
));
1778 * We cannot convert `textname' and `origin' separately.
1779 * `textname' doesn't contain TLD, but local mapping needs
1782 mr
= idn_encodename(IDN_LOCALCONV
| IDN_DELIMMAP
, lookup
->textname
,
1783 utf8_textname
, sizeof(utf8_textname
));
1784 idn_check_result(mr
, "convert textname to UTF-8");
1788 * If the name has too many dots, force the origin to be NULL
1789 * (which produces an absolute lookup). Otherwise, take the origin
1790 * we have if there's one in the struct already. If it's NULL,
1791 * take the first entry in the searchlist iff either usesearch
1792 * is TRUE or we got a domain line in the resolv.conf file.
1794 if (lookup
->new_search
) {
1796 if ((count_dots(utf8_textname
) >= ndots
) || !usesearch
) {
1797 lookup
->origin
= NULL
; /* Force abs lookup */
1798 lookup
->done_as_is
= ISC_TRUE
;
1799 lookup
->need_search
= usesearch
;
1800 } else if (lookup
->origin
== NULL
&& usesearch
) {
1801 lookup
->origin
= ISC_LIST_HEAD(search_list
);
1802 lookup
->need_search
= ISC_FALSE
;
1805 if ((count_dots(lookup
->textname
) >= ndots
) || !usesearch
) {
1806 lookup
->origin
= NULL
; /* Force abs lookup */
1807 lookup
->done_as_is
= ISC_TRUE
;
1808 lookup
->need_search
= usesearch
;
1809 } else if (lookup
->origin
== NULL
&& usesearch
) {
1810 lookup
->origin
= ISC_LIST_HEAD(search_list
);
1811 lookup
->need_search
= ISC_FALSE
;
1817 if (lookup
->origin
!= NULL
) {
1818 mr
= idn_encodename(IDN_LOCALCONV
| IDN_DELIMMAP
,
1819 lookup
->origin
->origin
, utf8_origin
,
1820 sizeof(utf8_origin
));
1821 idn_check_result(mr
, "convert origin to UTF-8");
1822 mr
= append_textname(utf8_textname
, utf8_origin
,
1823 sizeof(utf8_textname
));
1824 idn_check_result(mr
, "append origin to textname");
1826 mr
= idn_encodename(idnoptions
| IDN_LOCALMAP
| IDN_NAMEPREP
|
1827 IDN_IDNCONV
| IDN_LENCHECK
, utf8_textname
,
1828 idn_textname
, sizeof(idn_textname
));
1829 idn_check_result(mr
, "convert UTF-8 textname to IDN encoding");
1831 if (lookup
->origin
!= NULL
) {
1832 debug("trying origin %s", lookup
->origin
->origin
);
1833 result
= dns_message_gettempname(lookup
->sendmsg
,
1835 check_result(result
, "dns_message_gettempname");
1836 dns_name_init(lookup
->oname
, NULL
);
1837 /* XXX Helper funct to conv char* to name? */
1838 len
= strlen(lookup
->origin
->origin
);
1839 isc_buffer_init(&b
, lookup
->origin
->origin
, len
);
1840 isc_buffer_add(&b
, len
);
1841 result
= dns_name_fromtext(lookup
->oname
, &b
, dns_rootname
,
1842 ISC_FALSE
, &lookup
->onamebuf
);
1843 if (result
!= ISC_R_SUCCESS
) {
1844 dns_message_puttempname(lookup
->sendmsg
,
1846 dns_message_puttempname(lookup
->sendmsg
,
1848 fatal("'%s' is not in legal name syntax (%s)",
1849 lookup
->origin
->origin
,
1850 isc_result_totext(result
));
1852 if (lookup
->trace
&& lookup
->trace_root
) {
1853 dns_name_clone(dns_rootname
, lookup
->name
);
1855 len
= strlen(lookup
->textname
);
1856 isc_buffer_init(&b
, lookup
->textname
, len
);
1857 isc_buffer_add(&b
, len
);
1858 result
= dns_name_fromtext(lookup
->name
, &b
,
1859 lookup
->oname
, ISC_FALSE
,
1862 if (result
!= ISC_R_SUCCESS
) {
1863 dns_message_puttempname(lookup
->sendmsg
,
1865 dns_message_puttempname(lookup
->sendmsg
,
1867 fatal("'%s' is not in legal name syntax (%s)",
1868 lookup
->textname
, isc_result_totext(result
));
1870 dns_message_puttempname(lookup
->sendmsg
, &lookup
->oname
);
1874 debug("using root origin");
1875 if (lookup
->trace
&& lookup
->trace_root
)
1876 dns_name_clone(dns_rootname
, lookup
->name
);
1879 len
= strlen(idn_textname
);
1880 isc_buffer_init(&b
, idn_textname
, len
);
1881 isc_buffer_add(&b
, len
);
1882 result
= dns_name_fromtext(lookup
->name
, &b
,
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
,
1896 if (result
!= ISC_R_SUCCESS
) {
1897 dns_message_puttempname(lookup
->sendmsg
,
1899 isc_buffer_init(&b
, store
, MXNAME
);
1900 fatal("'%s' is not a legal name "
1901 "(%s)", lookup
->textname
,
1902 isc_result_totext(result
));
1905 dns_name_format(lookup
->name
, store
, sizeof(store
));
1906 trying(store
, lookup
);
1907 INSIST(dns_name_isabsolute(lookup
->name
));
1909 isc_random_get(&id
);
1910 lookup
->sendmsg
->id
= (unsigned short)id
& 0xFFFF;
1911 lookup
->sendmsg
->opcode
= dns_opcode_query
;
1912 lookup
->msgcounter
= 0;
1914 * If this is a trace request, completely disallow recursion, since
1915 * it's meaningless for traces.
1917 if (lookup
->trace
|| (lookup
->ns_search_only
&& !lookup
->trace_root
))
1918 lookup
->recurse
= ISC_FALSE
;
1920 if (lookup
->recurse
&&
1921 lookup
->rdtype
!= dns_rdatatype_axfr
&&
1922 lookup
->rdtype
!= dns_rdatatype_ixfr
) {
1923 debug("recursive query");
1924 lookup
->sendmsg
->flags
|= DNS_MESSAGEFLAG_RD
;
1928 if (lookup
->aaonly
) {
1930 lookup
->sendmsg
->flags
|= DNS_MESSAGEFLAG_AA
;
1933 if (lookup
->adflag
) {
1935 lookup
->sendmsg
->flags
|= DNS_MESSAGEFLAG_AD
;
1938 if (lookup
->cdflag
) {
1940 lookup
->sendmsg
->flags
|= DNS_MESSAGEFLAG_CD
;
1943 dns_message_addname(lookup
->sendmsg
, lookup
->name
,
1944 DNS_SECTION_QUESTION
);
1946 if (lookup
->trace
&& lookup
->trace_root
) {
1947 lookup
->qrdtype
= lookup
->rdtype
;
1948 lookup
->rdtype
= dns_rdatatype_ns
;
1951 if ((lookup
->rdtype
== dns_rdatatype_axfr
) ||
1952 (lookup
->rdtype
== dns_rdatatype_ixfr
)) {
1953 lookup
->doing_xfr
= ISC_TRUE
;
1955 * Force TCP mode if we're doing an xfr.
1956 * XXX UDP ixfr's would be useful
1958 lookup
->tcp_mode
= ISC_TRUE
;
1961 add_question(lookup
->sendmsg
, lookup
->name
, lookup
->rdclass
,
1965 if (lookup
->rdtype
== dns_rdatatype_ixfr
)
1968 /* XXX Insist this? */
1969 lookup
->tsigctx
= NULL
;
1970 lookup
->querysig
= NULL
;
1972 debug("initializing keys");
1973 result
= dns_message_settsigkey(lookup
->sendmsg
, key
);
1974 check_result(result
, "dns_message_settsigkey");
1977 lookup
->sendspace
= isc_mempool_get(commctx
);
1978 if (lookup
->sendspace
== NULL
)
1979 fatal("memory allocation failure");
1981 result
= dns_compress_init(&cctx
, -1, mctx
);
1982 check_result(result
, "dns_compress_init");
1984 debug("starting to render the message");
1985 isc_buffer_init(&lookup
->renderbuf
, lookup
->sendspace
, COMMSIZE
);
1986 result
= dns_message_renderbegin(lookup
->sendmsg
, &cctx
,
1987 &lookup
->renderbuf
);
1988 check_result(result
, "dns_message_renderbegin");
1989 if (lookup
->udpsize
> 0 || lookup
->dnssec
|| lookup
->edns
> -1) {
1990 if (lookup
->udpsize
== 0)
1991 lookup
->udpsize
= 4096;
1992 if (lookup
->edns
< 0)
1994 add_opt(lookup
->sendmsg
, lookup
->udpsize
,
1995 lookup
->edns
, lookup
->dnssec
);
1998 result
= dns_message_rendersection(lookup
->sendmsg
,
1999 DNS_SECTION_QUESTION
, 0);
2000 check_result(result
, "dns_message_rendersection");
2001 result
= dns_message_rendersection(lookup
->sendmsg
,
2002 DNS_SECTION_AUTHORITY
, 0);
2003 check_result(result
, "dns_message_rendersection");
2004 result
= dns_message_renderend(lookup
->sendmsg
);
2005 check_result(result
, "dns_message_renderend");
2006 debug("done rendering");
2008 dns_compress_invalidate(&cctx
);
2011 * Force TCP mode if the request is larger than 512 bytes.
2013 if (isc_buffer_usedlength(&lookup
->renderbuf
) > 512)
2014 lookup
->tcp_mode
= ISC_TRUE
;
2016 lookup
->pending
= ISC_FALSE
;
2018 for (serv
= ISC_LIST_HEAD(lookup
->my_server_list
);
2020 serv
= ISC_LIST_NEXT(serv
, link
)) {
2021 query
= isc_mem_allocate(mctx
, sizeof(dig_query_t
));
2023 fatal("memory allocation failure in %s:%d",
2024 __FILE__
, __LINE__
);
2025 debug("create query %p linked to lookup %p",
2027 query
->lookup
= lookup
;
2028 query
->waiting_connect
= ISC_FALSE
;
2029 query
->waiting_senddone
= ISC_FALSE
;
2030 query
->pending_free
= ISC_FALSE
;
2031 query
->recv_made
= ISC_FALSE
;
2032 query
->first_pass
= ISC_TRUE
;
2033 query
->first_soa_rcvd
= ISC_FALSE
;
2034 query
->second_rr_rcvd
= ISC_FALSE
;
2035 query
->first_repeat_rcvd
= ISC_FALSE
;
2036 query
->warn_id
= ISC_TRUE
;
2037 query
->first_rr_serial
= 0;
2038 query
->second_rr_serial
= 0;
2039 query
->servname
= serv
->servername
;
2040 query
->userarg
= serv
->userarg
;
2041 query
->rr_count
= 0;
2042 query
->msg_count
= 0;
2043 query
->byte_count
= 0;
2044 ISC_LINK_INIT(query
, link
);
2045 ISC_LIST_INIT(query
->recvlist
);
2046 ISC_LIST_INIT(query
->lengthlist
);
2048 query
->recvspace
= isc_mempool_get(commctx
);
2049 if (query
->recvspace
== NULL
)
2050 fatal("memory allocation failure");
2052 isc_buffer_init(&query
->recvbuf
, query
->recvspace
, COMMSIZE
);
2053 isc_buffer_init(&query
->lengthbuf
, query
->lengthspace
, 2);
2054 isc_buffer_init(&query
->slbuf
, query
->slspace
, 2);
2055 query
->sendbuf
= lookup
->renderbuf
;
2057 ISC_LINK_INIT(query
, link
);
2058 ISC_LIST_ENQUEUE(lookup
->q
, query
, link
);
2060 /* XXX qrflag, print_query, etc... */
2061 if (!ISC_LIST_EMPTY(lookup
->q
) && qr
) {
2063 printmessage(ISC_LIST_HEAD(lookup
->q
), lookup
->sendmsg
,
2069 * Event handler for send completion. Track send counter, and clear out
2070 * the query if the send was canceled.
2073 send_done(isc_task_t
*_task
, isc_event_t
*event
) {
2074 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
2075 isc_buffer_t
*b
= NULL
;
2076 dig_query_t
*query
, *next
;
2079 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
2085 debug("send_done()");
2087 debug("sendcount=%d", sendcount
);
2088 INSIST(sendcount
>= 0);
2090 for (b
= ISC_LIST_HEAD(sevent
->bufferlist
);
2092 b
= ISC_LIST_HEAD(sevent
->bufferlist
))
2093 ISC_LIST_DEQUEUE(sevent
->bufferlist
, b
, link
);
2095 query
= event
->ev_arg
;
2096 query
->waiting_senddone
= ISC_FALSE
;
2099 if (l
->ns_search_only
&& !l
->trace_root
) {
2100 debug("sending next, since searching");
2101 next
= ISC_LIST_NEXT(query
, link
);
2106 isc_event_free(&event
);
2108 if (query
->pending_free
)
2109 isc_mem_free(mctx
, query
);
2116 * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
2117 * IO sockets. The cancel handlers should take care of cleaning up the
2118 * query and lookup structures
2121 cancel_lookup(dig_lookup_t
*lookup
) {
2122 dig_query_t
*query
, *next
;
2124 debug("cancel_lookup()");
2125 query
= ISC_LIST_HEAD(lookup
->q
);
2126 while (query
!= NULL
) {
2127 next
= ISC_LIST_NEXT(query
, link
);
2128 if (query
->sock
!= NULL
) {
2129 isc_socket_cancel(query
->sock
, global_task
,
2130 ISC_SOCKCANCEL_ALL
);
2137 if (lookup
->timer
!= NULL
)
2138 isc_timer_detach(&lookup
->timer
);
2139 lookup
->pending
= ISC_FALSE
;
2140 lookup
->retries
= 0;
2144 bringup_timer(dig_query_t
*query
, unsigned int default_timeout
) {
2146 unsigned int local_timeout
;
2147 isc_result_t result
;
2149 debug("bringup_timer()");
2151 * If the timer already exists, that means we're calling this
2152 * a second time (for a retry). Don't need to recreate it,
2156 if (ISC_LIST_NEXT(query
, link
) != NULL
)
2157 local_timeout
= SERVER_TIMEOUT
;
2160 local_timeout
= default_timeout
;
2162 local_timeout
= timeout
;
2164 debug("have local timeout of %d", local_timeout
);
2165 isc_interval_set(&l
->interval
, local_timeout
, 0);
2166 if (l
->timer
!= NULL
)
2167 isc_timer_detach(&l
->timer
);
2168 result
= isc_timer_create(timermgr
, isc_timertype_once
, NULL
,
2169 &l
->interval
, global_task
, connect_timeout
,
2171 check_result(result
, "isc_timer_create");
2175 connect_done(isc_task_t
*task
, isc_event_t
*event
);
2178 * Unlike send_udp, this can't be called multiple times with the same
2179 * query. When we retry TCP, we requeue the whole lookup, which should
2183 send_tcp_connect(dig_query_t
*query
) {
2184 isc_result_t result
;
2188 debug("send_tcp_connect(%p)", query
);
2191 query
->waiting_connect
= ISC_TRUE
;
2192 query
->lookup
->current_query
= query
;
2193 get_address(query
->servname
, port
, &query
->sockaddr
);
2195 if (specified_source
&&
2196 (isc_sockaddr_pf(&query
->sockaddr
) !=
2197 isc_sockaddr_pf(&bind_address
))) {
2198 printf(";; Skipping server %s, incompatible "
2199 "address family\n", query
->servname
);
2200 query
->waiting_connect
= ISC_FALSE
;
2201 next
= ISC_LIST_NEXT(query
, link
);
2205 printf(";; No acceptable nameservers\n");
2206 check_next_lookup(l
);
2209 send_tcp_connect(next
);
2212 INSIST(query
->sock
== NULL
);
2213 result
= isc_socket_create(socketmgr
,
2214 isc_sockaddr_pf(&query
->sockaddr
),
2215 isc_sockettype_tcp
, &query
->sock
);
2216 check_result(result
, "isc_socket_create");
2218 debug("sockcount=%d", sockcount
);
2219 if (specified_source
)
2220 result
= isc_socket_bind(query
->sock
, &bind_address
,
2221 ISC_SOCKET_REUSEADDRESS
);
2223 if ((isc_sockaddr_pf(&query
->sockaddr
) == AF_INET
) &&
2225 isc_sockaddr_any(&bind_any
);
2227 isc_sockaddr_any6(&bind_any
);
2228 result
= isc_socket_bind(query
->sock
, &bind_any
, 0);
2230 check_result(result
, "isc_socket_bind");
2231 bringup_timer(query
, TCP_TIMEOUT
);
2232 result
= isc_socket_connect(query
->sock
, &query
->sockaddr
,
2233 global_task
, connect_done
, query
);
2234 check_result(result
, "isc_socket_connect");
2236 * If we're at the endgame of a nameserver search, we need to
2237 * immediately bring up all the queries. Do it here.
2239 if (l
->ns_search_only
&& !l
->trace_root
) {
2240 debug("sending next, since searching");
2241 next
= ISC_LIST_NEXT(query
, link
);
2243 send_tcp_connect(next
);
2248 * Send a UDP packet to the remote nameserver, possible starting the
2249 * recv action as well. Also make sure that the timer is running and
2250 * is properly reset.
2253 send_udp(dig_query_t
*query
) {
2254 dig_lookup_t
*l
= NULL
;
2255 isc_result_t result
;
2257 debug("send_udp(%p)", query
);
2260 bringup_timer(query
, UDP_TIMEOUT
);
2261 l
->current_query
= query
;
2262 debug("working on lookup %p, query %p", query
->lookup
, query
);
2263 if (!query
->recv_made
) {
2264 /* XXX Check the sense of this, need assertion? */
2265 query
->waiting_connect
= ISC_FALSE
;
2266 get_address(query
->servname
, port
, &query
->sockaddr
);
2268 result
= isc_socket_create(socketmgr
,
2269 isc_sockaddr_pf(&query
->sockaddr
),
2270 isc_sockettype_udp
, &query
->sock
);
2271 check_result(result
, "isc_socket_create");
2273 debug("sockcount=%d", sockcount
);
2274 if (specified_source
) {
2275 result
= isc_socket_bind(query
->sock
, &bind_address
,
2276 ISC_SOCKET_REUSEADDRESS
);
2278 isc_sockaddr_anyofpf(&bind_any
,
2279 isc_sockaddr_pf(&query
->sockaddr
));
2280 result
= isc_socket_bind(query
->sock
, &bind_any
, 0);
2282 check_result(result
, "isc_socket_bind");
2284 query
->recv_made
= ISC_TRUE
;
2285 ISC_LINK_INIT(&query
->recvbuf
, link
);
2286 ISC_LIST_ENQUEUE(query
->recvlist
, &query
->recvbuf
,
2288 debug("recving with lookup=%p, query=%p, sock=%p",
2289 query
->lookup
, query
, query
->sock
);
2290 result
= isc_socket_recvv(query
->sock
, &query
->recvlist
, 1,
2291 global_task
, recv_done
, query
);
2292 check_result(result
, "isc_socket_recvv");
2294 debug("recvcount=%d", recvcount
);
2296 ISC_LIST_INIT(query
->sendlist
);
2297 ISC_LIST_ENQUEUE(query
->sendlist
, &query
->sendbuf
, link
);
2298 debug("sending a request");
2299 TIME_NOW(&query
->time_sent
);
2300 INSIST(query
->sock
!= NULL
);
2301 query
->waiting_senddone
= ISC_TRUE
;
2302 result
= isc_socket_sendtov(query
->sock
, &query
->sendlist
,
2303 global_task
, send_done
, query
,
2304 &query
->sockaddr
, NULL
);
2305 check_result(result
, "isc_socket_sendtov");
2310 * IO timeout handler, used for both connect and recv timeouts. If
2311 * retries are still allowed, either resend the UDP packet or queue a
2312 * new TCP lookup. Otherwise, cancel the lookup.
2315 connect_timeout(isc_task_t
*task
, isc_event_t
*event
) {
2316 dig_lookup_t
*l
= NULL
;
2317 dig_query_t
*query
= NULL
, *cq
;
2320 REQUIRE(event
->ev_type
== ISC_TIMEREVENT_IDLE
);
2322 debug("connect_timeout()");
2326 query
= l
->current_query
;
2327 isc_event_free(&event
);
2331 if ((query
!= NULL
) && (query
->lookup
->current_query
!= NULL
) &&
2332 (ISC_LIST_NEXT(query
->lookup
->current_query
, link
) != NULL
)) {
2333 debug("trying next server...");
2334 cq
= query
->lookup
->current_query
;
2336 send_udp(ISC_LIST_NEXT(cq
, link
));
2338 send_tcp_connect(ISC_LIST_NEXT(cq
, link
));
2343 if (l
->retries
> 1) {
2346 debug("resending UDP request to first server");
2347 send_udp(ISC_LIST_HEAD(l
->q
));
2349 debug("making new TCP request, %d tries left",
2352 requeue_lookup(l
, ISC_TRUE
);
2354 check_next_lookup(l
);
2357 fputs(l
->cmdline
, stdout
);
2358 printf(";; connection timed out; no servers could be "
2361 check_next_lookup(l
);
2369 * Event handler for the TCP recv which gets the length header of TCP
2370 * packets. Start the next recv of length bytes.
2373 tcp_length_done(isc_task_t
*task
, isc_event_t
*event
) {
2374 isc_socketevent_t
*sevent
;
2375 isc_buffer_t
*b
= NULL
;
2376 isc_result_t result
;
2377 dig_query_t
*query
= NULL
;
2379 isc_uint16_t length
;
2381 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_RECVDONE
);
2386 debug("tcp_length_done()");
2389 sevent
= (isc_socketevent_t
*)event
;
2390 query
= event
->ev_arg
;
2393 INSIST(recvcount
>= 0);
2395 b
= ISC_LIST_HEAD(sevent
->bufferlist
);
2396 INSIST(b
== &query
->lengthbuf
);
2397 ISC_LIST_DEQUEUE(sevent
->bufferlist
, b
, link
);
2399 if (sevent
->result
== ISC_R_CANCELED
) {
2400 isc_event_free(&event
);
2403 check_next_lookup(l
);
2407 if (sevent
->result
!= ISC_R_SUCCESS
) {
2408 char sockstr
[ISC_SOCKADDR_FORMATSIZE
];
2409 isc_sockaddr_format(&query
->sockaddr
, sockstr
,
2411 printf(";; communications error to %s: %s\n",
2412 sockstr
, isc_result_totext(sevent
->result
));
2414 isc_socket_detach(&query
->sock
);
2416 debug("sockcount=%d", sockcount
);
2417 INSIST(sockcount
>= 0);
2418 isc_event_free(&event
);
2420 check_next_lookup(l
);
2424 length
= isc_buffer_getuint16(b
);
2426 isc_event_free(&event
);
2427 launch_next_query(query
, ISC_FALSE
);
2433 * Even though the buffer was already init'ed, we need
2434 * to redo it now, to force the length we want.
2436 isc_buffer_invalidate(&query
->recvbuf
);
2437 isc_buffer_init(&query
->recvbuf
, query
->recvspace
, length
);
2438 ENSURE(ISC_LIST_EMPTY(query
->recvlist
));
2439 ISC_LINK_INIT(&query
->recvbuf
, link
);
2440 ISC_LIST_ENQUEUE(query
->recvlist
, &query
->recvbuf
, link
);
2441 debug("recving with lookup=%p, query=%p", query
->lookup
, query
);
2442 result
= isc_socket_recvv(query
->sock
, &query
->recvlist
, length
, task
,
2444 check_result(result
, "isc_socket_recvv");
2446 debug("resubmitted recv request with length %d, recvcount=%d",
2448 isc_event_free(&event
);
2453 * For transfers that involve multiple recvs (XFR's in particular),
2454 * launch the next recv.
2457 launch_next_query(dig_query_t
*query
, isc_boolean_t include_question
) {
2458 isc_result_t result
;
2463 debug("launch_next_query()");
2465 if (!query
->lookup
->pending
) {
2466 debug("ignoring launch_next_query because !pending");
2467 isc_socket_detach(&query
->sock
);
2469 debug("sockcount=%d", sockcount
);
2470 INSIST(sockcount
>= 0);
2471 query
->waiting_connect
= ISC_FALSE
;
2474 check_next_lookup(l
);
2478 isc_buffer_clear(&query
->slbuf
);
2479 isc_buffer_clear(&query
->lengthbuf
);
2480 isc_buffer_putuint16(&query
->slbuf
, (isc_uint16_t
) query
->sendbuf
.used
);
2481 ISC_LIST_INIT(query
->sendlist
);
2482 ISC_LINK_INIT(&query
->slbuf
, link
);
2483 ISC_LIST_ENQUEUE(query
->sendlist
, &query
->slbuf
, link
);
2484 if (include_question
)
2485 ISC_LIST_ENQUEUE(query
->sendlist
, &query
->sendbuf
, link
);
2486 ISC_LINK_INIT(&query
->lengthbuf
, link
);
2487 ISC_LIST_ENQUEUE(query
->lengthlist
, &query
->lengthbuf
, link
);
2489 result
= isc_socket_recvv(query
->sock
, &query
->lengthlist
, 0,
2490 global_task
, tcp_length_done
, query
);
2491 check_result(result
, "isc_socket_recvv");
2493 debug("recvcount=%d", recvcount
);
2494 if (!query
->first_soa_rcvd
) {
2495 debug("sending a request in launch_next_query");
2496 TIME_NOW(&query
->time_sent
);
2497 query
->waiting_senddone
= ISC_TRUE
;
2498 result
= isc_socket_sendv(query
->sock
, &query
->sendlist
,
2499 global_task
, send_done
, query
);
2500 check_result(result
, "isc_socket_sendv");
2502 debug("sendcount=%d", sendcount
);
2504 query
->waiting_connect
= ISC_FALSE
;
2506 check_next_lookup(query
->lookup
);
2512 * Event handler for TCP connect complete. Make sure the connection was
2513 * successful, then pass into launch_next_query to actually send the
2517 connect_done(isc_task_t
*task
, isc_event_t
*event
) {
2518 isc_socketevent_t
*sevent
= NULL
;
2519 dig_query_t
*query
= NULL
, *next
;
2524 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_CONNECT
);
2527 debug("connect_done()");
2530 sevent
= (isc_socketevent_t
*)event
;
2531 query
= sevent
->ev_arg
;
2533 INSIST(query
->waiting_connect
);
2535 query
->waiting_connect
= ISC_FALSE
;
2537 if (sevent
->result
== ISC_R_CANCELED
) {
2538 debug("in cancel handler");
2539 isc_socket_detach(&query
->sock
);
2541 INSIST(sockcount
>= 0);
2542 debug("sockcount=%d", sockcount
);
2543 query
->waiting_connect
= ISC_FALSE
;
2544 isc_event_free(&event
);
2547 check_next_lookup(l
);
2551 if (sevent
->result
!= ISC_R_SUCCESS
) {
2552 char sockstr
[ISC_SOCKADDR_FORMATSIZE
];
2554 debug("unsuccessful connection: %s",
2555 isc_result_totext(sevent
->result
));
2556 isc_sockaddr_format(&query
->sockaddr
, sockstr
, sizeof(sockstr
));
2557 if (sevent
->result
!= ISC_R_CANCELED
)
2558 printf(";; Connection to %s(%s) for %s failed: "
2560 query
->servname
, query
->lookup
->textname
,
2561 isc_result_totext(sevent
->result
));
2562 isc_socket_detach(&query
->sock
);
2564 INSIST(sockcount
>= 0);
2565 /* XXX Clean up exitcodes */
2568 debug("sockcount=%d", sockcount
);
2569 query
->waiting_connect
= ISC_FALSE
;
2570 isc_event_free(&event
);
2572 if (l
->current_query
!= NULL
)
2573 next
= ISC_LIST_NEXT(l
->current_query
, link
);
2578 bringup_timer(next
, TCP_TIMEOUT
);
2579 send_tcp_connect(next
);
2581 check_next_lookup(l
);
2586 launch_next_query(query
, ISC_TRUE
);
2587 isc_event_free(&event
);
2592 * Check if the ongoing XFR needs more data before it's complete, using
2593 * the semantics of IXFR and AXFR protocols. Much of the complexity of
2594 * this routine comes from determining when an IXFR is complete.
2595 * ISC_FALSE means more data is on the way, and the recv has been issued.
2597 static isc_boolean_t
2598 check_for_more_data(dig_query_t
*query
, dns_message_t
*msg
,
2599 isc_socketevent_t
*sevent
)
2601 dns_rdataset_t
*rdataset
= NULL
;
2602 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2603 dns_rdata_soa_t soa
;
2604 isc_uint32_t serial
;
2605 isc_result_t result
;
2607 debug("check_for_more_data()");
2610 * By the time we're in this routine, we know we're doing
2611 * either an AXFR or IXFR. If there's no second_rr_type,
2612 * then we don't yet know which kind of answer we got back
2613 * from the server. Here, we're going to walk through the
2614 * rr's in the message, acting as necessary whenever we hit
2619 query
->byte_count
+= sevent
->n
;
2620 result
= dns_message_firstname(msg
, DNS_SECTION_ANSWER
);
2621 if (result
!= ISC_R_SUCCESS
) {
2622 puts("; Transfer failed.");
2628 dns_message_currentname(msg
, DNS_SECTION_ANSWER
,
2630 for (rdataset
= ISC_LIST_HEAD(name
->list
);
2632 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
2633 result
= dns_rdataset_first(rdataset
);
2634 if (result
!= ISC_R_SUCCESS
)
2638 dns_rdata_reset(&rdata
);
2639 dns_rdataset_current(rdataset
, &rdata
);
2641 * If this is the first rr, make sure
2644 if ((!query
->first_soa_rcvd
) &&
2645 (rdata
.type
!= dns_rdatatype_soa
)) {
2646 puts("; Transfer failed. "
2647 "Didn't start with SOA answer.");
2650 if ((!query
->second_rr_rcvd
) &&
2651 (rdata
.type
!= dns_rdatatype_soa
)) {
2652 query
->second_rr_rcvd
= ISC_TRUE
;
2653 query
->second_rr_serial
= 0;
2654 debug("got the second rr as nonsoa");
2659 * If the record is anything except an SOA
2660 * now, just continue on...
2662 if (rdata
.type
!= dns_rdatatype_soa
)
2664 /* Now we have an SOA. Work with it. */
2665 debug("got an SOA");
2666 (void)dns_rdata_tostruct(&rdata
, &soa
, NULL
);
2667 serial
= soa
.serial
;
2668 dns_rdata_freestruct(&soa
);
2669 if (!query
->first_soa_rcvd
) {
2670 query
->first_soa_rcvd
= ISC_TRUE
;
2671 query
->first_rr_serial
= serial
;
2672 debug("this is the first %d",
2673 query
->lookup
->ixfr_serial
);
2674 if (query
->lookup
->ixfr_serial
>=
2679 if (query
->lookup
->rdtype
==
2680 dns_rdatatype_axfr
) {
2681 debug("doing axfr, got second SOA");
2684 if (!query
->second_rr_rcvd
) {
2685 if (query
->first_rr_serial
== serial
) {
2686 debug("doing ixfr, got "
2690 debug("this is the second %d",
2691 query
->lookup
->ixfr_serial
);
2692 query
->second_rr_rcvd
= ISC_TRUE
;
2693 query
->second_rr_serial
= serial
;
2696 if (query
->second_rr_serial
== 0) {
2698 * If the second RR was a non-SOA
2699 * record, and we're getting any
2700 * other SOA, then this is an
2701 * AXFR, and we're done.
2703 debug("done, since axfr");
2707 * If we get to this point, we're doing an
2708 * IXFR and have to start really looking
2709 * at serial numbers.
2711 if (query
->first_rr_serial
== serial
) {
2712 debug("got a match for ixfr");
2713 if (!query
->first_repeat_rcvd
) {
2714 query
->first_repeat_rcvd
=
2718 debug("done with ixfr");
2721 debug("meaningless soa %d", serial
);
2723 result
= dns_rdataset_next(rdataset
);
2724 } while (result
== ISC_R_SUCCESS
);
2726 result
= dns_message_nextname(msg
, DNS_SECTION_ANSWER
);
2727 } while (result
== ISC_R_SUCCESS
);
2728 launch_next_query(query
, ISC_FALSE
);
2731 received(sevent
->n
, &sevent
->address
, query
);
2736 * Event handler for recv complete. Perform whatever actions are necessary,
2737 * based on the specifics of the user's request.
2740 recv_done(isc_task_t
*task
, isc_event_t
*event
) {
2741 isc_socketevent_t
*sevent
= NULL
;
2742 dig_query_t
*query
= NULL
;
2743 isc_buffer_t
*b
= NULL
;
2744 dns_message_t
*msg
= NULL
;
2746 dig_message_t
*chase_msg
= NULL
;
2747 dig_message_t
*chase_msg2
= NULL
;
2749 isc_result_t result
;
2750 dig_lookup_t
*n
, *l
;
2751 isc_boolean_t docancel
= ISC_FALSE
;
2752 isc_boolean_t match
= ISC_TRUE
;
2753 unsigned int parseflags
;
2755 unsigned int msgflags
;
2757 isc_result_t do_sigchase
= ISC_FALSE
;
2759 dns_message_t
*msg_temp
= NULL
;
2761 isc_buffer_t
*buf
= NULL
;
2767 debug("recv_done()");
2771 debug("recvcount=%d", recvcount
);
2772 INSIST(recvcount
>= 0);
2774 query
= event
->ev_arg
;
2775 debug("lookup=%p, query=%p", query
->lookup
, query
);
2779 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_RECVDONE
);
2780 sevent
= (isc_socketevent_t
*)event
;
2782 b
= ISC_LIST_HEAD(sevent
->bufferlist
);
2783 INSIST(b
== &query
->recvbuf
);
2784 ISC_LIST_DEQUEUE(sevent
->bufferlist
, &query
->recvbuf
, link
);
2786 if ((l
->tcp_mode
) && (l
->timer
!= NULL
))
2787 isc_timer_touch(l
->timer
);
2788 if ((!l
->pending
&& !l
->ns_search_only
) || cancel_now
) {
2789 debug("no longer pending. Got %s",
2790 isc_result_totext(sevent
->result
));
2791 query
->waiting_connect
= ISC_FALSE
;
2793 isc_event_free(&event
);
2795 check_next_lookup(l
);
2800 if (sevent
->result
!= ISC_R_SUCCESS
) {
2801 if (sevent
->result
== ISC_R_CANCELED
) {
2802 debug("in recv cancel handler");
2803 query
->waiting_connect
= ISC_FALSE
;
2805 printf(";; communications error: %s\n",
2806 isc_result_totext(sevent
->result
));
2807 isc_socket_detach(&query
->sock
);
2809 debug("sockcount=%d", sockcount
);
2810 INSIST(sockcount
>= 0);
2812 isc_event_free(&event
);
2814 check_next_lookup(l
);
2820 !isc_sockaddr_compare(&sevent
->address
, &query
->sockaddr
,
2821 ISC_SOCKADDR_CMPADDR
|
2822 ISC_SOCKADDR_CMPPORT
|
2823 ISC_SOCKADDR_CMPSCOPE
|
2824 ISC_SOCKADDR_CMPSCOPEZERO
)) {
2825 char buf1
[ISC_SOCKADDR_FORMATSIZE
];
2826 char buf2
[ISC_SOCKADDR_FORMATSIZE
];
2829 if (isc_sockaddr_pf(&query
->sockaddr
) == AF_INET
)
2830 isc_sockaddr_any(&any
);
2832 isc_sockaddr_any6(&any
);
2835 * We don't expect a match when the packet is
2836 * sent to 0.0.0.0, :: or to a multicast addresses.
2837 * XXXMPA broadcast needs to be handled here as well.
2839 if ((!isc_sockaddr_eqaddr(&query
->sockaddr
, &any
) &&
2840 !isc_sockaddr_ismulticast(&query
->sockaddr
)) ||
2841 isc_sockaddr_getport(&query
->sockaddr
) !=
2842 isc_sockaddr_getport(&sevent
->address
)) {
2843 isc_sockaddr_format(&sevent
->address
, buf1
,
2845 isc_sockaddr_format(&query
->sockaddr
, buf2
,
2847 printf(";; reply from unexpected source: %s,"
2848 " expected %s\n", buf1
, buf2
);
2853 result
= dns_message_peekheader(b
, &id
, &msgflags
);
2854 if (result
!= ISC_R_SUCCESS
|| l
->sendmsg
->id
!= id
) {
2857 isc_boolean_t fail
= ISC_TRUE
;
2858 if (result
== ISC_R_SUCCESS
) {
2859 if (!query
->first_soa_rcvd
||
2861 printf(";; %s: ID mismatch: "
2862 "expected ID %u, got %u\n",
2863 query
->first_soa_rcvd
?
2864 "WARNING" : "ERROR",
2865 l
->sendmsg
->id
, id
);
2866 if (query
->first_soa_rcvd
)
2868 query
->warn_id
= ISC_FALSE
;
2870 printf(";; ERROR: short "
2871 "(< header size) message\n");
2873 isc_event_free(&event
);
2875 check_next_lookup(l
);
2880 } else if (result
== ISC_R_SUCCESS
)
2881 printf(";; Warning: ID mismatch: "
2882 "expected ID %u, got %u\n", l
->sendmsg
->id
, id
);
2884 printf(";; Warning: short "
2885 "(< header size) message received\n");
2888 if (result
== ISC_R_SUCCESS
&& (msgflags
& DNS_MESSAGEFLAG_QR
) == 0)
2889 printf(";; Warning: query response not set\n");
2892 isc_buffer_invalidate(&query
->recvbuf
);
2893 isc_buffer_init(&query
->recvbuf
, query
->recvspace
, COMMSIZE
);
2894 ISC_LIST_ENQUEUE(query
->recvlist
, &query
->recvbuf
, link
);
2895 result
= isc_socket_recvv(query
->sock
, &query
->recvlist
, 1,
2896 global_task
, recv_done
, query
);
2897 check_result(result
, "isc_socket_recvv");
2899 isc_event_free(&event
);
2904 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
, &msg
);
2905 check_result(result
, "dns_message_create");
2908 if (l
->querysig
== NULL
) {
2909 debug("getting initial querysig");
2910 result
= dns_message_getquerytsig(l
->sendmsg
, mctx
,
2912 check_result(result
, "dns_message_getquerytsig");
2914 result
= dns_message_setquerytsig(msg
, l
->querysig
);
2915 check_result(result
, "dns_message_setquerytsig");
2916 result
= dns_message_settsigkey(msg
, key
);
2917 check_result(result
, "dns_message_settsigkey");
2918 msg
->tsigctx
= l
->tsigctx
;
2920 if (l
->msgcounter
!= 0)
2921 msg
->tcp_continuation
= 1;
2925 debug("before parse starts");
2926 parseflags
= DNS_MESSAGEPARSE_PRESERVEORDER
;
2929 do_sigchase
= ISC_FALSE
;
2932 do_sigchase
= ISC_TRUE
;
2935 if (l
->besteffort
) {
2936 parseflags
|= DNS_MESSAGEPARSE_BESTEFFORT
;
2937 parseflags
|= DNS_MESSAGEPARSE_IGNORETRUNCATION
;
2939 result
= dns_message_parse(msg
, b
, parseflags
);
2940 if (result
== DNS_R_RECOVERABLE
) {
2941 printf(";; Warning: Message parser reports malformed "
2942 "message packet.\n");
2943 result
= ISC_R_SUCCESS
;
2945 if (result
!= ISC_R_SUCCESS
) {
2946 printf(";; Got bad packet: %s\n", isc_result_totext(result
));
2948 query
->waiting_connect
= ISC_FALSE
;
2949 dns_message_destroy(&msg
);
2950 isc_event_free(&event
);
2953 check_next_lookup(l
);
2957 if ((msg
->flags
& DNS_MESSAGEFLAG_TC
) != 0 &&
2958 !l
->ignore
&& !l
->tcp_mode
) {
2959 printf(";; Truncated, retrying in TCP mode.\n");
2960 n
= requeue_lookup(l
, ISC_TRUE
);
2961 n
->tcp_mode
= ISC_TRUE
;
2962 n
->origin
= query
->lookup
->origin
;
2963 dns_message_destroy(&msg
);
2964 isc_event_free(&event
);
2967 check_next_lookup(l
);
2971 if ((msg
->rcode
== dns_rcode_servfail
&& !l
->servfail_stops
) ||
2972 (check_ra
&& (msg
->flags
& DNS_MESSAGEFLAG_RA
) == 0 && l
->recurse
))
2974 dig_query_t
*next
= ISC_LIST_NEXT(query
, link
);
2975 if (l
->current_query
== query
)
2976 l
->current_query
= NULL
;
2978 debug("sending query %p\n", next
);
2980 send_tcp_connect(next
);
2985 * If our query is at the head of the list and there
2986 * is no next, we're the only one left, so fall
2987 * through to print the message.
2989 if ((ISC_LIST_HEAD(l
->q
) != query
) ||
2990 (ISC_LIST_NEXT(query
, link
) != NULL
)) {
2991 if( l
->comments
== ISC_TRUE
)
2992 printf(";; Got %s from %s, "
2993 "trying next server\n",
2994 msg
->rcode
== dns_rcode_servfail
?
2996 "recursion not available",
2999 check_next_lookup(l
);
3000 dns_message_destroy(&msg
);
3001 isc_event_free(&event
);
3008 result
= dns_tsig_verify(&query
->recvbuf
, msg
, NULL
, NULL
);
3009 if (result
!= ISC_R_SUCCESS
) {
3010 printf(";; Couldn't verify signature: %s\n",
3011 isc_result_totext(result
));
3012 validated
= ISC_FALSE
;
3014 l
->tsigctx
= msg
->tsigctx
;
3015 msg
->tsigctx
= NULL
;
3016 if (l
->querysig
!= NULL
) {
3017 debug("freeing querysig buffer %p", l
->querysig
);
3018 isc_buffer_free(&l
->querysig
);
3020 result
= dns_message_getquerytsig(msg
, mctx
, &l
->querysig
);
3021 check_result(result
,"dns_message_getquerytsig");
3024 extrabytes
= isc_buffer_remaininglength(b
);
3026 debug("after parse");
3027 if (l
->doing_xfr
&& l
->xfr_q
== NULL
) {
3030 * Once we are in the XFR message, increase
3031 * the timeout to much longer, so brief network
3032 * outages won't cause the XFR to abort
3034 if (timeout
!= INT_MAX
&& l
->timer
!= NULL
) {
3035 unsigned int local_timeout
;
3039 local_timeout
= TCP_TIMEOUT
* 4;
3041 local_timeout
= UDP_TIMEOUT
* 4;
3043 if (timeout
< (INT_MAX
/ 4))
3044 local_timeout
= timeout
* 4;
3046 local_timeout
= INT_MAX
;
3048 debug("have local timeout of %d", local_timeout
);
3049 isc_interval_set(&l
->interval
, local_timeout
, 0);
3050 result
= isc_timer_reset(l
->timer
,
3055 check_result(result
, "isc_timer_reset");
3059 if (!l
->doing_xfr
|| l
->xfr_q
== query
) {
3060 if (msg
->rcode
!= dns_rcode_noerror
&&
3061 (l
->origin
!= NULL
|| l
->need_search
)) {
3062 if (!next_origin(msg
, query
) || showsearch
) {
3063 printmessage(query
, msg
, ISC_TRUE
);
3064 received(b
->used
, &sevent
->address
, query
);
3066 } else if (!l
->trace
&& !l
->ns_search_only
) {
3070 printmessage(query
, msg
, ISC_TRUE
);
3071 } else if (l
->trace
) {
3073 int count
= msg
->counts
[DNS_SECTION_ANSWER
];
3075 debug("in TRACE code");
3076 if (!l
->ns_search_only
)
3077 printmessage(query
, msg
, ISC_TRUE
);
3079 l
->rdtype
= l
->qrdtype
;
3080 if (l
->trace_root
|| (l
->ns_search_only
&& count
> 0)) {
3082 l
->rdtype
= dns_rdatatype_soa
;
3083 n
= followup_lookup(msg
, query
,
3084 DNS_SECTION_ANSWER
);
3085 l
->trace_root
= ISC_FALSE
;
3086 } else if (count
== 0)
3087 n
= followup_lookup(msg
, query
,
3088 DNS_SECTION_AUTHORITY
);
3090 docancel
= ISC_TRUE
;
3092 debug("in NSSEARCH code");
3094 if (l
->trace_root
) {
3096 * This is the initial NS query.
3100 l
->rdtype
= dns_rdatatype_soa
;
3101 n
= followup_lookup(msg
, query
,
3102 DNS_SECTION_ANSWER
);
3104 docancel
= ISC_TRUE
;
3105 l
->trace_root
= ISC_FALSE
;
3110 printmessage(query
, msg
, ISC_TRUE
);
3114 chase_msg
= isc_mem_allocate(mctx
,
3115 sizeof(dig_message_t
));
3116 if (chase_msg
== NULL
) {
3117 fatal("Memory allocation failure in %s:%d",
3118 __FILE__
, __LINE__
);
3120 ISC_LIST_INITANDAPPEND(chase_message_list
, chase_msg
,
3122 if (dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
,
3123 &msg_temp
) != ISC_R_SUCCESS
) {
3124 fatal("dns_message_create in %s:%d",
3125 __FILE__
, __LINE__
);
3128 isc_buffer_usedregion(b
, &r
);
3129 result
= isc_buffer_allocate(mctx
, &buf
, r
.length
);
3131 check_result(result
, "isc_buffer_allocate");
3132 result
= isc_buffer_copyregion(buf
, &r
);
3133 check_result(result
, "isc_buffer_copyregion");
3135 result
= dns_message_parse(msg_temp
, buf
, 0);
3137 isc_buffer_free(&buf
);
3138 chase_msg
->msg
= msg_temp
;
3140 chase_msg2
= isc_mem_allocate(mctx
,
3141 sizeof(dig_message_t
));
3142 if (chase_msg2
== NULL
) {
3143 fatal("Memory allocation failure in %s:%d",
3144 __FILE__
, __LINE__
);
3146 ISC_LIST_INITANDAPPEND(chase_message_list2
, chase_msg2
,
3148 chase_msg2
->msg
= msg
;
3154 if (l
->sigchase
&& ISC_LIST_EMPTY(lookup_list
)) {
3160 debug("still pending.");
3162 if (query
!= l
->xfr_q
) {
3163 dns_message_destroy(&msg
);
3164 isc_event_free(&event
);
3165 query
->waiting_connect
= ISC_FALSE
;
3170 docancel
= check_for_more_data(query
, msg
, sevent
);
3172 dns_message_destroy(&msg
);
3175 check_next_lookup(l
);
3179 if (msg
->rcode
== dns_rcode_noerror
|| l
->origin
== NULL
) {
3184 received(b
->used
, &sevent
->address
, query
);
3187 if (!query
->lookup
->ns_search_only
)
3188 query
->lookup
->pending
= ISC_FALSE
;
3189 if (!query
->lookup
->ns_search_only
||
3190 query
->lookup
->trace_root
|| docancel
) {
3194 dns_message_destroy(&msg
);
3199 check_next_lookup(l
);
3207 dns_message_destroy(&msg
);
3209 isc_event_free(&event
);
3214 * Turn a name into an address, using system-supplied routines. This is
3215 * used in looking up server names, etc... and needs to use system-supplied
3216 * routines, since they may be using a non-DNS system for these lookups.
3219 get_address(char *host
, in_port_t port
, isc_sockaddr_t
*sockaddr
) {
3221 isc_result_t result
;
3224 result
= bind9_getaddresses(host
, port
, sockaddr
, 1, &count
);
3226 if (result
!= ISC_R_SUCCESS
)
3227 fatal("couldn't get address for '%s': %s",
3228 host
, isc_result_totext(result
));
3233 * Initiate either a TCP or UDP lookup
3236 do_lookup(dig_lookup_t
*lookup
) {
3238 REQUIRE(lookup
!= NULL
);
3240 debug("do_lookup()");
3241 lookup
->pending
= ISC_TRUE
;
3242 if (lookup
->tcp_mode
)
3243 send_tcp_connect(ISC_LIST_HEAD(lookup
->q
));
3245 send_udp(ISC_LIST_HEAD(lookup
->q
));
3249 * Start everything in action upon task startup.
3252 onrun_callback(isc_task_t
*task
, isc_event_t
*event
) {
3255 isc_event_free(&event
);
3262 * Make everything on the lookup queue go away. Mainly used by the
3267 dig_lookup_t
*l
, *n
;
3268 dig_query_t
*q
, *nq
;
3270 debug("cancel_all()");
3277 cancel_now
= ISC_TRUE
;
3278 if (current_lookup
!= NULL
) {
3279 if (current_lookup
->timer
!= NULL
)
3280 isc_timer_detach(¤t_lookup
->timer
);
3281 q
= ISC_LIST_HEAD(current_lookup
->q
);
3283 debug("cancelling query %p, belonging to %p",
3285 nq
= ISC_LIST_NEXT(q
, link
);
3286 if (q
->sock
!= NULL
) {
3287 isc_socket_cancel(q
->sock
, NULL
,
3288 ISC_SOCKCANCEL_ALL
);
3295 l
= ISC_LIST_HEAD(lookup_list
);
3297 n
= ISC_LIST_NEXT(l
, link
);
3298 ISC_LIST_DEQUEUE(lookup_list
, l
, link
);
3299 try_clear_lookup(l
);
3306 * Destroy all of the libs we are using, and get everything ready for a
3310 destroy_libs(void) {
3313 dig_message_t
*chase_msg
;
3316 isc_result_t result
;
3319 debug("destroy_libs()");
3320 if (global_task
!= NULL
) {
3321 debug("freeing task");
3322 isc_task_detach(&global_task
);
3325 * The taskmgr_destroy() call blocks until all events are cleared
3328 if (taskmgr
!= NULL
) {
3329 debug("freeing taskmgr");
3330 isc_taskmgr_destroy(&taskmgr
);
3333 REQUIRE(sockcount
== 0);
3334 REQUIRE(recvcount
== 0);
3335 REQUIRE(sendcount
== 0);
3337 INSIST(ISC_LIST_HEAD(lookup_list
) == NULL
);
3338 INSIST(current_lookup
== NULL
);
3341 free_now
= ISC_TRUE
;
3343 lwres_conf_clear(lwctx
);
3344 lwres_context_destroy(&lwctx
);
3346 flush_server_list();
3351 result
= dns_name_settotextfilter(NULL
);
3352 check_result(result
, "dns_name_settotextfilter");
3356 if (commctx
!= NULL
) {
3357 debug("freeing commctx");
3358 isc_mempool_destroy(&commctx
);
3360 if (socketmgr
!= NULL
) {
3361 debug("freeing socketmgr");
3362 isc_socketmgr_destroy(&socketmgr
);
3364 if (timermgr
!= NULL
) {
3365 debug("freeing timermgr");
3366 isc_timermgr_destroy(&timermgr
);
3369 debug("freeing key %p", key
);
3370 dns_tsigkey_detach(&key
);
3372 if (namebuf
!= NULL
)
3373 isc_buffer_free(&namebuf
);
3376 debug("destroy DST lib");
3378 is_dst_up
= ISC_FALSE
;
3381 debug("detach from entropy");
3382 isc_entropy_detach(&entp
);
3386 DESTROYLOCK(&lookup_lock
);
3389 debug("Destroy the messages kept for sigchase");
3390 /* Destroy the messages kept for sigchase */
3391 chase_msg
= ISC_LIST_HEAD(chase_message_list
);
3393 while (chase_msg
!= NULL
) {
3394 INSIST(chase_msg
->msg
!= NULL
);
3395 dns_message_destroy(&(chase_msg
->msg
));
3397 chase_msg
= ISC_LIST_NEXT(chase_msg
, link
);
3398 isc_mem_free(mctx
, ptr
);
3401 chase_msg
= ISC_LIST_HEAD(chase_message_list2
);
3403 while (chase_msg
!= NULL
) {
3404 INSIST(chase_msg
->msg
!= NULL
);
3405 dns_message_destroy(&(chase_msg
->msg
));
3407 chase_msg
= ISC_LIST_NEXT(chase_msg
, link
);
3408 isc_mem_free(mctx
, ptr
);
3410 if (dns_name_dynamic(&chase_name
))
3411 free_name(&chase_name
, mctx
);
3413 if (dns_name_dynamic(&chase_current_name
))
3414 free_name(&chase_current_name
, mctx
);
3415 if (dns_name_dynamic(&chase_authority_name
))
3416 free_name(&chase_authority_name
, mctx
);
3419 if (dns_name_dynamic(&chase_signame
))
3420 free_name(&chase_signame
, mctx
);
3423 debug("Destroy memory");
3426 if (memdebugging
!= 0)
3427 isc_mem_stats(mctx
, stderr
);
3429 isc_mem_destroy(&mctx
);
3434 initialize_idn(void) {
3436 isc_result_t result
;
3438 #ifdef HAVE_SETLOCALE
3440 (void)setlocale(LC_ALL
, "");
3442 /* Create configuration context. */
3443 r
= idn_nameinit(1);
3444 if (r
!= idn_success
)
3445 fatal("idn api initialization failed: %s",
3446 idn_result_tostring(r
));
3448 /* Set domain name -> text post-conversion filter. */
3449 result
= dns_name_settotextfilter(output_filter
);
3450 check_result(result
, "dns_name_settotextfilter");
3454 output_filter(isc_buffer_t
*buffer
, unsigned int used_org
,
3455 isc_boolean_t absolute
)
3457 char tmp1
[MAXDLEN
], tmp2
[MAXDLEN
];
3458 size_t fromlen
, tolen
;
3459 isc_boolean_t end_with_dot
;
3462 * Copy contents of 'buffer' to 'tmp1', supply trailing dot
3463 * if 'absolute' is true, and terminate with NUL.
3465 fromlen
= isc_buffer_usedlength(buffer
) - used_org
;
3466 if (fromlen
>= MAXDLEN
)
3467 return (ISC_R_SUCCESS
);
3468 memcpy(tmp1
, (char *)isc_buffer_base(buffer
) + used_org
, fromlen
);
3469 end_with_dot
= (tmp1
[fromlen
- 1] == '.') ? ISC_TRUE
: ISC_FALSE
;
3470 if (absolute
&& !end_with_dot
) {
3472 if (fromlen
>= MAXDLEN
)
3473 return (ISC_R_SUCCESS
);
3474 tmp1
[fromlen
- 1] = '.';
3476 tmp1
[fromlen
] = '\0';
3479 * Convert contents of 'tmp1' to local encoding.
3481 if (idn_decodename(IDN_DECODE_APP
, tmp1
, tmp2
, MAXDLEN
) != idn_success
)
3482 return (ISC_R_SUCCESS
);
3486 * Copy the converted contents in 'tmp1' back to 'buffer'.
3487 * If we have appended trailing dot, remove it.
3489 tolen
= strlen(tmp1
);
3490 if (absolute
&& !end_with_dot
&& tmp1
[tolen
- 1] == '.')
3493 if (isc_buffer_length(buffer
) < used_org
+ tolen
)
3494 return (ISC_R_NOSPACE
);
3496 isc_buffer_subtract(buffer
, isc_buffer_usedlength(buffer
) - used_org
);
3497 memcpy(isc_buffer_used(buffer
), tmp1
, tolen
);
3498 isc_buffer_add(buffer
, tolen
);
3500 return (ISC_R_SUCCESS
);
3504 append_textname(char *name
, const char *origin
, size_t namesize
) {
3505 size_t namelen
= strlen(name
);
3506 size_t originlen
= strlen(origin
);
3508 /* Already absolute? */
3509 if (namelen
> 0 && name
[namelen
- 1] == '.')
3512 /* Append dot and origin */
3514 if (namelen
+ 1 + originlen
>= namesize
)
3515 return idn_buffer_overflow
;
3517 name
[namelen
++] = '.';
3518 (void)strcpy(name
+ namelen
, origin
);
3523 idn_check_result(idn_result_t r
, const char *msg
) {
3524 if (r
!= idn_success
) {
3526 fatal("%s: %s", msg
, idn_result_tostring(r
));
3529 #endif /* WITH_IDN */
3533 print_type(dns_rdatatype_t type
)
3535 isc_buffer_t
* b
= NULL
;
3536 isc_result_t result
;
3539 result
= isc_buffer_allocate(mctx
, &b
, 4000);
3540 check_result(result
, "isc_buffer_allocate");
3542 result
= dns_rdatatype_totext(type
, b
);
3543 check_result(result
, "print_type");
3545 isc_buffer_usedregion(b
, &r
);
3546 r
.base
[r
.length
] = '\0';
3548 printf("%s", r
.base
);
3550 isc_buffer_free(&b
);
3554 dump_database_section(dns_message_t
*msg
, int section
)
3556 dns_name_t
*msg_name
=NULL
;
3558 dns_rdataset_t
*rdataset
;
3561 dns_message_currentname(msg
, section
, &msg_name
);
3563 for (rdataset
= ISC_LIST_HEAD(msg_name
->list
); rdataset
!= NULL
;
3564 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3565 dns_name_print(msg_name
, stdout
);
3567 print_rdataset(msg_name
, rdataset
, mctx
);
3571 } while (dns_message_nextname(msg
, section
) == ISC_R_SUCCESS
);
3575 dump_database(void) {
3576 dig_message_t
* msg
;
3578 for (msg
= ISC_LIST_HEAD(chase_message_list
); msg
!= NULL
;
3579 msg
= ISC_LIST_NEXT(msg
, link
)) {
3580 if (dns_message_firstname(msg
->msg
, DNS_SECTION_ANSWER
)
3582 dump_database_section(msg
->msg
, DNS_SECTION_ANSWER
);
3584 if (dns_message_firstname(msg
->msg
, DNS_SECTION_AUTHORITY
)
3586 dump_database_section(msg
->msg
, DNS_SECTION_AUTHORITY
);
3588 if (dns_message_firstname(msg
->msg
, DNS_SECTION_ADDITIONAL
)
3590 dump_database_section(msg
->msg
, DNS_SECTION_ADDITIONAL
);
3596 search_type(dns_name_t
*name
, dns_rdatatype_t type
, dns_rdatatype_t covers
) {
3597 dns_rdataset_t
*rdataset
;
3598 dns_rdata_sig_t siginfo
;
3599 dns_rdata_t sigrdata
;
3600 isc_result_t result
;
3602 for (rdataset
= ISC_LIST_HEAD(name
->list
); rdataset
!= NULL
;
3603 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3604 if (type
== dns_rdatatype_any
) {
3605 if (rdataset
->type
!= dns_rdatatype_rrsig
)
3607 } else if ((type
== dns_rdatatype_rrsig
) &&
3608 (rdataset
->type
== dns_rdatatype_rrsig
)) {
3609 dns_rdata_init(&sigrdata
);
3610 result
= dns_rdataset_first(rdataset
);
3611 check_result(result
, "empty rdataset");
3612 dns_rdataset_current(rdataset
, &sigrdata
);
3613 result
= dns_rdata_tostruct(&sigrdata
, &siginfo
, NULL
);
3614 check_result(result
, "sigrdata tostruct siginfo");
3616 if ((siginfo
.covered
== covers
) ||
3617 (covers
== dns_rdatatype_any
)) {
3618 dns_rdata_reset(&sigrdata
);
3619 dns_rdata_freestruct(&siginfo
);
3622 dns_rdata_reset(&sigrdata
);
3623 dns_rdata_freestruct(&siginfo
);
3624 } else if (rdataset
->type
== type
)
3631 chase_scanname_section(dns_message_t
*msg
, dns_name_t
*name
,
3632 dns_rdatatype_t type
, dns_rdatatype_t covers
,
3635 dns_rdataset_t
*rdataset
;
3636 dns_name_t
*msg_name
= NULL
;
3639 dns_message_currentname(msg
, section
, &msg_name
);
3640 if (dns_name_compare(msg_name
, name
) == 0) {
3641 rdataset
= search_type(msg_name
, type
, covers
);
3642 if (rdataset
!= NULL
)
3646 } while (dns_message_nextname(msg
, section
) == ISC_R_SUCCESS
);
3653 chase_scanname(dns_name_t
*name
, dns_rdatatype_t type
, dns_rdatatype_t covers
)
3655 dns_rdataset_t
*rdataset
= NULL
;
3656 dig_message_t
* msg
;
3658 for (msg
= ISC_LIST_HEAD(chase_message_list2
); msg
!= NULL
;
3659 msg
= ISC_LIST_NEXT(msg
, link
)) {
3660 if (dns_message_firstname(msg
->msg
, DNS_SECTION_ANSWER
)
3662 rdataset
= chase_scanname_section(msg
->msg
, name
,
3664 DNS_SECTION_ANSWER
);
3665 if (rdataset
!= NULL
)
3667 if (dns_message_firstname(msg
->msg
, DNS_SECTION_AUTHORITY
)
3670 chase_scanname_section(msg
->msg
, name
,
3672 DNS_SECTION_AUTHORITY
);
3673 if (rdataset
!= NULL
)
3675 if (dns_message_firstname(msg
->msg
, DNS_SECTION_ADDITIONAL
)
3678 chase_scanname_section(msg
->msg
, name
, type
,
3680 DNS_SECTION_ADDITIONAL
);
3681 if (rdataset
!= NULL
)
3689 sigchase_scanname(dns_rdatatype_t type
, dns_rdatatype_t covers
,
3690 isc_boolean_t
* lookedup
, dns_name_t
*rdata_name
)
3692 dig_lookup_t
*lookup
;
3693 isc_buffer_t
*b
= NULL
;
3695 isc_result_t result
;
3696 dns_rdataset_t
* temp
;
3697 dns_rdatatype_t querytype
;
3699 temp
= chase_scanname(rdata_name
, type
, covers
);
3703 if (*lookedup
== ISC_TRUE
)
3706 lookup
= clone_lookup(current_lookup
, ISC_TRUE
);
3707 lookup
->trace_root
= ISC_FALSE
;
3708 lookup
->new_search
= ISC_TRUE
;
3710 result
= isc_buffer_allocate(mctx
, &b
, BUFSIZE
);
3711 check_result(result
, "isc_buffer_allocate");
3712 result
= dns_name_totext(rdata_name
, ISC_FALSE
, b
);
3713 check_result(result
, "dns_name_totext");
3714 isc_buffer_usedregion(b
, &r
);
3715 r
.base
[r
.length
] = '\0';
3716 strcpy(lookup
->textname
, (char*)r
.base
);
3717 isc_buffer_free(&b
);
3719 if (type
== dns_rdatatype_rrsig
)
3724 if (querytype
== 0 || querytype
== 255) {
3725 printf("Error in the queried type: %d\n", querytype
);
3729 lookup
->rdtype
= querytype
;
3730 lookup
->rdtypeset
= ISC_TRUE
;
3731 lookup
->qrdtype
= querytype
;
3732 *lookedup
= ISC_TRUE
;
3734 ISC_LIST_APPEND(lookup_list
, lookup
, link
);
3735 printf("\n\nLaunch a query to find a RRset of type ");
3737 printf(" for zone: %s\n", lookup
->textname
);
3742 insert_trustedkey(dst_key_t
* key
)
3746 if (tk_list
.nb_tk
>= MAX_TRUSTED_KEY
)
3749 tk_list
.key
[tk_list
.nb_tk
++] = key
;
3758 for (i
= 0; i
< MAX_TRUSTED_KEY
; i
++) {
3759 if (tk_list
.key
[i
] != NULL
) {
3760 dst_key_free(&tk_list
.key
[i
]);
3761 tk_list
.key
[i
] = NULL
;
3770 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
3773 removetmpkey(isc_mem_t
*mctx
, const char *file
)
3775 char *tempnamekey
= NULL
;
3777 isc_result_t result
;
3779 tempnamekeylen
= strlen(file
)+10;
3781 tempnamekey
= isc_mem_allocate(mctx
, tempnamekeylen
);
3782 if (tempnamekey
== NULL
)
3783 return (ISC_R_NOMEMORY
);
3785 memset(tempnamekey
, 0, tempnamekeylen
);
3787 strcat(tempnamekey
, file
);
3788 strcat(tempnamekey
,".key");
3789 isc_file_remove(tempnamekey
);
3791 result
= isc_file_remove(tempnamekey
);
3792 isc_mem_free(mctx
, tempnamekey
);
3797 opentmpkey(isc_mem_t
*mctx
, const char *file
, char **tempp
, FILE **fp
) {
3799 isc_result_t result
;
3800 char *tempname
= NULL
;
3801 char *tempnamekey
= NULL
;
3809 tempnamelen
= strlen(file
) + 20;
3810 tempname
= isc_mem_allocate(mctx
, tempnamelen
);
3811 if (tempname
== NULL
)
3812 return (ISC_R_NOMEMORY
);
3813 memset(tempname
, 0, tempnamelen
);
3815 result
= isc_file_mktemplate(file
, tempname
, tempnamelen
);
3816 if (result
!= ISC_R_SUCCESS
)
3822 if (cp
== tempname
) {
3823 isc_mem_free(mctx
, tempname
);
3824 return (ISC_R_FAILURE
);
3828 while (cp
>= tempname
&& *cp
== 'X') {
3829 isc_random_get(&which
);
3830 *cp
= alphnum
[which
% (sizeof(alphnum
) - 1)];
3834 tempnamekeylen
= tempnamelen
+5;
3835 tempnamekey
= isc_mem_allocate(mctx
, tempnamekeylen
);
3836 if (tempnamekey
== NULL
)
3837 return (ISC_R_NOMEMORY
);
3839 memset(tempnamekey
, 0, tempnamekeylen
);
3840 strncpy(tempnamekey
, tempname
, tempnamelen
);
3841 strcat(tempnamekey
,".key");
3844 if (isc_file_exists(tempnamekey
)) {
3845 isc_mem_free(mctx
, tempnamekey
);
3846 isc_mem_free(mctx
, tempname
);
3850 if ((f
= fopen(tempnamekey
, "w")) == NULL
) {
3851 printf("get_trusted_key(): trusted key not found %s\n",
3853 return (ISC_R_FAILURE
);
3857 isc_mem_free(mctx
, tempnamekey
);
3860 return (ISC_R_SUCCESS
);
3863 isc_mem_free(mctx
, tempname
);
3870 get_trusted_key(isc_mem_t
*mctx
)
3872 isc_result_t result
;
3873 const char *filename
= NULL
;
3874 char *filetemp
= NULL
;
3877 dst_key_t
*key
= NULL
;
3879 result
= isc_file_exists(trustedkey
);
3880 if (result
!= ISC_TRUE
) {
3881 result
= isc_file_exists("/etc/trusted-key.key");
3882 if (result
!= ISC_TRUE
) {
3883 result
= isc_file_exists("./trusted-key.key");
3884 if (result
!= ISC_TRUE
)
3885 return (ISC_R_FAILURE
);
3887 filename
= "./trusted-key.key";
3889 filename
= "/etc/trusted-key.key";
3891 filename
= trustedkey
;
3893 if (filename
== NULL
) {
3894 printf("No trusted key\n");
3895 return (ISC_R_FAILURE
);
3898 if ((fp
= fopen(filename
, "r")) == NULL
) {
3899 printf("get_trusted_key(): trusted key not found %s\n",
3901 return (ISC_R_FAILURE
);
3903 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
3904 result
= opentmpkey(mctx
,"tmp_file", &filetemp
, &fptemp
);
3905 if (result
!= ISC_R_SUCCESS
) {
3907 return (ISC_R_FAILURE
);
3909 if (fputs(buf
, fptemp
) < 0) {
3912 return (ISC_R_FAILURE
);
3915 result
= dst_key_fromnamedfile(filetemp
, DST_TYPE_PUBLIC
,
3917 removetmpkey(mctx
, filetemp
);
3918 isc_mem_free(mctx
, filetemp
);
3919 if (result
!= ISC_R_SUCCESS
) {
3921 return (ISC_R_FAILURE
);
3923 insert_trustedkey(key
);
3925 dst_key_tofile(key
, DST_TYPE_PUBLIC
,"/tmp");
3929 return (ISC_R_SUCCESS
);
3934 nameFromString(const char *str
, dns_name_t
*p_ret
) {
3935 size_t len
= strlen(str
);
3936 isc_result_t result
;
3937 isc_buffer_t buffer
;
3938 dns_fixedname_t fixedname
;
3940 REQUIRE(p_ret
!= NULL
);
3941 REQUIRE(str
!= NULL
);
3943 isc_buffer_init(&buffer
, str
, len
);
3944 isc_buffer_add(&buffer
, len
);
3946 dns_fixedname_init(&fixedname
);
3947 result
= dns_name_fromtext(dns_fixedname_name(&fixedname
), &buffer
,
3948 dns_rootname
, ISC_TRUE
, NULL
);
3949 check_result(result
, "nameFromString");
3951 if (dns_name_dynamic(p_ret
))
3952 free_name(p_ret
, mctx
);
3954 result
= dns_name_dup(dns_fixedname_name(&fixedname
), mctx
, p_ret
);
3955 check_result(result
, "nameFromString");
3961 prepare_lookup(dns_name_t
*name
)
3963 isc_result_t result
;
3964 dig_lookup_t
*lookup
= NULL
;
3968 lookup
= clone_lookup(current_lookup
, ISC_TRUE
);
3969 lookup
->trace_root
= ISC_FALSE
;
3970 lookup
->new_search
= ISC_TRUE
;
3971 lookup
->trace_root_sigchase
= ISC_FALSE
;
3973 strncpy(lookup
->textname
, lookup
->textnamesigchase
, MXNAME
);
3975 lookup
->rdtype
= lookup
->rdtype_sigchase
;
3976 lookup
->rdtypeset
= ISC_TRUE
;
3977 lookup
->qrdtype
= lookup
->qrdtype_sigchase
;
3979 s
= ISC_LIST_HEAD(lookup
->my_server_list
);
3981 debug("freeing server %p belonging to %p",
3984 s
= ISC_LIST_NEXT(s
, link
);
3985 ISC_LIST_DEQUEUE(lookup
->my_server_list
,
3986 (dig_server_t
*)ptr
, link
);
3987 isc_mem_free(mctx
, ptr
);
3991 for (result
= dns_rdataset_first(chase_nsrdataset
);
3992 result
== ISC_R_SUCCESS
;
3993 result
= dns_rdataset_next(chase_nsrdataset
)) {
3994 char namestr
[DNS_NAME_FORMATSIZE
];
3996 dns_rdata_t rdata
= DNS_RDATA_INIT
;
3997 dig_server_t
* srv
= NULL
;
3998 #define __FOLLOW_GLUE__
3999 #ifdef __FOLLOW_GLUE__
4000 isc_buffer_t
*b
= NULL
;
4001 isc_result_t result
;
4003 dns_rdataset_t
*rdataset
= NULL
;
4004 isc_boolean_t
true = ISC_TRUE
;
4007 memset(namestr
, 0, DNS_NAME_FORMATSIZE
);
4009 dns_rdataset_current(chase_nsrdataset
, &rdata
);
4011 (void)dns_rdata_tostruct(&rdata
, &ns
, NULL
);
4015 #ifdef __FOLLOW_GLUE__
4017 result
= advanced_rrsearch(&rdataset
, &ns
.name
,
4019 dns_rdatatype_any
, &true);
4020 if (result
== ISC_R_SUCCESS
) {
4021 for (result
= dns_rdataset_first(rdataset
);
4022 result
== ISC_R_SUCCESS
;
4023 result
= dns_rdataset_next(rdataset
)) {
4024 dns_rdata_t aaaa
= DNS_RDATA_INIT
;
4025 dns_rdataset_current(rdataset
, &aaaa
);
4027 result
= isc_buffer_allocate(mctx
, &b
, 80);
4028 check_result(result
, "isc_buffer_allocate");
4030 dns_rdata_totext(&aaaa
, &ns
.name
, b
);
4031 isc_buffer_usedregion(b
, &r
);
4032 r
.base
[r
.length
] = '\0';
4033 strncpy(namestr
, (char*)r
.base
,
4034 DNS_NAME_FORMATSIZE
);
4035 isc_buffer_free(&b
);
4036 dns_rdata_reset(&aaaa
);
4039 srv
= make_server(namestr
, namestr
);
4041 ISC_LIST_APPEND(lookup
->my_server_list
,
4047 result
= advanced_rrsearch(&rdataset
, &ns
.name
, dns_rdatatype_a
,
4048 dns_rdatatype_any
, &true);
4049 if (result
== ISC_R_SUCCESS
) {
4050 for (result
= dns_rdataset_first(rdataset
);
4051 result
== ISC_R_SUCCESS
;
4052 result
= dns_rdataset_next(rdataset
)) {
4053 dns_rdata_t a
= DNS_RDATA_INIT
;
4054 dns_rdataset_current(rdataset
, &a
);
4056 result
= isc_buffer_allocate(mctx
, &b
, 80);
4057 check_result(result
, "isc_buffer_allocate");
4059 dns_rdata_totext(&a
, &ns
.name
, b
);
4060 isc_buffer_usedregion(b
, &r
);
4061 r
.base
[r
.length
] = '\0';
4062 strncpy(namestr
, (char*)r
.base
,
4063 DNS_NAME_FORMATSIZE
);
4064 isc_buffer_free(&b
);
4065 dns_rdata_reset(&a
);
4066 printf("ns name: %s\n", namestr
);
4069 srv
= make_server(namestr
, namestr
);
4071 ISC_LIST_APPEND(lookup
->my_server_list
,
4077 dns_name_format(&ns
.name
, namestr
, sizeof(namestr
));
4078 printf("ns name: ");
4079 dns_name_print(&ns
.name
, stdout
);
4081 srv
= make_server(namestr
, namestr
);
4083 ISC_LIST_APPEND(lookup
->my_server_list
, srv
, link
);
4086 dns_rdata_freestruct(&ns
);
4087 dns_rdata_reset(&rdata
);
4091 ISC_LIST_APPEND(lookup_list
, lookup
, link
);
4092 printf("\nLaunch a query to find a RRset of type ");
4093 print_type(lookup
->rdtype
);
4094 printf(" for zone: %s", lookup
->textname
);
4095 printf(" with nameservers:");
4097 print_rdataset(name
, chase_nsrdataset
, mctx
);
4098 return (ISC_R_SUCCESS
);
4103 child_of_zone(dns_name_t
* name
, dns_name_t
* zone_name
,
4104 dns_name_t
* child_name
)
4106 dns_namereln_t name_reln
;
4108 unsigned int nlabelsp
;
4110 name_reln
= dns_name_fullcompare(name
, zone_name
, &orderp
, &nlabelsp
);
4111 if (name_reln
!= dns_namereln_subdomain
||
4112 dns_name_countlabels(name
) <= dns_name_countlabels(zone_name
) + 1) {
4113 printf("\n;; ERROR : ");
4114 dns_name_print(name
, stdout
);
4115 printf(" is not a subdomain of: ");
4116 dns_name_print(zone_name
, stdout
);
4117 printf(" FAILED\n\n");
4118 return (ISC_R_FAILURE
);
4121 dns_name_getlabelsequence(name
,
4122 dns_name_countlabels(name
) -
4123 dns_name_countlabels(zone_name
) -1,
4124 dns_name_countlabels(zone_name
) +1,
4126 return (ISC_R_SUCCESS
);
4130 grandfather_pb_test(dns_name_t
*zone_name
, dns_rdataset_t
*sigrdataset
)
4132 isc_result_t result
;
4133 dns_rdata_t sigrdata
;
4134 dns_rdata_sig_t siginfo
;
4136 result
= dns_rdataset_first(sigrdataset
);
4137 check_result(result
, "empty RRSIG dataset");
4138 dns_rdata_init(&sigrdata
);
4141 dns_rdataset_current(sigrdataset
, &sigrdata
);
4143 result
= dns_rdata_tostruct(&sigrdata
, &siginfo
, NULL
);
4144 check_result(result
, "sigrdata tostruct siginfo");
4146 if (dns_name_compare(&siginfo
.signer
, zone_name
) == 0) {
4147 dns_rdata_freestruct(&siginfo
);
4148 dns_rdata_reset(&sigrdata
);
4149 return (ISC_R_SUCCESS
);
4152 dns_rdata_freestruct(&siginfo
);
4154 } while (dns_rdataset_next(chase_sigkeyrdataset
) == ISC_R_SUCCESS
);
4156 dns_rdata_reset(&sigrdata
);
4158 return (ISC_R_FAILURE
);
4163 initialization(dns_name_t
*name
)
4165 isc_result_t result
;
4166 isc_boolean_t
true = ISC_TRUE
;
4168 chase_nsrdataset
= NULL
;
4169 result
= advanced_rrsearch(&chase_nsrdataset
, name
, dns_rdatatype_ns
,
4170 dns_rdatatype_any
, &true);
4171 if (result
!= ISC_R_SUCCESS
) {
4172 printf("\n;; NS RRset is missing to continue validation:"
4174 return (ISC_R_FAILURE
);
4176 INSIST(chase_nsrdataset
!= NULL
);
4177 prepare_lookup(name
);
4179 dup_name(name
, &chase_current_name
, mctx
);
4181 return (ISC_R_SUCCESS
);
4186 print_rdataset(dns_name_t
*name
, dns_rdataset_t
*rdataset
, isc_mem_t
*mctx
)
4188 isc_buffer_t
*b
= NULL
;
4189 isc_result_t result
;
4192 result
= isc_buffer_allocate(mctx
, &b
, 9000);
4193 check_result(result
, "isc_buffer_allocate");
4195 printrdataset(name
, rdataset
, b
);
4197 isc_buffer_usedregion(b
, &r
);
4198 r
.base
[r
.length
] = '\0';
4201 printf("%s\n", r
.base
);
4203 isc_buffer_free(&b
);
4208 dup_name(dns_name_t
*source
, dns_name_t
*target
, isc_mem_t
*mctx
) {
4209 isc_result_t result
;
4211 if (dns_name_dynamic(target
))
4212 free_name(target
, mctx
);
4213 result
= dns_name_dup(source
, mctx
, target
);
4214 check_result(result
, "dns_name_dup");
4218 free_name(dns_name_t
*name
, isc_mem_t
*mctx
) {
4219 dns_name_free(name
, mctx
);
4220 dns_name_init(name
, NULL
);
4225 * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter
4226 * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key
4227 * and the RRset is valid
4228 * return ISC_R_NOTFOUND if not contains trusted key
4229 or if the RRset isn't valid
4230 * return ISC_R_FAILURE if problem
4234 contains_trusted_key(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
4235 dns_rdataset_t
*sigrdataset
,
4238 isc_result_t result
;
4240 dst_key_t
*trustedKey
= NULL
;
4241 dst_key_t
*dnsseckey
= NULL
;
4244 if (name
== NULL
|| rdataset
== NULL
)
4245 return (ISC_R_FAILURE
);
4247 result
= dns_rdataset_first(rdataset
);
4248 check_result(result
, "empty rdataset");
4249 dns_rdata_init(&rdata
);
4252 dns_rdataset_current(rdataset
, &rdata
);
4253 INSIST(rdata
.type
== dns_rdatatype_dnskey
);
4255 result
= dns_dnssec_keyfromrdata(name
, &rdata
,
4257 check_result(result
, "dns_dnssec_keyfromrdata");
4260 for (i
= 0; i
< tk_list
.nb_tk
; i
++) {
4261 if (dst_key_compare(tk_list
.key
[i
], dnsseckey
)
4263 dns_rdata_reset(&rdata
);
4265 printf(";; Ok, find a Trusted Key in the "
4266 "DNSKEY RRset: %d\n",
4267 dst_key_id(dnsseckey
));
4268 if (sigchase_verify_sig_key(name
, rdataset
,
4273 dst_key_free(&dnsseckey
);
4275 return (ISC_R_SUCCESS
);
4280 dns_rdata_reset(&rdata
);
4281 if (dnsseckey
!= NULL
)
4282 dst_key_free(&dnsseckey
);
4283 } while (dns_rdataset_next(rdataset
) == ISC_R_SUCCESS
);
4285 if (trustedKey
!= NULL
)
4286 dst_key_free(&trustedKey
);
4289 return (ISC_R_NOTFOUND
);
4293 sigchase_verify_sig(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
4294 dns_rdataset_t
*keyrdataset
,
4295 dns_rdataset_t
*sigrdataset
,
4298 isc_result_t result
;
4299 dns_rdata_t keyrdata
;
4300 dst_key_t
*dnsseckey
= NULL
;
4302 result
= dns_rdataset_first(keyrdataset
);
4303 check_result(result
, "empty DNSKEY dataset");
4304 dns_rdata_init(&keyrdata
);
4307 dns_rdataset_current(keyrdataset
, &keyrdata
);
4308 INSIST(keyrdata
.type
== dns_rdatatype_dnskey
);
4310 result
= dns_dnssec_keyfromrdata(name
, &keyrdata
,
4312 check_result(result
, "dns_dnssec_keyfromrdata");
4314 result
= sigchase_verify_sig_key(name
, rdataset
, dnsseckey
,
4316 if (result
== ISC_R_SUCCESS
) {
4317 dns_rdata_reset(&keyrdata
);
4318 dst_key_free(&dnsseckey
);
4319 return (ISC_R_SUCCESS
);
4321 dst_key_free(&dnsseckey
);
4322 } while (dns_rdataset_next(chase_keyrdataset
) == ISC_R_SUCCESS
);
4324 dns_rdata_reset(&keyrdata
);
4326 return (ISC_R_NOTFOUND
);
4330 sigchase_verify_sig_key(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
4331 dst_key_t
*dnsseckey
, dns_rdataset_t
*sigrdataset
,
4334 isc_result_t result
;
4335 dns_rdata_t sigrdata
;
4336 dns_rdata_sig_t siginfo
;
4338 result
= dns_rdataset_first(sigrdataset
);
4339 check_result(result
, "empty RRSIG dataset");
4340 dns_rdata_init(&sigrdata
);
4343 dns_rdataset_current(sigrdataset
, &sigrdata
);
4345 result
= dns_rdata_tostruct(&sigrdata
, &siginfo
, NULL
);
4346 check_result(result
, "sigrdata tostruct siginfo");
4349 * Test if the id of the DNSKEY is
4350 * the id of the DNSKEY signer's
4352 if (siginfo
.keyid
== dst_key_id(dnsseckey
)) {
4354 result
= dns_rdataset_first(rdataset
);
4355 check_result(result
, "empty DS dataset");
4357 result
= dns_dnssec_verify(name
, rdataset
, dnsseckey
,
4358 ISC_FALSE
, mctx
, &sigrdata
);
4360 printf(";; VERIFYING ");
4361 print_type(rdataset
->type
);
4362 printf(" RRset for ");
4363 dns_name_print(name
, stdout
);
4364 printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey
),
4365 isc_result_totext(result
));
4367 if (result
== ISC_R_SUCCESS
) {
4368 dns_rdata_reset(&sigrdata
);
4372 dns_rdata_freestruct(&siginfo
);
4374 } while (dns_rdataset_next(chase_sigkeyrdataset
) == ISC_R_SUCCESS
);
4376 dns_rdata_reset(&sigrdata
);
4378 return (ISC_R_NOTFOUND
);
4383 sigchase_verify_ds(dns_name_t
*name
, dns_rdataset_t
*keyrdataset
,
4384 dns_rdataset_t
*dsrdataset
, isc_mem_t
*mctx
)
4386 isc_result_t result
;
4387 dns_rdata_t keyrdata
;
4388 dns_rdata_t newdsrdata
;
4389 dns_rdata_t dsrdata
;
4390 dns_rdata_ds_t dsinfo
;
4391 dst_key_t
*dnsseckey
= NULL
;
4392 unsigned char dsbuf
[DNS_DS_BUFFERSIZE
];
4394 result
= dns_rdataset_first(dsrdataset
);
4395 check_result(result
, "empty DSset dataset");
4396 dns_rdata_init(&dsrdata
);
4398 dns_rdataset_current(dsrdataset
, &dsrdata
);
4400 result
= dns_rdata_tostruct(&dsrdata
, &dsinfo
, NULL
);
4401 check_result(result
, "dns_rdata_tostruct for DS");
4403 result
= dns_rdataset_first(keyrdataset
);
4404 check_result(result
, "empty KEY dataset");
4405 dns_rdata_init(&keyrdata
);
4408 dns_rdataset_current(keyrdataset
, &keyrdata
);
4409 INSIST(keyrdata
.type
== dns_rdatatype_dnskey
);
4411 result
= dns_dnssec_keyfromrdata(name
, &keyrdata
,
4413 check_result(result
, "dns_dnssec_keyfromrdata");
4416 * Test if the id of the DNSKEY is the
4417 * id of DNSKEY referenced by the DS
4419 if (dsinfo
.key_tag
== dst_key_id(dnsseckey
)) {
4420 dns_rdata_init(&newdsrdata
);
4422 result
= dns_ds_buildrdata(name
, &keyrdata
,
4424 dsbuf
, &newdsrdata
);
4425 dns_rdata_freestruct(&dsinfo
);
4427 if (result
!= ISC_R_SUCCESS
) {
4428 dns_rdata_reset(&keyrdata
);
4429 dns_rdata_reset(&newdsrdata
);
4430 dns_rdata_reset(&dsrdata
);
4431 dst_key_free(&dnsseckey
);
4432 dns_rdata_freestruct(&dsinfo
);
4433 printf("Oops: impossible to build"
4439 if (dns_rdata_compare(&dsrdata
,
4440 &newdsrdata
) == 0) {
4441 printf(";; OK a DS valids a DNSKEY"
4443 printf(";; Now verify that this"
4444 " DNSKEY validates the "
4447 result
= sigchase_verify_sig_key(name
,
4450 chase_sigkeyrdataset
,
4452 if (result
== ISC_R_SUCCESS
) {
4453 dns_rdata_reset(&keyrdata
);
4454 dns_rdata_reset(&newdsrdata
);
4455 dns_rdata_reset(&dsrdata
);
4456 dst_key_free(&dnsseckey
);
4461 printf(";; This DS is NOT the DS for"
4462 " the chasing KEY: FAILED\n");
4465 dns_rdata_reset(&newdsrdata
);
4467 dst_key_free(&dnsseckey
);
4469 } while (dns_rdataset_next(chase_keyrdataset
) == ISC_R_SUCCESS
);
4470 dns_rdata_reset(&keyrdata
);
4472 } while (dns_rdataset_next(chase_dsrdataset
) == ISC_R_SUCCESS
);
4474 dns_rdata_reset(&dsrdata
); WARNING
4477 return (ISC_R_NOTFOUND
);
4482 * take a pointer on a rdataset in parameter and try to resolv it.
4483 * the searched rrset is a rrset on 'name' with type 'type'
4484 * (and if the type is a rrsig the signature cover 'covers').
4485 * the lookedup is to known if you have already done the query on the net.
4486 * ISC_R_SUCCESS: if we found the rrset
4487 * ISC_R_NOTFOUND: we do not found the rrset in cache
4488 * and we do a query on the net
4489 * ISC_R_FAILURE: rrset not found
4492 advanced_rrsearch(dns_rdataset_t
**rdataset
, dns_name_t
*name
,
4493 dns_rdatatype_t type
, dns_rdatatype_t covers
,
4494 isc_boolean_t
*lookedup
)
4496 isc_boolean_t tmplookedup
;
4498 INSIST(rdataset
!= NULL
);
4500 if (*rdataset
!= NULL
)
4501 return (ISC_R_SUCCESS
);
4503 tmplookedup
= *lookedup
;
4504 if ((*rdataset
= sigchase_scanname(type
, covers
,
4505 lookedup
, name
)) == NULL
) {
4507 return (ISC_R_FAILURE
);
4508 return (ISC_R_NOTFOUND
);
4510 *lookedup
= ISC_FALSE
;
4511 return (ISC_R_SUCCESS
);
4518 sigchase_td(dns_message_t
*msg
)
4520 isc_result_t result
;
4521 dns_name_t
*name
= NULL
;
4522 isc_boolean_t have_answer
= ISC_FALSE
;
4523 isc_boolean_t
true = ISC_TRUE
;
4525 if ((result
= dns_message_firstname(msg
, DNS_SECTION_ANSWER
))
4527 dns_message_currentname(msg
, DNS_SECTION_ANSWER
, &name
);
4528 if (current_lookup
->trace_root_sigchase
) {
4529 initialization(name
);
4534 if (!current_lookup
->trace_root_sigchase
) {
4535 result
= dns_message_firstname(msg
,
4536 DNS_SECTION_AUTHORITY
);
4537 if (result
== ISC_R_SUCCESS
)
4538 dns_message_currentname(msg
,
4539 DNS_SECTION_AUTHORITY
,
4542 = chase_scanname_section(msg
, name
,
4545 DNS_SECTION_AUTHORITY
);
4546 dup_name(name
, &chase_authority_name
, mctx
);
4547 if (chase_nsrdataset
!= NULL
) {
4548 have_delegation_ns
= ISC_TRUE
;
4549 printf("no response but there is a delegation"
4550 " in authority section:");
4551 dns_name_print(name
, stdout
);
4554 printf("no response and no delegation in "
4555 "authority section but a reference"
4557 dns_name_print(name
, stdout
);
4559 error_message
= msg
;
4562 printf(";; NO ANSWERS: %s\n",
4563 isc_result_totext(result
));
4564 free_name(&chase_name
, mctx
);
4573 = chase_scanname_section(msg
, &chase_name
,
4577 DNS_SECTION_ANSWER
);
4578 if (chase_rdataset
!= NULL
)
4579 have_response
= ISC_TRUE
;
4582 result
= advanced_rrsearch(&chase_keyrdataset
,
4583 &chase_current_name
,
4584 dns_rdatatype_dnskey
,
4586 &chase_keylookedup
);
4587 if (result
== ISC_R_FAILURE
) {
4588 printf("\n;; DNSKEY is missing to continue validation:"
4592 if (result
== ISC_R_NOTFOUND
)
4594 INSIST(chase_keyrdataset
!= NULL
);
4595 printf("\n;; DNSKEYset:\n");
4596 print_rdataset(&chase_current_name
, chase_keyrdataset
, mctx
);
4599 result
= advanced_rrsearch(&chase_sigkeyrdataset
,
4600 &chase_current_name
,
4601 dns_rdatatype_rrsig
,
4602 dns_rdatatype_dnskey
,
4603 &chase_sigkeylookedup
);
4604 if (result
== ISC_R_FAILURE
) {
4605 printf("\n;; RRSIG of DNSKEY is missing to continue validation:"
4609 if (result
== ISC_R_NOTFOUND
)
4611 INSIST(chase_sigkeyrdataset
!= NULL
);
4612 printf("\n;; RRSIG of the DNSKEYset:\n");
4613 print_rdataset(&chase_current_name
, chase_sigkeyrdataset
, mctx
);
4616 if (!chase_dslookedup
&& !chase_nslookedup
) {
4617 if (!delegation_follow
) {
4618 result
= contains_trusted_key(&chase_current_name
,
4620 chase_sigkeyrdataset
,
4623 INSIST(chase_dsrdataset
!= NULL
);
4624 INSIST(chase_sigdsrdataset
!= NULL
);
4625 result
= sigchase_verify_ds(&chase_current_name
,
4631 if (result
!= ISC_R_SUCCESS
) {
4632 printf("\n;; chain of trust can't be validated:"
4636 chase_dsrdataset
= NULL
;
4637 chase_sigdsrdataset
= NULL
;
4641 if (have_response
|| (!have_delegation_ns
&& !have_response
)) {
4642 /* test if it's a grand father case */
4644 if (have_response
) {
4645 result
= advanced_rrsearch(&chase_sigrdataset
,
4647 dns_rdatatype_rrsig
,
4651 if (result
== ISC_R_FAILURE
) {
4652 printf("\n;; RRset is missing to continue"
4653 " validation SHOULD NOT APPEND:"
4659 result
= advanced_rrsearch(&chase_sigrdataset
,
4660 &chase_authority_name
,
4661 dns_rdatatype_rrsig
,
4664 if (result
== ISC_R_FAILURE
) {
4665 printf("\n;; RRSIG is missing to continue"
4666 " validation SHOULD NOT APPEND:"
4671 result
= grandfather_pb_test(&chase_current_name
,
4673 if (result
!= ISC_R_SUCCESS
) {
4674 dns_name_t tmp_name
;
4676 printf("\n;; We are in a Grand Father Problem:"
4677 " See 2.2.1 in RFC 3568\n");
4678 chase_rdataset
= NULL
;
4679 chase_sigrdataset
= NULL
;
4680 have_response
= ISC_FALSE
;
4681 have_delegation_ns
= ISC_FALSE
;
4683 dns_name_init(&tmp_name
, NULL
);
4684 result
= child_of_zone(&chase_name
, &chase_current_name
,
4686 if (dns_name_dynamic(&chase_authority_name
))
4687 free_name(&chase_authority_name
, mctx
);
4688 dup_name(&tmp_name
, &chase_authority_name
, mctx
);
4689 printf(";; and we try to continue chain of trust"
4690 " validation of the zone: ");
4691 dns_name_print(&chase_authority_name
, stdout
);
4693 have_delegation_ns
= ISC_TRUE
;
4698 chase_sigrdataset
= NULL
;
4702 if (have_delegation_ns
) {
4703 chase_nsrdataset
= NULL
;
4704 result
= advanced_rrsearch(&chase_nsrdataset
,
4705 &chase_authority_name
,
4709 if (result
== ISC_R_FAILURE
) {
4710 printf("\n;;NSset is missing to continue validation:"
4714 if (result
== ISC_R_NOTFOUND
) {
4717 INSIST(chase_nsrdataset
!= NULL
);
4719 result
= advanced_rrsearch(&chase_dsrdataset
,
4720 &chase_authority_name
,
4724 if (result
== ISC_R_FAILURE
) {
4725 printf("\n;; DSset is missing to continue validation:"
4729 if (result
== ISC_R_NOTFOUND
)
4731 INSIST(chase_dsrdataset
!= NULL
);
4732 printf("\n;; DSset:\n");
4733 print_rdataset(&chase_authority_name
, chase_dsrdataset
, mctx
);
4735 result
= advanced_rrsearch(&chase_sigdsrdataset
,
4736 &chase_authority_name
,
4737 dns_rdatatype_rrsig
,
4740 if (result
!= ISC_R_SUCCESS
) {
4741 printf("\n;; DSset is missing to continue validation:"
4745 printf("\n;; RRSIGset of DSset\n");
4746 print_rdataset(&chase_authority_name
,
4747 chase_sigdsrdataset
, mctx
);
4748 INSIST(chase_sigdsrdataset
!= NULL
);
4750 result
= sigchase_verify_sig(&chase_authority_name
,
4753 chase_sigdsrdataset
, mctx
);
4754 if (result
!= ISC_R_SUCCESS
) {
4755 printf("\n;; Impossible to verify the DSset:"
4759 chase_keyrdataset
= NULL
;
4760 chase_sigkeyrdataset
= NULL
;
4763 prepare_lookup(&chase_authority_name
);
4765 have_response
= ISC_FALSE
;
4766 have_delegation_ns
= ISC_FALSE
;
4767 delegation_follow
= ISC_TRUE
;
4768 error_message
= NULL
;
4769 dup_name(&chase_authority_name
, &chase_current_name
, mctx
);
4770 free_name(&chase_authority_name
, mctx
);
4775 if (error_message
!= NULL
) {
4776 dns_rdataset_t
*rdataset
;
4777 dns_rdataset_t
*sigrdataset
;
4778 dns_name_t rdata_name
;
4779 isc_result_t ret
= ISC_R_FAILURE
;
4781 dns_name_init(&rdata_name
, NULL
);
4782 result
= prove_nx(error_message
, &chase_name
,
4783 current_lookup
->rdclass_sigchase
,
4784 current_lookup
->rdtype_sigchase
, &rdata_name
,
4785 &rdataset
, &sigrdataset
);
4786 if (rdataset
== NULL
|| sigrdataset
== NULL
||
4787 dns_name_countlabels(&rdata_name
) == 0) {
4788 printf("\n;; Impossible to verify the non-existence,"
4789 " the NSEC RRset can't be validated:"
4793 ret
= sigchase_verify_sig(&rdata_name
, rdataset
,
4796 if (ret
!= ISC_R_SUCCESS
) {
4797 free_name(&rdata_name
, mctx
);
4798 printf("\n;; Impossible to verify the NSEC RR to prove"
4799 " the non-existence : FAILED\n\n");
4802 free_name(&rdata_name
, mctx
);
4803 if (result
!= ISC_R_SUCCESS
) {
4804 printf("\n;; Impossible to verify the non-existence:"
4808 printf("\n;; OK the query doesn't have response but"
4809 " we have validate this fact : SUCCESS\n\n");
4815 printf(";; cleanandgo \n");
4816 if (dns_name_dynamic(&chase_current_name
))
4817 free_name(&chase_current_name
, mctx
);
4818 if (dns_name_dynamic(&chase_authority_name
))
4819 free_name(&chase_authority_name
, mctx
);
4824 result
= advanced_rrsearch(&chase_rdataset
, &chase_name
,
4825 current_lookup
->rdtype_sigchase
,
4828 if (result
== ISC_R_FAILURE
) {
4829 printf("\n;; RRsig of RRset is missing to continue validation"
4830 " SHOULD NOT APPEND: FAILED\n\n");
4833 result
= sigchase_verify_sig(&chase_name
, chase_rdataset
,
4835 chase_sigrdataset
, mctx
);
4836 if (result
!= ISC_R_SUCCESS
) {
4837 printf("\n;; Impossible to verify the RRset : FAILED\n\n");
4840 print_rdataset(&chase_name , chase_rdataset, mctx);
4841 printf("DNSKEYset:\n");
4842 print_rdataset(&chase_name , chase_keyrdataset, mctx);
4843 printf("RRSIG of RRset:\n");
4844 print_rdataset(&chase_name , chase_sigrdataset, mctx);
4849 printf("\n;; The Answer:\n");
4850 print_rdataset(&chase_name
, chase_rdataset
, mctx
);
4852 printf("\n;; FINISH : we have validate the DNSSEC chain"
4853 " of trust: SUCCESS\n\n");
4864 getneededrr(dns_message_t
*msg
)
4866 isc_result_t result
;
4867 dns_name_t
*name
= NULL
;
4868 dns_rdata_t sigrdata
;
4869 dns_rdata_sig_t siginfo
;
4870 isc_boolean_t
true = ISC_TRUE
;
4872 if ((result
= dns_message_firstname(msg
, DNS_SECTION_ANSWER
))
4874 printf(";; NO ANSWERS: %s\n", isc_result_totext(result
));
4876 if (chase_name
.ndata
== NULL
)
4877 return (ISC_R_ADDRNOTAVAIL
);
4879 dns_message_currentname(msg
, DNS_SECTION_ANSWER
, &name
);
4882 /* What do we chase? */
4883 if (chase_rdataset
== NULL
) {
4884 result
= advanced_rrsearch(&chase_rdataset
, name
,
4886 dns_rdatatype_any
, &true);
4887 if (result
!= ISC_R_SUCCESS
) {
4888 printf("\n;; No Answers: Validation FAILED\n\n");
4889 return (ISC_R_NOTFOUND
);
4891 dup_name(name
, &chase_name
, mctx
);
4892 printf(";; RRset to chase:\n");
4893 print_rdataset(&chase_name
, chase_rdataset
, mctx
);
4895 INSIST(chase_rdataset
!= NULL
);
4898 if (chase_sigrdataset
== NULL
) {
4899 result
= advanced_rrsearch(&chase_sigrdataset
, name
,
4900 dns_rdatatype_rrsig
,
4901 chase_rdataset
->type
,
4902 &chase_siglookedup
);
4903 if (result
== ISC_R_FAILURE
) {
4904 printf("\n;; RRSIG is missing for continue validation:"
4906 if (dns_name_dynamic(&chase_name
))
4907 free_name(&chase_name
, mctx
);
4908 return (ISC_R_NOTFOUND
);
4910 if (result
== ISC_R_NOTFOUND
) {
4911 return (ISC_R_NOTFOUND
);
4913 printf("\n;; RRSIG of the RRset to chase:\n");
4914 print_rdataset(&chase_name
, chase_sigrdataset
, mctx
);
4916 INSIST(chase_sigrdataset
!= NULL
);
4919 /* first find the DNSKEY name */
4920 result
= dns_rdataset_first(chase_sigrdataset
);
4921 check_result(result
, "empty RRSIG dataset");
4922 dns_rdata_init(&sigrdata
);
4923 dns_rdataset_current(chase_sigrdataset
, &sigrdata
);
4924 result
= dns_rdata_tostruct(&sigrdata
, &siginfo
, NULL
);
4925 check_result(result
, "sigrdata tostruct siginfo");
4926 dup_name(&siginfo
.signer
, &chase_signame
, mctx
);
4927 dns_rdata_freestruct(&siginfo
);
4928 dns_rdata_reset(&sigrdata
);
4930 /* Do we have a key? */
4931 if (chase_keyrdataset
== NULL
) {
4932 result
= advanced_rrsearch(&chase_keyrdataset
,
4934 dns_rdatatype_dnskey
,
4936 &chase_keylookedup
);
4937 if (result
== ISC_R_FAILURE
) {
4938 printf("\n;; DNSKEY is missing to continue validation:"
4940 free_name(&chase_signame
, mctx
);
4941 if (dns_name_dynamic(&chase_name
))
4942 free_name(&chase_name
, mctx
);
4943 return (ISC_R_NOTFOUND
);
4945 if (result
== ISC_R_NOTFOUND
) {
4946 free_name(&chase_signame
, mctx
);
4947 return (ISC_R_NOTFOUND
);
4949 printf("\n;; DNSKEYset that signs the RRset to chase:\n");
4950 print_rdataset(&chase_signame
, chase_keyrdataset
, mctx
);
4952 INSIST(chase_keyrdataset
!= NULL
);
4954 if (chase_sigkeyrdataset
== NULL
) {
4955 result
= advanced_rrsearch(&chase_sigkeyrdataset
,
4957 dns_rdatatype_rrsig
,
4958 dns_rdatatype_dnskey
,
4959 &chase_sigkeylookedup
);
4960 if (result
== ISC_R_FAILURE
) {
4961 printf("\n;; RRSIG for DNSKEY is missing to continue"
4962 " validation : FAILED\n\n");
4963 free_name(&chase_signame
, mctx
);
4964 if (dns_name_dynamic(&chase_name
))
4965 free_name(&chase_name
, mctx
);
4966 return (ISC_R_NOTFOUND
);
4968 if (result
== ISC_R_NOTFOUND
) {
4969 free_name(&chase_signame
, mctx
);
4970 return (ISC_R_NOTFOUND
);
4972 printf("\n;; RRSIG of the DNSKEYset that signs the "
4973 "RRset to chase:\n");
4974 print_rdataset(&chase_signame
, chase_sigkeyrdataset
, mctx
);
4976 INSIST(chase_sigkeyrdataset
!= NULL
);
4979 if (chase_dsrdataset
== NULL
) {
4980 result
= advanced_rrsearch(&chase_dsrdataset
, &chase_signame
,
4984 if (result
== ISC_R_FAILURE
) {
4985 printf("\n;; WARNING There is no DS for the zone: ");
4986 dns_name_print(&chase_signame
, stdout
);
4989 if (result
== ISC_R_NOTFOUND
) {
4990 free_name(&chase_signame
, mctx
);
4991 return (ISC_R_NOTFOUND
);
4993 if (chase_dsrdataset
!= NULL
) {
4994 printf("\n;; DSset of the DNSKEYset\n");
4995 print_rdataset(&chase_signame
, chase_dsrdataset
, mctx
);
4999 if (chase_dsrdataset
!= NULL
) {
5001 * if there is no RRSIG of DS,
5002 * we don't want to search on the network
5004 result
= advanced_rrsearch(&chase_sigdsrdataset
,
5006 dns_rdatatype_rrsig
,
5007 dns_rdatatype_ds
, &true);
5008 if (result
== ISC_R_FAILURE
) {
5009 printf(";; WARNING : NO RRSIG DS : RRSIG DS"
5010 " should come with DS\n");
5012 * We continue even the DS couldn't be validated,
5013 * because the DNSKEY could be a Trusted Key.
5015 chase_dsrdataset
= NULL
;
5017 printf("\n;; RRSIG of the DSset of the DNSKEYset\n");
5018 print_rdataset(&chase_signame
, chase_sigdsrdataset
,
5028 sigchase_bu(dns_message_t
*msg
)
5030 isc_result_t result
;
5033 if (tk_list
.nb_tk
== 0) {
5034 result
= get_trusted_key(mctx
);
5035 if (result
!= ISC_R_SUCCESS
) {
5036 printf("No trusted keys present\n");
5042 ret
= getneededrr(msg
);
5043 if (ret
== ISC_R_NOTFOUND
)
5046 if (ret
== ISC_R_ADDRNOTAVAIL
) {
5047 /* We have no response */
5048 dns_rdataset_t
*rdataset
;
5049 dns_rdataset_t
*sigrdataset
;
5050 dns_name_t rdata_name
;
5051 dns_name_t query_name
;
5054 dns_name_init(&query_name
, NULL
);
5055 dns_name_init(&rdata_name
, NULL
);
5056 nameFromString(current_lookup
->textname
, &query_name
);
5058 result
= prove_nx(msg
, &query_name
, current_lookup
->rdclass
,
5059 current_lookup
->rdtype
, &rdata_name
,
5060 &rdataset
, &sigrdataset
);
5061 free_name(&query_name
, mctx
);
5062 if (rdataset
== NULL
|| sigrdataset
== NULL
||
5063 dns_name_countlabels(&rdata_name
) == 0) {
5064 printf("\n;; Impossible to verify the Non-existence,"
5065 " the NSEC RRset can't be validated: "
5071 if (result
!= ISC_R_SUCCESS
) {
5072 printf("\n No Answers and impossible to prove the"
5073 " unsecurity : Validation FAILED\n\n");
5077 printf(";; An NSEC prove the non-existence of a answers,"
5078 " Now we want validate this NSEC\n");
5080 dup_name(&rdata_name
, &chase_name
, mctx
);
5081 free_name(&rdata_name
, mctx
);
5082 chase_rdataset
= rdataset
;
5083 chase_sigrdataset
= sigrdataset
;
5084 chase_keyrdataset
= NULL
;
5085 chase_sigkeyrdataset
= NULL
;
5086 chase_dsrdataset
= NULL
;
5087 chase_sigdsrdataset
= NULL
;
5088 chase_siglookedup
= ISC_FALSE
;
5089 chase_keylookedup
= ISC_FALSE
;
5090 chase_dslookedup
= ISC_FALSE
;
5091 chase_sigdslookedup
= ISC_FALSE
;
5098 printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n");
5100 result
= sigchase_verify_sig(&chase_name
, chase_rdataset
,
5102 chase_sigrdataset
, mctx
);
5103 if (result
!= ISC_R_SUCCESS
) {
5104 free_name(&chase_name
, mctx
);
5105 free_name(&chase_signame
, mctx
);
5106 printf(";; No DNSKEY is valid to check the RRSIG"
5107 " of the RRset: FAILED\n");
5111 printf(";; OK We found DNSKEY (or more) to validate the RRset\n");
5113 result
= contains_trusted_key(&chase_signame
, chase_keyrdataset
,
5114 chase_sigkeyrdataset
, mctx
);
5115 if (result
== ISC_R_SUCCESS
) {
5116 free_name(&chase_name
, mctx
);
5117 free_name(&chase_signame
, mctx
);
5118 printf("\n;; Ok this DNSKEY is a Trusted Key,"
5119 " DNSSEC validation is ok: SUCCESS\n\n");
5124 printf(";; Now, we are going to validate this DNSKEY by the DS\n");
5126 if (chase_dsrdataset
== NULL
) {
5127 free_name(&chase_name
, mctx
);
5128 free_name(&chase_signame
, mctx
);
5129 printf(";; the DNSKEY isn't trusted-key and there isn't"
5130 " DS to validate the DNSKEY: FAILED\n");
5135 result
= sigchase_verify_ds(&chase_signame
, chase_keyrdataset
,
5136 chase_dsrdataset
, mctx
);
5137 if (result
!= ISC_R_SUCCESS
) {
5138 free_name(&chase_signame
, mctx
);
5139 free_name(&chase_name
, mctx
);
5140 printf(";; ERROR no DS validates a DNSKEY in the"
5141 " DNSKEY RRset: FAILED\n");
5145 printf(";; OK this DNSKEY (validated by the DS) validates"
5146 " the RRset of the DNSKEYs, thus the DNSKEY validates"
5148 INSIST(chase_sigdsrdataset
!= NULL
);
5150 dup_name(&chase_signame
, &chase_name
, mctx
);
5151 free_name(&chase_signame
, mctx
);
5152 chase_rdataset
= chase_dsrdataset
;
5153 chase_sigrdataset
= chase_sigdsrdataset
;
5154 chase_keyrdataset
= NULL
;
5155 chase_sigkeyrdataset
= NULL
;
5156 chase_dsrdataset
= NULL
;
5157 chase_sigdsrdataset
= NULL
;
5158 chase_siglookedup
= chase_keylookedup
= ISC_FALSE
;
5159 chase_dslookedup
= chase_sigdslookedup
= ISC_FALSE
;
5161 printf(";; Now, we want to validate the DS : recursive call\n");
5168 sigchase(dns_message_t
*msg
) {
5170 if (current_lookup
->do_topdown
) {
5183 * return 1 if name1 < name2
5184 * 0 if name1 == name2
5185 * -1 if name1 > name2
5189 inf_name(dns_name_t
*name1
, dns_name_t
*name2
)
5193 unsigned int nblabel1
;
5194 unsigned int nblabel2
;
5199 nblabel1
= dns_name_countlabels(name1
);
5200 nblabel2
= dns_name_countlabels(name2
);
5202 if (nblabel1
>= nblabel2
)
5203 min_lum_label
= nblabel2
;
5205 min_lum_label
= nblabel1
;
5208 for (i
=1 ; i
< min_lum_label
; i
++) {
5209 dns_name_getlabel(name1
, nblabel1
-1 - i
, &label1
);
5210 dns_name_getlabel(name2
, nblabel2
-1 - i
, &label2
);
5211 if ((ret
= isc_region_compare(&label1
, &label2
)) != 0) {
5218 if (nblabel1
== nblabel2
)
5221 if (nblabel1
< nblabel2
)
5233 prove_nx_domain(dns_message_t
*msg
,
5235 dns_name_t
*rdata_name
,
5236 dns_rdataset_t
**rdataset
,
5237 dns_rdataset_t
**sigrdataset
)
5239 isc_result_t ret
= ISC_R_FAILURE
;
5240 isc_result_t result
= ISC_R_NOTFOUND
;
5241 dns_rdataset_t
*nsecset
= NULL
;
5242 dns_rdataset_t
*signsecset
= NULL
;
5243 dns_rdata_t nsec
= DNS_RDATA_INIT
;
5244 dns_name_t
*nsecname
;
5245 dns_rdata_nsec_t nsecstruct
;
5247 if ((result
= dns_message_firstname(msg
, DNS_SECTION_AUTHORITY
))
5249 printf(";; nothing in authority section : impossible to"
5250 " validate the non-existence : FAILED\n");
5251 return (ISC_R_FAILURE
);
5256 dns_message_currentname(msg
, DNS_SECTION_AUTHORITY
, &nsecname
);
5257 nsecset
= search_type(nsecname
, dns_rdatatype_nsec
,
5259 if (nsecset
== NULL
)
5262 printf("There is a NSEC for this zone in the"
5263 " AUTHORITY section:\n");
5264 print_rdataset(nsecname
, nsecset
, mctx
);
5266 for (result
= dns_rdataset_first(nsecset
);
5267 result
== ISC_R_SUCCESS
;
5268 result
= dns_rdataset_next(nsecset
)) {
5269 dns_rdataset_current(nsecset
, &nsec
);
5273 = chase_scanname_section(msg
, nsecname
,
5274 dns_rdatatype_rrsig
,
5276 DNS_SECTION_AUTHORITY
);
5277 if (signsecset
== NULL
) {
5278 printf(";; no RRSIG NSEC in authority section:"
5279 " impossible to validate the "
5280 "non-existence: FAILED\n");
5281 return (ISC_R_FAILURE
);
5284 ret
= dns_rdata_tostruct(&nsec
, &nsecstruct
, NULL
);
5285 check_result(ret
,"dns_rdata_tostruct");
5287 if ((inf_name(nsecname
, &nsecstruct
.next
) == 1 &&
5288 inf_name(name
, &nsecstruct
.next
) == 1) ||
5289 (inf_name(name
, nsecname
) == 1 &&
5290 inf_name(&nsecstruct
.next
, name
) == 1)) {
5291 dns_rdata_freestruct(&nsecstruct
);
5292 *rdataset
= nsecset
;
5293 *sigrdataset
= signsecset
;
5294 dup_name(nsecname
, rdata_name
, mctx
);
5296 return (ISC_R_SUCCESS
);
5299 dns_rdata_freestruct(&nsecstruct
);
5301 } while (dns_message_nextname(msg
, DNS_SECTION_AUTHORITY
)
5305 *sigrdataset
= NULL
;
5307 return (ISC_R_FAILURE
);
5318 prove_nx_type(dns_message_t
*msg
, dns_name_t
*name
, dns_rdataset_t
*nsecset
,
5319 dns_rdataclass_t
class, dns_rdatatype_t type
,
5320 dns_name_t
*rdata_name
, dns_rdataset_t
**rdataset
,
5321 dns_rdataset_t
**sigrdataset
)
5324 dns_rdataset_t
*signsecset
;
5325 dns_rdata_t nsec
= DNS_RDATA_INIT
;
5329 ret
= dns_rdataset_first(nsecset
);
5330 check_result(ret
,"dns_rdataset_first");
5332 dns_rdataset_current(nsecset
, &nsec
);
5334 ret
= dns_nsec_typepresent(&nsec
, type
);
5335 if (ret
== ISC_R_SUCCESS
)
5336 printf("OK the NSEC said that the type doesn't exist \n");
5338 signsecset
= chase_scanname_section(msg
, name
,
5339 dns_rdatatype_rrsig
,
5341 DNS_SECTION_AUTHORITY
);
5342 if (signsecset
== NULL
) {
5343 printf("There isn't RRSIG NSEC for the zone \n");
5344 return (ISC_R_FAILURE
);
5346 dup_name(name
, rdata_name
, mctx
);
5347 *rdataset
= nsecset
;
5348 *sigrdataset
= signsecset
;
5360 prove_nx(dns_message_t
*msg
, dns_name_t
*name
, dns_rdataclass_t
class,
5361 dns_rdatatype_t type
, dns_name_t
*rdata_name
,
5362 dns_rdataset_t
**rdataset
, dns_rdataset_t
**sigrdataset
)
5365 dns_rdataset_t
*nsecset
= NULL
;
5367 printf("We want to prove the non-existance of a type of rdata %d"
5368 " or of the zone: \n", type
);
5370 if ((ret
= dns_message_firstname(msg
, DNS_SECTION_AUTHORITY
))
5372 printf(";; nothing in authority section : impossible to"
5373 " validate the non-existence : FAILED\n");
5374 return (ISC_R_FAILURE
);
5377 nsecset
= chase_scanname_section(msg
, name
, dns_rdatatype_nsec
,
5379 DNS_SECTION_AUTHORITY
);
5380 if (nsecset
!= NULL
) {
5381 printf("We have a NSEC for this zone :OK\n");
5382 ret
= prove_nx_type(msg
, name
, nsecset
, class,
5383 type
, rdata_name
, rdataset
,
5385 if (ret
!= ISC_R_SUCCESS
) {
5386 printf("prove_nx: ERROR type exist\n");
5389 printf("prove_nx: OK type does not exist\n");
5390 return (ISC_R_SUCCESS
);
5393 printf("there is no NSEC for this zone: validating "
5394 "that the zone doesn't exist\n");
5395 ret
= prove_nx_domain(msg
, name
, rdata_name
,
5396 rdataset
, sigrdataset
);
5399 /* Never get here */