1 /* $NetBSD: dighost.c,v 1.1.1.3 2009/12/26 22:18:54 christos Exp $ */
4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: dighost.c,v 1.328 2009/11/10 17:27:40 each Exp */
24 * Notice to programmers: Do not use this code as an example of how to
25 * use the ISC library to perform DNS lookups. Dig and Host both operate
26 * on the request level, since they allow fine-tuning of output and are
27 * intended as debugging tools. As a result, they perform many of the
28 * functions which could be better handled using the dns_resolver
29 * functions in most applications.
43 #include <idn/result.h>
45 #include <idn/resconf.h>
49 #include <dns/byaddr.h>
51 #include <dns/dnssec.h>
54 #include <isc/random.h>
57 #include <dns/fixedname.h>
59 #include <dns/message.h>
61 #include <dns/rdata.h>
62 #include <dns/rdataclass.h>
63 #include <dns/rdatalist.h>
64 #include <dns/rdataset.h>
65 #include <dns/rdatastruct.h>
66 #include <dns/rdatatype.h>
67 #include <dns/result.h>
73 #include <isc/base64.h>
74 #include <isc/entropy.h>
78 #include <isc/netaddr.h>
80 #include <isc/netdb.h>
82 #include <isc/parseint.h>
83 #include <isc/print.h>
84 #include <isc/random.h>
85 #include <isc/result.h>
86 #include <isc/string.h>
88 #include <isc/timer.h>
89 #include <isc/types.h>
92 #include <isccfg/namedconf.h>
94 #include <lwres/lwres.h>
95 #include <lwres/net.h>
97 #include <bind9/getaddresses.h>
101 #if ! defined(NS_INADDRSZ)
102 #define NS_INADDRSZ 4
105 #if ! defined(NS_IN6ADDRSZ)
106 #define NS_IN6ADDRSZ 16
109 static lwres_context_t
*lwctx
= NULL
;
110 static lwres_conf_t
*lwconf
;
112 dig_lookuplist_t lookup_list
;
113 dig_serverlist_t server_list
;
114 dig_searchlistlist_t search_list
;
117 check_ra
= ISC_FALSE
,
118 have_ipv4
= ISC_FALSE
,
119 have_ipv6
= ISC_FALSE
,
120 specified_source
= ISC_FALSE
,
121 free_now
= ISC_FALSE
,
122 cancel_now
= ISC_FALSE
,
123 usesearch
= ISC_FALSE
,
124 showsearch
= ISC_FALSE
,
126 is_dst_up
= ISC_FALSE
;
128 unsigned int timeout
= 0;
129 unsigned int extrabytes
;
130 isc_mem_t
*mctx
= NULL
;
131 isc_log_t
*lctx
= NULL
;
132 isc_taskmgr_t
*taskmgr
= NULL
;
133 isc_task_t
*global_task
= NULL
;
134 isc_timermgr_t
*timermgr
= NULL
;
135 isc_socketmgr_t
*socketmgr
= NULL
;
136 isc_sockaddr_t bind_address
;
137 isc_sockaddr_t bind_any
;
143 int lookup_counter
= 0;
146 static void initialize_idn(void);
147 static isc_result_t
output_filter(isc_buffer_t
*buffer
,
148 unsigned int used_org
,
149 isc_boolean_t absolute
);
150 static idn_result_t
append_textname(char *name
, const char *origin
,
152 static void idn_check_result(idn_result_t r
, const char *msg
);
161 *\li 0 Everything went well, including things like NXDOMAIN
163 *\li 7 Got too many RR's or Names
164 *\li 8 Couldn't open batch file
165 *\li 9 No reply from server
166 *\li 10 Internal error
170 char keynametext
[MXNAME
];
171 char keyfile
[MXNAME
] = "";
172 char keysecret
[MXNAME
] = "";
173 dns_name_t
*hmacname
= NULL
;
174 unsigned int digestbits
= 0;
175 isc_buffer_t
*namebuf
= NULL
;
176 dns_tsigkey_t
*key
= NULL
;
177 isc_boolean_t validated
= ISC_TRUE
;
178 isc_entropy_t
*entp
= NULL
;
179 isc_mempool_t
*commctx
= NULL
;
180 isc_boolean_t debugging
= ISC_FALSE
;
181 isc_boolean_t memdebugging
= ISC_FALSE
;
182 const char *progname
= NULL
;
183 isc_mutex_t lookup_lock
;
184 dig_lookup_t
*current_lookup
= NULL
;
188 isc_result_t
get_trusted_key(isc_mem_t
*mctx
);
189 dns_rdataset_t
* sigchase_scanname(dns_rdatatype_t type
,
190 dns_rdatatype_t covers
,
191 isc_boolean_t
*lookedup
,
192 dns_name_t
*rdata_name
);
193 dns_rdataset_t
* chase_scanname_section(dns_message_t
*msg
,
195 dns_rdatatype_t type
,
196 dns_rdatatype_t covers
,
198 isc_result_t
advanced_rrsearch(dns_rdataset_t
**rdataset
,
200 dns_rdatatype_t type
,
201 dns_rdatatype_t covers
,
202 isc_boolean_t
*lookedup
);
203 isc_result_t
sigchase_verify_sig_key(dns_name_t
*name
,
204 dns_rdataset_t
*rdataset
,
205 dst_key_t
* dnsseckey
,
206 dns_rdataset_t
*sigrdataset
,
208 isc_result_t
sigchase_verify_sig(dns_name_t
*name
,
209 dns_rdataset_t
*rdataset
,
210 dns_rdataset_t
*keyrdataset
,
211 dns_rdataset_t
*sigrdataset
,
213 isc_result_t
sigchase_verify_ds(dns_name_t
*name
,
214 dns_rdataset_t
*keyrdataset
,
215 dns_rdataset_t
*dsrdataset
,
217 void sigchase(dns_message_t
*msg
);
218 void print_rdata(dns_rdata_t
*rdata
, isc_mem_t
*mctx
);
219 void print_rdataset(dns_name_t
*name
,
220 dns_rdataset_t
*rdataset
, isc_mem_t
*mctx
);
221 void dup_name(dns_name_t
*source
, dns_name_t
* target
,
223 void free_name(dns_name_t
*name
, isc_mem_t
*mctx
);
224 void dump_database(void);
225 void dump_database_section(dns_message_t
*msg
, int section
);
226 dns_rdataset_t
* search_type(dns_name_t
*name
, dns_rdatatype_t type
,
227 dns_rdatatype_t covers
);
228 isc_result_t
contains_trusted_key(dns_name_t
*name
,
229 dns_rdataset_t
*rdataset
,
230 dns_rdataset_t
*sigrdataset
,
232 void print_type(dns_rdatatype_t type
);
233 isc_result_t
prove_nx_domain(dns_message_t
* msg
,
235 dns_name_t
* rdata_name
,
236 dns_rdataset_t
** rdataset
,
237 dns_rdataset_t
** sigrdataset
);
238 isc_result_t
prove_nx_type(dns_message_t
* msg
, dns_name_t
*name
,
239 dns_rdataset_t
*nsec
,
240 dns_rdataclass_t
class,
241 dns_rdatatype_t type
,
242 dns_name_t
* rdata_name
,
243 dns_rdataset_t
** rdataset
,
244 dns_rdataset_t
** sigrdataset
);
245 isc_result_t
prove_nx(dns_message_t
* msg
, dns_name_t
* name
,
246 dns_rdataclass_t
class,
247 dns_rdatatype_t type
,
248 dns_name_t
* rdata_name
,
249 dns_rdataset_t
** rdataset
,
250 dns_rdataset_t
** sigrdataset
);
251 static void nameFromString(const char *str
, dns_name_t
*p_ret
);
252 int inf_name(dns_name_t
* name1
, dns_name_t
* name2
);
253 isc_result_t
opentmpkey(isc_mem_t
*mctx
, const char *file
,
254 char **tempp
, FILE **fp
);
255 isc_result_t
removetmpkey(isc_mem_t
*mctx
, const char *file
);
256 void clean_trustedkey(void);
257 void insert_trustedkey(dst_key_t
* key
);
259 isc_result_t
getneededrr(dns_message_t
*msg
);
260 void sigchase_bottom_up(dns_message_t
*msg
);
261 void sigchase_bu(dns_message_t
*msg
);
264 isc_result_t
initialization(dns_name_t
*name
);
265 isc_result_t
prepare_lookup(dns_name_t
*name
);
266 isc_result_t
grandfather_pb_test(dns_name_t
* zone_name
,
267 dns_rdataset_t
*sigrdataset
);
268 isc_result_t
child_of_zone(dns_name_t
*name
,
269 dns_name_t
*zone_name
,
270 dns_name_t
*child_name
);
271 void sigchase_td(dns_message_t
*msg
);
273 char trustedkey
[MXNAME
] = "";
275 dns_rdataset_t
*chase_rdataset
= NULL
;
276 dns_rdataset_t
*chase_sigrdataset
= NULL
;
277 dns_rdataset_t
*chase_dsrdataset
= NULL
;
278 dns_rdataset_t
*chase_sigdsrdataset
= NULL
;
279 dns_rdataset_t
*chase_keyrdataset
= NULL
;
280 dns_rdataset_t
*chase_sigkeyrdataset
= NULL
;
281 dns_rdataset_t
*chase_nsrdataset
= NULL
;
283 dns_name_t chase_name
; /* the query name */
286 * the current name is the parent name when we follow delegation
288 dns_name_t chase_current_name
;
290 * the child name is used for delegation (NS DS responses in AUTHORITY section)
292 dns_name_t chase_authority_name
;
295 dns_name_t chase_signame
;
299 isc_boolean_t chase_siglookedup
= ISC_FALSE
;
300 isc_boolean_t chase_keylookedup
= ISC_FALSE
;
301 isc_boolean_t chase_sigkeylookedup
= ISC_FALSE
;
302 isc_boolean_t chase_dslookedup
= ISC_FALSE
;
303 isc_boolean_t chase_sigdslookedup
= ISC_FALSE
;
305 isc_boolean_t chase_nslookedup
= ISC_FALSE
;
306 isc_boolean_t chase_lookedup
= ISC_FALSE
;
309 isc_boolean_t delegation_follow
= ISC_FALSE
;
310 isc_boolean_t grandfather_pb
= ISC_FALSE
;
311 isc_boolean_t have_response
= ISC_FALSE
;
312 isc_boolean_t have_delegation_ns
= ISC_FALSE
;
313 dns_message_t
* error_message
= NULL
;
316 isc_boolean_t dsvalidating
= ISC_FALSE
;
317 isc_boolean_t chase_name_dup
= ISC_FALSE
;
319 ISC_LIST(dig_message_t
) chase_message_list
;
320 ISC_LIST(dig_message_t
) chase_message_list2
;
323 #define MAX_TRUSTED_KEY 5
324 typedef struct struct_trusted_key_list
{
325 dst_key_t
* key
[MAX_TRUSTED_KEY
];
329 struct_tk_list tk_list
= { {NULL
, NULL
, NULL
, NULL
, NULL
}, 0};
333 #define DIG_MAX_ADDRESSES 20
336 * Apply and clear locks at the event level in global task.
337 * Can I get rid of these using shutdown events? XXX
339 #define LOCK_LOOKUP {\
340 debug("lock_lookup %s:%d", __FILE__, __LINE__);\
341 check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\
344 #define UNLOCK_LOOKUP {\
345 debug("unlock_lookup %s:%d", __FILE__, __LINE__);\
346 check_result(isc_mutex_unlock((&lookup_lock)),\
347 "isc_mutex_unlock");\
351 cancel_lookup(dig_lookup_t
*lookup
);
354 recv_done(isc_task_t
*task
, isc_event_t
*event
);
357 send_udp(dig_query_t
*query
);
360 connect_timeout(isc_task_t
*task
, isc_event_t
*event
);
363 launch_next_query(dig_query_t
*query
, isc_boolean_t include_question
);
367 mem_alloc(void *arg
, size_t size
) {
368 return (isc_mem_get(arg
, size
));
372 mem_free(void *arg
, void *mem
, size_t size
) {
373 isc_mem_put(arg
, mem
, size
);
377 next_token(char **stringp
, const char *delim
) {
381 res
= strsep(stringp
, delim
);
384 } while (*res
== '\0');
389 count_dots(char *string
) {
403 hex_dump(isc_buffer_t
*b
) {
407 isc_buffer_usedregion(b
, &r
);
409 printf("%d bytes\n", r
.length
);
410 for (len
= 0; len
< r
.length
; len
++) {
411 printf("%02x ", r
.base
[len
]);
412 if (len
% 16 == 15) {
414 for (i
= len
- 15; i
<= len
; i
++) {
415 if (r
.base
[i
] >= '!' && r
.base
[i
] <= '}')
424 for (i
= len
; (i
% 16) != 0; i
++)
427 for (i
= ((len
>>4)<<4); i
< len
; i
++) {
428 if (r
.base
[i
] >= '!' && r
.base
[i
] <= '}')
438 * Append 'len' bytes of 'text' at '*p', failing with
439 * ISC_R_NOSPACE if that would advance p past 'end'.
442 append(const char *text
, int len
, char **p
, char *end
) {
444 return (ISC_R_NOSPACE
);
445 memcpy(*p
, text
, len
);
447 return (ISC_R_SUCCESS
);
451 reverse_octets(const char *in
, char **p
, char *end
) {
452 char *dot
= strchr(in
, '.');
456 result
= reverse_octets(dot
+ 1, p
, end
);
457 if (result
!= ISC_R_SUCCESS
)
459 result
= append(".", 1, p
, end
);
460 if (result
!= ISC_R_SUCCESS
)
466 return (append(in
, len
, p
, end
));
470 get_reverse(char *reverse
, size_t len
, char *value
, isc_boolean_t ip6_int
,
471 isc_boolean_t strict
)
477 addr
.family
= AF_INET6
;
478 r
= inet_pton(AF_INET6
, value
, &addr
.type
.in6
);
480 /* This is a valid IPv6 address. */
481 dns_fixedname_t fname
;
483 unsigned int options
= 0;
486 options
|= DNS_BYADDROPT_IPV6INT
;
487 dns_fixedname_init(&fname
);
488 name
= dns_fixedname_name(&fname
);
489 result
= dns_byaddr_createptrname2(&addr
, options
, name
);
490 if (result
!= ISC_R_SUCCESS
)
492 dns_name_format(name
, reverse
, len
);
493 return (ISC_R_SUCCESS
);
496 * Not a valid IPv6 address. Assume IPv4.
497 * If 'strict' is not set, construct the
498 * in-addr.arpa name by blindly reversing
499 * octets whether or not they look like integers,
500 * so that this can be used for RFC2317 names
504 char *end
= reverse
+ len
;
505 if (strict
&& inet_pton(AF_INET
, value
, &addr
.type
.in
) != 1)
506 return (DNS_R_BADDOTTEDQUAD
);
507 result
= reverse_octets(value
, &p
, end
);
508 if (result
!= ISC_R_SUCCESS
)
510 /* Append .in-addr.arpa. and a terminating NUL. */
511 result
= append(".in-addr.arpa.", 15, &p
, end
);
512 if (result
!= ISC_R_SUCCESS
)
514 return (ISC_R_SUCCESS
);
519 fatal(const char *format
, ...) {
523 fprintf(stderr
, "%s: ", progname
);
524 va_start(args
, format
);
525 vfprintf(stderr
, format
, args
);
527 fprintf(stderr
, "\n");
531 exitcode
= fatalexit
;
536 debug(const char *format
, ...) {
541 va_start(args
, format
);
542 vfprintf(stderr
, format
, args
);
544 fprintf(stderr
, "\n");
549 check_result(isc_result_t result
, const char *msg
) {
550 if (result
!= ISC_R_SUCCESS
) {
551 fatal("%s: %s", msg
, isc_result_totext(result
));
556 * Create a server structure, which is part of the lookup structure.
557 * This is little more than a linked list of servers to query in hopes
558 * of finding the answer the user is looking for
561 make_server(const char *servname
, const char *userarg
) {
564 REQUIRE(servname
!= NULL
);
566 debug("make_server(%s)", servname
);
567 srv
= isc_mem_allocate(mctx
, sizeof(struct dig_server
));
569 fatal("memory allocation failure in %s:%d",
571 strncpy(srv
->servername
, servname
, MXNAME
);
572 strncpy(srv
->userarg
, userarg
, MXNAME
);
573 srv
->servername
[MXNAME
-1] = 0;
574 srv
->userarg
[MXNAME
-1] = 0;
575 ISC_LINK_INIT(srv
, link
);
580 addr2af(int lwresaddrtype
)
584 switch (lwresaddrtype
) {
585 case LWRES_ADDRTYPE_V4
:
589 case LWRES_ADDRTYPE_V6
:
598 * Create a copy of the server list from the lwres configuration structure.
599 * The dest list must have already had ISC_LIST_INIT applied.
602 copy_server_list(lwres_conf_t
*confdata
, dig_serverlist_t
*dest
) {
603 dig_server_t
*newsrv
;
604 char tmp
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
608 debug("copy_server_list()");
609 for (i
= 0; i
< confdata
->nsnext
; i
++) {
610 af
= addr2af(confdata
->nameservers
[i
].family
);
612 if (af
== AF_INET
&& !have_ipv4
)
614 if (af
== AF_INET6
&& !have_ipv6
)
617 lwres_net_ntop(af
, confdata
->nameservers
[i
].address
,
619 newsrv
= make_server(tmp
, tmp
);
620 ISC_LINK_INIT(newsrv
, link
);
621 ISC_LIST_ENQUEUE(*dest
, newsrv
, link
);
626 flush_server_list(void) {
627 dig_server_t
*s
, *ps
;
629 debug("flush_server_list()");
630 s
= ISC_LIST_HEAD(server_list
);
633 s
= ISC_LIST_NEXT(s
, link
);
634 ISC_LIST_DEQUEUE(server_list
, ps
, link
);
635 isc_mem_free(mctx
, ps
);
640 set_nameserver(char *opt
) {
642 isc_sockaddr_t sockaddrs
[DIG_MAX_ADDRESSES
];
643 isc_netaddr_t netaddr
;
646 char tmp
[ISC_NETADDR_FORMATSIZE
];
651 result
= bind9_getaddresses(opt
, 0, sockaddrs
,
652 DIG_MAX_ADDRESSES
, &count
);
653 if (result
!= ISC_R_SUCCESS
)
654 fatal("couldn't get address for '%s': %s",
655 opt
, isc_result_totext(result
));
659 for (i
= 0; i
< count
; i
++) {
660 isc_netaddr_fromsockaddr(&netaddr
, &sockaddrs
[i
]);
661 isc_netaddr_format(&netaddr
, tmp
, sizeof(tmp
));
662 srv
= make_server(tmp
, opt
);
664 fatal("memory allocation failure");
665 ISC_LIST_APPEND(server_list
, srv
, link
);
670 add_nameserver(lwres_conf_t
*confdata
, const char *addr
, int af
) {
672 int i
= confdata
->nsnext
;
674 if (confdata
->nsnext
>= LWRES_CONFMAXNAMESERVERS
)
675 return (ISC_R_FAILURE
);
679 confdata
->nameservers
[i
].family
= LWRES_ADDRTYPE_V4
;
680 confdata
->nameservers
[i
].length
= NS_INADDRSZ
;
683 confdata
->nameservers
[i
].family
= LWRES_ADDRTYPE_V6
;
684 confdata
->nameservers
[i
].length
= NS_IN6ADDRSZ
;
687 return (ISC_R_FAILURE
);
690 if (lwres_net_pton(af
, addr
, &confdata
->nameservers
[i
].address
) == 1) {
692 return (ISC_R_SUCCESS
);
694 return (ISC_R_FAILURE
);
698 * Produce a cloned server list. The dest list must have already had
699 * ISC_LIST_INIT applied.
702 clone_server_list(dig_serverlist_t src
, dig_serverlist_t
*dest
) {
703 dig_server_t
*srv
, *newsrv
;
705 debug("clone_server_list()");
706 srv
= ISC_LIST_HEAD(src
);
707 while (srv
!= NULL
) {
708 newsrv
= make_server(srv
->servername
, srv
->userarg
);
709 ISC_LINK_INIT(newsrv
, link
);
710 ISC_LIST_ENQUEUE(*dest
, newsrv
, link
);
711 srv
= ISC_LIST_NEXT(srv
, link
);
716 * Create an empty lookup structure, which holds all the information needed
717 * to get an answer to a user's question. This structure contains two
718 * linked lists: the server list (servers to query) and the query list
719 * (outstanding queries which have been made to the listed servers).
722 make_empty_lookup(void) {
723 dig_lookup_t
*looknew
;
725 debug("make_empty_lookup()");
729 looknew
= isc_mem_allocate(mctx
, sizeof(struct dig_lookup
));
731 fatal("memory allocation failure in %s:%d",
733 looknew
->pending
= ISC_TRUE
;
734 looknew
->textname
[0] = 0;
735 looknew
->cmdline
[0] = 0;
736 looknew
->rdtype
= dns_rdatatype_a
;
737 looknew
->qrdtype
= dns_rdatatype_a
;
738 looknew
->rdclass
= dns_rdataclass_in
;
739 looknew
->rdtypeset
= ISC_FALSE
;
740 looknew
->rdclassset
= ISC_FALSE
;
741 looknew
->sendspace
= NULL
;
742 looknew
->sendmsg
= NULL
;
743 looknew
->name
= NULL
;
744 looknew
->oname
= NULL
;
745 looknew
->timer
= NULL
;
746 looknew
->xfr_q
= NULL
;
747 looknew
->current_query
= NULL
;
748 looknew
->doing_xfr
= ISC_FALSE
;
749 looknew
->ixfr_serial
= ISC_FALSE
;
750 looknew
->trace
= ISC_FALSE
;
751 looknew
->trace_root
= ISC_FALSE
;
752 looknew
->identify
= ISC_FALSE
;
753 looknew
->identify_previous_line
= ISC_FALSE
;
754 looknew
->ignore
= ISC_FALSE
;
755 looknew
->servfail_stops
= ISC_TRUE
;
756 looknew
->besteffort
= ISC_TRUE
;
757 looknew
->dnssec
= ISC_FALSE
;
758 looknew
->nsid
= ISC_FALSE
;
760 looknew
->sigchase
= ISC_FALSE
;
762 looknew
->do_topdown
= ISC_FALSE
;
763 looknew
->trace_root_sigchase
= ISC_FALSE
;
764 looknew
->rdtype_sigchaseset
= ISC_FALSE
;
765 looknew
->rdtype_sigchase
= dns_rdatatype_any
;
766 looknew
->qrdtype_sigchase
= dns_rdatatype_any
;
767 looknew
->rdclass_sigchase
= dns_rdataclass_in
;
768 looknew
->rdclass_sigchaseset
= ISC_FALSE
;
771 looknew
->udpsize
= 0;
773 looknew
->recurse
= ISC_TRUE
;
774 looknew
->aaonly
= ISC_FALSE
;
775 looknew
->adflag
= ISC_FALSE
;
776 looknew
->cdflag
= ISC_FALSE
;
777 looknew
->ns_search_only
= ISC_FALSE
;
778 looknew
->origin
= NULL
;
779 looknew
->tsigctx
= NULL
;
780 looknew
->querysig
= NULL
;
781 looknew
->retries
= tries
;
782 looknew
->nsfound
= 0;
783 looknew
->tcp_mode
= ISC_FALSE
;
784 looknew
->ip6_int
= ISC_FALSE
;
785 looknew
->comments
= ISC_TRUE
;
786 looknew
->stats
= ISC_TRUE
;
787 looknew
->section_question
= ISC_TRUE
;
788 looknew
->section_answer
= ISC_TRUE
;
789 looknew
->section_authority
= ISC_TRUE
;
790 looknew
->section_additional
= ISC_TRUE
;
791 looknew
->new_search
= ISC_FALSE
;
792 looknew
->done_as_is
= ISC_FALSE
;
793 looknew
->need_search
= ISC_FALSE
;
794 ISC_LINK_INIT(looknew
, link
);
795 ISC_LIST_INIT(looknew
->q
);
796 ISC_LIST_INIT(looknew
->my_server_list
);
801 * Clone a lookup, perhaps copying the server list. This does not clone
802 * the query list, since it will be regenerated by the setup_lookup()
803 * function, nor does it queue up the new lookup for processing.
804 * Caution: If you don't clone the servers, you MUST clone the server
805 * list separately from somewhere else, or construct it by hand.
808 clone_lookup(dig_lookup_t
*lookold
, isc_boolean_t servers
) {
809 dig_lookup_t
*looknew
;
811 debug("clone_lookup()");
815 looknew
= make_empty_lookup();
816 INSIST(looknew
!= NULL
);
817 strncpy(looknew
->textname
, lookold
->textname
, MXNAME
);
819 strncpy(looknew
->textnamesigchase
, lookold
->textnamesigchase
, MXNAME
);
821 strncpy(looknew
->cmdline
, lookold
->cmdline
, MXNAME
);
822 looknew
->textname
[MXNAME
-1] = 0;
823 looknew
->rdtype
= lookold
->rdtype
;
824 looknew
->qrdtype
= lookold
->qrdtype
;
825 looknew
->rdclass
= lookold
->rdclass
;
826 looknew
->rdtypeset
= lookold
->rdtypeset
;
827 looknew
->rdclassset
= lookold
->rdclassset
;
828 looknew
->doing_xfr
= lookold
->doing_xfr
;
829 looknew
->ixfr_serial
= lookold
->ixfr_serial
;
830 looknew
->trace
= lookold
->trace
;
831 looknew
->trace_root
= lookold
->trace_root
;
832 looknew
->identify
= lookold
->identify
;
833 looknew
->identify_previous_line
= lookold
->identify_previous_line
;
834 looknew
->ignore
= lookold
->ignore
;
835 looknew
->servfail_stops
= lookold
->servfail_stops
;
836 looknew
->besteffort
= lookold
->besteffort
;
837 looknew
->dnssec
= lookold
->dnssec
;
838 looknew
->nsid
= lookold
->nsid
;
840 looknew
->sigchase
= lookold
->sigchase
;
842 looknew
->do_topdown
= lookold
->do_topdown
;
843 looknew
->trace_root_sigchase
= lookold
->trace_root_sigchase
;
844 looknew
->rdtype_sigchaseset
= lookold
->rdtype_sigchaseset
;
845 looknew
->rdtype_sigchase
= lookold
->rdtype_sigchase
;
846 looknew
->qrdtype_sigchase
= lookold
->qrdtype_sigchase
;
847 looknew
->rdclass_sigchase
= lookold
->rdclass_sigchase
;
848 looknew
->rdclass_sigchaseset
= lookold
->rdclass_sigchaseset
;
851 looknew
->udpsize
= lookold
->udpsize
;
852 looknew
->edns
= lookold
->edns
;
853 looknew
->recurse
= lookold
->recurse
;
854 looknew
->aaonly
= lookold
->aaonly
;
855 looknew
->adflag
= lookold
->adflag
;
856 looknew
->cdflag
= lookold
->cdflag
;
857 looknew
->ns_search_only
= lookold
->ns_search_only
;
858 looknew
->tcp_mode
= lookold
->tcp_mode
;
859 looknew
->comments
= lookold
->comments
;
860 looknew
->stats
= lookold
->stats
;
861 looknew
->section_question
= lookold
->section_question
;
862 looknew
->section_answer
= lookold
->section_answer
;
863 looknew
->section_authority
= lookold
->section_authority
;
864 looknew
->section_additional
= lookold
->section_additional
;
865 looknew
->retries
= lookold
->retries
;
866 looknew
->tsigctx
= NULL
;
867 looknew
->need_search
= lookold
->need_search
;
868 looknew
->done_as_is
= lookold
->done_as_is
;
871 clone_server_list(lookold
->my_server_list
,
872 &looknew
->my_server_list
);
877 * Requeue a lookup for further processing, perhaps copying the server
878 * list. The new lookup structure is returned to the caller, and is
879 * queued for processing. If servers are not cloned in the requeue, they
880 * must be added before allowing the current event to complete, since the
881 * completion of the event may result in the next entry on the lookup
885 requeue_lookup(dig_lookup_t
*lookold
, isc_boolean_t servers
) {
886 dig_lookup_t
*looknew
;
888 debug("requeue_lookup()");
891 if (lookup_counter
> LOOKUP_LIMIT
)
892 fatal("too many lookups");
894 looknew
= clone_lookup(lookold
, servers
);
895 INSIST(looknew
!= NULL
);
897 debug("before insertion, init@%p -> %p, new@%p -> %p",
898 lookold
, lookold
->link
.next
, looknew
, looknew
->link
.next
);
899 ISC_LIST_PREPEND(lookup_list
, looknew
, link
);
900 debug("after insertion, init -> %p, new = %p, new -> %p",
901 lookold
, looknew
, looknew
->link
.next
);
907 setup_text_key(void) {
910 isc_buffer_t secretbuf
;
912 unsigned char *secretstore
;
914 debug("setup_text_key()");
915 result
= isc_buffer_allocate(mctx
, &namebuf
, MXNAME
);
916 check_result(result
, "isc_buffer_allocate");
917 dns_name_init(&keyname
, NULL
);
918 check_result(result
, "dns_name_init");
919 isc_buffer_putstr(namebuf
, keynametext
);
920 secretsize
= strlen(keysecret
) * 3 / 4;
921 secretstore
= isc_mem_allocate(mctx
, secretsize
);
922 if (secretstore
== NULL
)
923 fatal("memory allocation failure in %s:%d",
925 isc_buffer_init(&secretbuf
, secretstore
, secretsize
);
926 result
= isc_base64_decodestring(keysecret
, &secretbuf
);
927 if (result
!= ISC_R_SUCCESS
)
930 secretsize
= isc_buffer_usedlength(&secretbuf
);
932 result
= dns_name_fromtext(&keyname
, namebuf
, dns_rootname
, 0, namebuf
);
933 if (result
!= ISC_R_SUCCESS
)
936 result
= dns_tsigkey_create(&keyname
, hmacname
, secretstore
,
937 secretsize
, ISC_FALSE
, NULL
, 0, 0, mctx
,
940 if (result
!= ISC_R_SUCCESS
)
941 printf(";; Couldn't create key %s: %s\n",
942 keynametext
, isc_result_totext(result
));
944 dst_key_setbits(key
->key
, digestbits
);
946 isc_mem_free(mctx
, secretstore
);
947 dns_name_invalidate(&keyname
);
948 isc_buffer_free(&namebuf
);
952 parse_uint(isc_uint32_t
*uip
, const char *value
, isc_uint32_t max
,
955 isc_result_t result
= isc_parse_uint32(&n
, value
, 10);
956 if (result
== ISC_R_SUCCESS
&& n
> max
)
957 result
= ISC_R_RANGE
;
958 if (result
!= ISC_R_SUCCESS
) {
959 printf("invalid %s '%s': %s\n", desc
,
960 value
, isc_result_totext(result
));
964 return (ISC_R_SUCCESS
);
968 parse_bits(char *arg
, const char *desc
, isc_uint32_t max
) {
972 result
= parse_uint(&tmp
, arg
, max
, desc
);
973 if (result
!= ISC_R_SUCCESS
)
974 fatal("couldn't parse digest bits");
975 tmp
= (tmp
+ 7) & ~0x7U
;
981 * Parse HMAC algorithm specification
984 parse_hmac(const char *hmac
) {
988 REQUIRE(hmac
!= NULL
);
991 if (len
>= (int) sizeof(buf
))
992 fatal("unknown key type '%.*s'", len
, hmac
);
993 strncpy(buf
, hmac
, sizeof(buf
));
997 if (strcasecmp(buf
, "hmac-md5") == 0) {
998 hmacname
= DNS_TSIG_HMACMD5_NAME
;
999 } else if (strncasecmp(buf
, "hmac-md5-", 9) == 0) {
1000 hmacname
= DNS_TSIG_HMACMD5_NAME
;
1001 digestbits
= parse_bits(&buf
[9], "digest-bits [0..128]", 128);
1002 } else if (strcasecmp(buf
, "hmac-sha1") == 0) {
1003 hmacname
= DNS_TSIG_HMACSHA1_NAME
;
1005 } else if (strncasecmp(buf
, "hmac-sha1-", 10) == 0) {
1006 hmacname
= DNS_TSIG_HMACSHA1_NAME
;
1007 digestbits
= parse_bits(&buf
[10], "digest-bits [0..160]", 160);
1008 } else if (strcasecmp(buf
, "hmac-sha224") == 0) {
1009 hmacname
= DNS_TSIG_HMACSHA224_NAME
;
1010 } else if (strncasecmp(buf
, "hmac-sha224-", 12) == 0) {
1011 hmacname
= DNS_TSIG_HMACSHA224_NAME
;
1012 digestbits
= parse_bits(&buf
[12], "digest-bits [0..224]", 224);
1013 } else if (strcasecmp(buf
, "hmac-sha256") == 0) {
1014 hmacname
= DNS_TSIG_HMACSHA256_NAME
;
1015 } else if (strncasecmp(buf
, "hmac-sha256-", 12) == 0) {
1016 hmacname
= DNS_TSIG_HMACSHA256_NAME
;
1017 digestbits
= parse_bits(&buf
[12], "digest-bits [0..256]", 256);
1018 } else if (strcasecmp(buf
, "hmac-sha384") == 0) {
1019 hmacname
= DNS_TSIG_HMACSHA384_NAME
;
1020 } else if (strncasecmp(buf
, "hmac-sha384-", 12) == 0) {
1021 hmacname
= DNS_TSIG_HMACSHA384_NAME
;
1022 digestbits
= parse_bits(&buf
[12], "digest-bits [0..384]", 384);
1023 } else if (strcasecmp(buf
, "hmac-sha512") == 0) {
1024 hmacname
= DNS_TSIG_HMACSHA512_NAME
;
1025 } else if (strncasecmp(buf
, "hmac-sha512-", 12) == 0) {
1026 hmacname
= DNS_TSIG_HMACSHA512_NAME
;
1027 digestbits
= parse_bits(&buf
[12], "digest-bits [0..512]", 512);
1029 fprintf(stderr
, ";; Warning, ignoring "
1030 "invalid TSIG algorithm %s\n", buf
);
1035 * Get a key from a named.conf format keyfile
1038 read_confkey(void) {
1039 isc_log_t
*lctx
= NULL
;
1040 cfg_parser_t
*pctx
= NULL
;
1041 cfg_obj_t
*file
= NULL
;
1042 const cfg_obj_t
*key
= NULL
;
1043 const cfg_obj_t
*secretobj
= NULL
;
1044 const cfg_obj_t
*algorithmobj
= NULL
;
1045 const char *keyname
;
1046 const char *secretstr
;
1047 const char *algorithm
;
1048 isc_result_t result
;
1050 if (! isc_file_exists(keyfile
))
1051 return (ISC_R_FILENOTFOUND
);
1053 result
= cfg_parser_create(mctx
, lctx
, &pctx
);
1054 if (result
!= ISC_R_SUCCESS
)
1057 result
= cfg_parse_file(pctx
, keyfile
, &cfg_type_sessionkey
,
1059 if (result
!= ISC_R_SUCCESS
)
1062 result
= cfg_map_get(file
, "key", &key
);
1063 if (result
!= ISC_R_SUCCESS
)
1066 (void) cfg_map_get(key
, "secret", &secretobj
);
1067 (void) cfg_map_get(key
, "algorithm", &algorithmobj
);
1068 if (secretobj
== NULL
|| algorithmobj
== NULL
)
1069 fatal("key must have algorithm and secret");
1071 keyname
= cfg_obj_asstring(cfg_map_getname(key
));
1072 secretstr
= cfg_obj_asstring(secretobj
);
1073 algorithm
= cfg_obj_asstring(algorithmobj
);
1075 strncpy(keynametext
, keyname
, sizeof(keynametext
));
1076 strncpy(keysecret
, secretstr
, sizeof(keysecret
));
1077 parse_hmac(algorithm
);
1083 cfg_obj_destroy(pctx
, &file
);
1084 cfg_parser_destroy(&pctx
);
1091 setup_file_key(void) {
1092 isc_result_t result
;
1093 dst_key_t
*dstkey
= NULL
;
1095 debug("setup_file_key()");
1097 /* Try reading the key from a K* pair */
1098 result
= dst_key_fromnamedfile(keyfile
, NULL
,
1099 DST_TYPE_PRIVATE
| DST_TYPE_KEY
, mctx
,
1102 /* If that didn't work, try reading it as a session.key keyfile */
1103 if (result
!= ISC_R_SUCCESS
) {
1104 result
= read_confkey();
1105 if (result
== ISC_R_SUCCESS
)
1109 if (result
!= ISC_R_SUCCESS
) {
1110 fprintf(stderr
, "Couldn't read key from %s: %s\n",
1111 keyfile
, isc_result_totext(result
));
1115 switch (dst_key_alg(dstkey
)) {
1116 case DST_ALG_HMACMD5
:
1117 hmacname
= DNS_TSIG_HMACMD5_NAME
;
1119 case DST_ALG_HMACSHA1
:
1120 hmacname
= DNS_TSIG_HMACSHA1_NAME
;
1122 case DST_ALG_HMACSHA224
:
1123 hmacname
= DNS_TSIG_HMACSHA224_NAME
;
1125 case DST_ALG_HMACSHA256
:
1126 hmacname
= DNS_TSIG_HMACSHA256_NAME
;
1128 case DST_ALG_HMACSHA384
:
1129 hmacname
= DNS_TSIG_HMACSHA384_NAME
;
1131 case DST_ALG_HMACSHA512
:
1132 hmacname
= DNS_TSIG_HMACSHA512_NAME
;
1135 printf(";; Couldn't create key %s: bad algorithm\n",
1139 result
= dns_tsigkey_createfromkey(dst_key_name(dstkey
), hmacname
,
1140 dstkey
, ISC_FALSE
, NULL
, 0, 0,
1142 if (result
!= ISC_R_SUCCESS
) {
1143 printf(";; Couldn't create key %s: %s\n",
1144 keynametext
, isc_result_totext(result
));
1150 dst_key_free(&dstkey
);
1153 static dig_searchlist_t
*
1154 make_searchlist_entry(char *domain
) {
1155 dig_searchlist_t
*search
;
1156 search
= isc_mem_allocate(mctx
, sizeof(*search
));
1158 fatal("memory allocation failure in %s:%d",
1159 __FILE__
, __LINE__
);
1160 strncpy(search
->origin
, domain
, MXNAME
);
1161 search
->origin
[MXNAME
-1] = 0;
1162 ISC_LINK_INIT(search
, link
);
1167 create_search_list(lwres_conf_t
*confdata
) {
1169 dig_searchlist_t
*search
;
1171 debug("create_search_list()");
1172 ISC_LIST_INIT(search_list
);
1174 for (i
= 0; i
< confdata
->searchnxt
; i
++) {
1175 search
= make_searchlist_entry(confdata
->search
[i
]);
1176 ISC_LIST_APPEND(search_list
, search
, link
);
1181 * Setup the system as a whole, reading key information and resolv.conf
1185 setup_system(void) {
1186 dig_searchlist_t
*domain
= NULL
;
1187 lwres_result_t lwresult
;
1188 unsigned int lwresflags
;
1190 debug("setup_system()");
1192 lwresflags
= LWRES_CONTEXT_SERVERMODE
;
1194 lwresflags
|= LWRES_CONTEXT_USEIPV4
;
1196 lwresflags
|= LWRES_CONTEXT_USEIPV6
;
1198 lwresult
= lwres_context_create(&lwctx
, mctx
, mem_alloc
, mem_free
,
1200 if (lwresult
!= LWRES_R_SUCCESS
)
1201 fatal("lwres_context_create failed");
1203 lwresult
= lwres_conf_parse(lwctx
, RESOLV_CONF
);
1204 if (lwresult
!= LWRES_R_SUCCESS
&& lwresult
!= LWRES_R_NOTFOUND
)
1205 fatal("parse of %s failed", RESOLV_CONF
);
1207 lwconf
= lwres_conf_get(lwctx
);
1209 /* Make the search list */
1210 if (lwconf
->searchnxt
> 0)
1211 create_search_list(lwconf
);
1212 else { /* No search list. Use the domain name if any */
1213 if (lwconf
->domainname
!= NULL
) {
1214 domain
= make_searchlist_entry(lwconf
->domainname
);
1215 ISC_LIST_INITANDAPPEND(search_list
, domain
, link
);
1221 ndots
= lwconf
->ndots
;
1222 debug("ndots is %d.", ndots
);
1225 /* If user doesn't specify server use nameservers from resolv.conf. */
1226 if (ISC_LIST_EMPTY(server_list
))
1227 copy_server_list(lwconf
, &server_list
);
1229 /* If we don't find a nameserver fall back to localhost */
1230 if (ISC_LIST_EMPTY(server_list
)) {
1232 lwresult
= add_nameserver(lwconf
, "127.0.0.1", AF_INET
);
1233 if (lwresult
!= ISC_R_SUCCESS
)
1234 fatal("add_nameserver failed");
1237 lwresult
= add_nameserver(lwconf
, "::1", AF_INET6
);
1238 if (lwresult
!= ISC_R_SUCCESS
)
1239 fatal("add_nameserver failed");
1242 copy_server_list(lwconf
, &server_list
);
1249 if (keyfile
[0] != 0)
1251 else if (keysecret
[0] != 0)
1254 /* Setup the list of messages for +sigchase */
1255 ISC_LIST_INIT(chase_message_list
);
1256 ISC_LIST_INIT(chase_message_list2
);
1257 dns_name_init(&chase_name
, NULL
);
1259 dns_name_init(&chase_current_name
, NULL
);
1260 dns_name_init(&chase_authority_name
, NULL
);
1263 dns_name_init(&chase_signame
, NULL
);
1271 clear_searchlist(void) {
1272 dig_searchlist_t
*search
;
1273 while ((search
= ISC_LIST_HEAD(search_list
)) != NULL
) {
1274 ISC_LIST_UNLINK(search_list
, search
, link
);
1275 isc_mem_free(mctx
, search
);
1280 * Override the search list derived from resolv.conf by 'domain'.
1283 set_search_domain(char *domain
) {
1284 dig_searchlist_t
*search
;
1287 search
= make_searchlist_entry(domain
);
1288 ISC_LIST_APPEND(search_list
, search
, link
);
1292 * Setup the ISC and DNS libraries for use by the system.
1296 isc_result_t result
;
1297 isc_logconfig_t
*logconfig
= NULL
;
1299 debug("setup_libs()");
1301 result
= isc_net_probeipv4();
1302 if (result
== ISC_R_SUCCESS
)
1303 have_ipv4
= ISC_TRUE
;
1305 result
= isc_net_probeipv6();
1306 if (result
== ISC_R_SUCCESS
)
1307 have_ipv6
= ISC_TRUE
;
1308 if (!have_ipv6
&& !have_ipv4
)
1309 fatal("can't find either v4 or v6 networking");
1311 result
= isc_mem_create(0, 0, &mctx
);
1312 check_result(result
, "isc_mem_create");
1314 result
= isc_log_create(mctx
, &lctx
, &logconfig
);
1315 check_result(result
, "isc_log_create");
1317 isc_log_setcontext(lctx
);
1319 dns_log_setcontext(lctx
);
1321 result
= isc_log_usechannel(logconfig
, "default_debug", NULL
, NULL
);
1322 check_result(result
, "isc_log_usechannel");
1324 isc_log_setdebuglevel(lctx
, 0);
1326 result
= isc_taskmgr_create(mctx
, 1, 0, &taskmgr
);
1327 check_result(result
, "isc_taskmgr_create");
1329 result
= isc_task_create(taskmgr
, 0, &global_task
);
1330 check_result(result
, "isc_task_create");
1332 result
= isc_timermgr_create(mctx
, &timermgr
);
1333 check_result(result
, "isc_timermgr_create");
1335 result
= isc_socketmgr_create(mctx
, &socketmgr
);
1336 check_result(result
, "isc_socketmgr_create");
1338 result
= isc_entropy_create(mctx
, &entp
);
1339 check_result(result
, "isc_entropy_create");
1341 result
= dst_lib_init(mctx
, entp
, 0);
1342 check_result(result
, "dst_lib_init");
1343 is_dst_up
= ISC_TRUE
;
1345 result
= isc_mempool_create(mctx
, COMMSIZE
, &commctx
);
1346 check_result(result
, "isc_mempool_create");
1347 isc_mempool_setname(commctx
, "COMMPOOL");
1349 * 6 and 2 set as reasonable parameters for 3 or 4 nameserver
1352 isc_mempool_setfreemax(commctx
, 6);
1353 isc_mempool_setfillcount(commctx
, 2);
1355 result
= isc_mutex_init(&lookup_lock
);
1356 check_result(result
, "isc_mutex_init");
1358 dns_result_register();
1362 * Add EDNS0 option record to a message. Currently, the only supported
1363 * options are UDP buffer size, the DO bit, and NSID request.
1366 add_opt(dns_message_t
*msg
, isc_uint16_t udpsize
, isc_uint16_t edns
,
1367 isc_boolean_t dnssec
, isc_boolean_t nsid
)
1369 dns_rdataset_t
*rdataset
= NULL
;
1370 dns_rdatalist_t
*rdatalist
= NULL
;
1371 dns_rdata_t
*rdata
= NULL
;
1372 isc_result_t result
;
1375 result
= dns_message_gettemprdataset(msg
, &rdataset
);
1376 check_result(result
, "dns_message_gettemprdataset");
1377 dns_rdataset_init(rdataset
);
1378 result
= dns_message_gettemprdatalist(msg
, &rdatalist
);
1379 check_result(result
, "dns_message_gettemprdatalist");
1380 result
= dns_message_gettemprdata(msg
, &rdata
);
1381 check_result(result
, "dns_message_gettemprdata");
1383 debug("setting udp size of %d", udpsize
);
1384 rdatalist
->type
= dns_rdatatype_opt
;
1385 rdatalist
->covers
= 0;
1386 rdatalist
->rdclass
= udpsize
;
1387 rdatalist
->ttl
= edns
<< 16;
1389 rdatalist
->ttl
|= DNS_MESSAGEEXTFLAG_DO
;
1391 unsigned char data
[4];
1394 isc_buffer_init(&buf
, data
, sizeof(data
));
1395 isc_buffer_putuint16(&buf
, DNS_OPT_NSID
);
1396 isc_buffer_putuint16(&buf
, 0);
1398 rdata
->length
= sizeof(data
);
1403 ISC_LIST_INIT(rdatalist
->rdata
);
1404 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1405 dns_rdatalist_tordataset(rdatalist
, rdataset
);
1406 result
= dns_message_setopt(msg
, rdataset
);
1407 check_result(result
, "dns_message_setopt");
1411 * Add a question section to a message, asking for the specified name,
1415 add_question(dns_message_t
*message
, dns_name_t
*name
,
1416 dns_rdataclass_t rdclass
, dns_rdatatype_t rdtype
)
1418 dns_rdataset_t
*rdataset
;
1419 isc_result_t result
;
1421 debug("add_question()");
1423 result
= dns_message_gettemprdataset(message
, &rdataset
);
1424 check_result(result
, "dns_message_gettemprdataset()");
1425 dns_rdataset_init(rdataset
);
1426 dns_rdataset_makequestion(rdataset
, rdclass
, rdtype
);
1427 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1431 * Check if we're done with all the queued lookups, which is true iff
1432 * all sockets, sends, and recvs are accounted for (counters == 0),
1433 * and the lookup list is empty.
1434 * If we are done, pass control back out to dighost_shutdown() (which is
1435 * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
1436 * a whole or reseed the lookup list.
1439 check_if_done(void) {
1440 debug("check_if_done()");
1441 debug("list %s", ISC_LIST_EMPTY(lookup_list
) ? "empty" : "full");
1442 if (ISC_LIST_EMPTY(lookup_list
) && current_lookup
== NULL
&&
1444 INSIST(sockcount
== 0);
1445 INSIST(recvcount
== 0);
1446 debug("shutting down");
1452 * Clear out a query when we're done with it. WARNING: This routine
1453 * WILL invalidate the query pointer.
1456 clear_query(dig_query_t
*query
) {
1457 dig_lookup_t
*lookup
;
1459 REQUIRE(query
!= NULL
);
1461 debug("clear_query(%p)", query
);
1463 lookup
= query
->lookup
;
1465 if (lookup
->current_query
== query
)
1466 lookup
->current_query
= NULL
;
1468 ISC_LIST_UNLINK(lookup
->q
, query
, link
);
1469 if (ISC_LINK_LINKED(&query
->recvbuf
, link
))
1470 ISC_LIST_DEQUEUE(query
->recvlist
, &query
->recvbuf
,
1472 if (ISC_LINK_LINKED(&query
->lengthbuf
, link
))
1473 ISC_LIST_DEQUEUE(query
->lengthlist
, &query
->lengthbuf
,
1475 INSIST(query
->recvspace
!= NULL
);
1476 if (query
->sock
!= NULL
) {
1477 isc_socket_detach(&query
->sock
);
1479 debug("sockcount=%d", sockcount
);
1481 isc_mempool_put(commctx
, query
->recvspace
);
1482 isc_buffer_invalidate(&query
->recvbuf
);
1483 isc_buffer_invalidate(&query
->lengthbuf
);
1484 if (query
->waiting_senddone
)
1485 query
->pending_free
= ISC_TRUE
;
1487 isc_mem_free(mctx
, query
);
1491 * Try and clear out a lookup if we're done with it. Return ISC_TRUE if
1492 * the lookup was successfully cleared. If ISC_TRUE is returned, the
1493 * lookup pointer has been invalidated.
1495 static isc_boolean_t
1496 try_clear_lookup(dig_lookup_t
*lookup
) {
1499 REQUIRE(lookup
!= NULL
);
1501 debug("try_clear_lookup(%p)", lookup
);
1503 if (ISC_LIST_HEAD(lookup
->q
) != NULL
) {
1505 q
= ISC_LIST_HEAD(lookup
->q
);
1507 debug("query to %s still pending", q
->servname
);
1508 q
= ISC_LIST_NEXT(q
, link
);
1515 * At this point, we know there are no queries on the lookup,
1516 * so can make it go away also.
1518 destroy_lookup(lookup
);
1523 destroy_lookup(dig_lookup_t
*lookup
) {
1528 s
= ISC_LIST_HEAD(lookup
->my_server_list
);
1530 debug("freeing server %p belonging to %p", s
, lookup
);
1532 s
= ISC_LIST_NEXT(s
, link
);
1533 ISC_LIST_DEQUEUE(lookup
->my_server_list
,
1534 (dig_server_t
*)ptr
, link
);
1535 isc_mem_free(mctx
, ptr
);
1537 if (lookup
->sendmsg
!= NULL
)
1538 dns_message_destroy(&lookup
->sendmsg
);
1539 if (lookup
->querysig
!= NULL
) {
1540 debug("freeing buffer %p", lookup
->querysig
);
1541 isc_buffer_free(&lookup
->querysig
);
1543 if (lookup
->timer
!= NULL
)
1544 isc_timer_detach(&lookup
->timer
);
1545 if (lookup
->sendspace
!= NULL
)
1546 isc_mempool_put(commctx
, lookup
->sendspace
);
1548 if (lookup
->tsigctx
!= NULL
)
1549 dst_context_destroy(&lookup
->tsigctx
);
1551 isc_mem_free(mctx
, lookup
);
1555 * If we can, start the next lookup in the queue running.
1556 * This assumes that the lookup on the head of the queue hasn't been
1557 * started yet. It also removes the lookup from the head of the queue,
1558 * setting the current_lookup pointer pointing to it.
1561 start_lookup(void) {
1562 debug("start_lookup()");
1567 * If there's a current lookup running, we really shouldn't get
1570 INSIST(current_lookup
== NULL
);
1572 current_lookup
= ISC_LIST_HEAD(lookup_list
);
1574 * Put the current lookup somewhere so cancel_all can find it
1576 if (current_lookup
!= NULL
) {
1577 ISC_LIST_DEQUEUE(lookup_list
, current_lookup
, link
);
1579 if (current_lookup
->do_topdown
&&
1580 !current_lookup
->rdtype_sigchaseset
) {
1581 dst_key_t
*trustedkey
= NULL
;
1582 isc_buffer_t
*b
= NULL
;
1584 isc_result_t result
;
1585 dns_name_t query_name
;
1586 dns_name_t
*key_name
;
1589 result
= get_trusted_key(mctx
);
1590 if (result
!= ISC_R_SUCCESS
) {
1591 printf("\n;; No trusted key, "
1592 "+sigchase option is disabled\n");
1593 current_lookup
->sigchase
= ISC_FALSE
;
1596 dns_name_init(&query_name
, NULL
);
1597 nameFromString(current_lookup
->textname
, &query_name
);
1599 for (i
= 0; i
< tk_list
.nb_tk
; i
++) {
1600 key_name
= dst_key_name(tk_list
.key
[i
]);
1602 if (dns_name_issubdomain(&query_name
,
1603 key_name
) == ISC_TRUE
)
1604 trustedkey
= tk_list
.key
[i
];
1606 * Verify temp is really the lowest
1610 if (trustedkey
== NULL
) {
1611 printf("\n;; The queried zone: ");
1612 dns_name_print(&query_name
, stdout
);
1613 printf(" isn't a subdomain of any Trusted Keys"
1614 ": +sigchase option is disable\n");
1615 current_lookup
->sigchase
= ISC_FALSE
;
1616 free_name(&query_name
, mctx
);
1619 free_name(&query_name
, mctx
);
1621 current_lookup
->rdtype_sigchase
1622 = current_lookup
->rdtype
;
1623 current_lookup
->rdtype_sigchaseset
1624 = current_lookup
->rdtypeset
;
1625 current_lookup
->rdtype
= dns_rdatatype_ns
;
1627 current_lookup
->qrdtype_sigchase
1628 = current_lookup
->qrdtype
;
1629 current_lookup
->qrdtype
= dns_rdatatype_ns
;
1631 current_lookup
->rdclass_sigchase
1632 = current_lookup
->rdclass
;
1633 current_lookup
->rdclass_sigchaseset
1634 = current_lookup
->rdclassset
;
1635 current_lookup
->rdclass
= dns_rdataclass_in
;
1637 strncpy(current_lookup
->textnamesigchase
,
1638 current_lookup
->textname
, MXNAME
);
1640 current_lookup
->trace_root_sigchase
= ISC_TRUE
;
1642 result
= isc_buffer_allocate(mctx
, &b
, BUFSIZE
);
1643 check_result(result
, "isc_buffer_allocate");
1644 result
= dns_name_totext(dst_key_name(trustedkey
),
1646 check_result(result
, "dns_name_totext");
1647 isc_buffer_usedregion(b
, &r
);
1648 r
.base
[r
.length
] = '\0';
1649 strncpy(current_lookup
->textname
, (char*)r
.base
,
1651 isc_buffer_free(&b
);
1653 nameFromString(current_lookup
->textnamesigchase
,
1656 dns_name_init(&chase_authority_name
, NULL
);
1660 setup_lookup(current_lookup
);
1661 do_lookup(current_lookup
);
1668 * If we can, clear the current lookup and start the next one running.
1669 * This calls try_clear_lookup, so may invalidate the lookup pointer.
1672 check_next_lookup(dig_lookup_t
*lookup
) {
1676 debug("check_next_lookup(%p)", lookup
);
1678 if (ISC_LIST_HEAD(lookup
->q
) != NULL
) {
1679 debug("still have a worker");
1682 if (try_clear_lookup(lookup
)) {
1683 current_lookup
= NULL
;
1689 * Create and queue a new lookup as a followup to the current lookup,
1690 * based on the supplied message and section. This is used in trace and
1691 * name server search modes to start a new lookup using servers from
1692 * NS records in a reply. Returns the number of followup lookups made.
1695 followup_lookup(dns_message_t
*msg
, dig_query_t
*query
, dns_section_t section
)
1697 dig_lookup_t
*lookup
= NULL
;
1698 dig_server_t
*srv
= NULL
;
1699 dns_rdataset_t
*rdataset
= NULL
;
1700 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1701 dns_name_t
*name
= NULL
;
1702 isc_result_t result
;
1703 isc_boolean_t success
= ISC_FALSE
;
1706 isc_boolean_t horizontal
= ISC_FALSE
, bad
= ISC_FALSE
;
1710 debug("following up %s", query
->lookup
->textname
);
1712 for (result
= dns_message_firstname(msg
, section
);
1713 result
== ISC_R_SUCCESS
;
1714 result
= dns_message_nextname(msg
, section
)) {
1716 dns_message_currentname(msg
, section
, &name
);
1718 if (section
== DNS_SECTION_AUTHORITY
) {
1720 result
= dns_message_findtype(name
, dns_rdatatype_soa
,
1722 if (result
== ISC_R_SUCCESS
)
1726 result
= dns_message_findtype(name
, dns_rdatatype_ns
, 0,
1728 if (result
!= ISC_R_SUCCESS
)
1731 debug("found NS set");
1733 if (query
->lookup
->trace
&& !query
->lookup
->trace_root
) {
1734 dns_namereln_t namereln
;
1735 unsigned int nlabels
;
1738 domain
= dns_fixedname_name(&query
->lookup
->fdomain
);
1739 namereln
= dns_name_fullcompare(name
, domain
,
1741 if (namereln
== dns_namereln_equal
) {
1743 printf(";; BAD (HORIZONTAL) REFERRAL\n");
1744 horizontal
= ISC_TRUE
;
1745 } else if (namereln
!= dns_namereln_subdomain
) {
1747 printf(";; BAD REFERRAL\n");
1753 for (result
= dns_rdataset_first(rdataset
);
1754 result
== ISC_R_SUCCESS
;
1755 result
= dns_rdataset_next(rdataset
)) {
1756 char namestr
[DNS_NAME_FORMATSIZE
];
1759 if (query
->lookup
->trace_root
&&
1760 query
->lookup
->nsfound
>= MXSERV
)
1763 dns_rdataset_current(rdataset
, &rdata
);
1765 query
->lookup
->nsfound
++;
1766 result
= dns_rdata_tostruct(&rdata
, &ns
, NULL
);
1767 check_result(result
, "dns_rdata_tostruct");
1768 dns_name_format(&ns
.name
, namestr
, sizeof(namestr
));
1769 dns_rdata_freestruct(&ns
);
1771 /* Initialize lookup if we've not yet */
1772 debug("found NS %d %s", numLookups
, namestr
);
1777 lookup
= requeue_lookup(query
->lookup
,
1779 cancel_lookup(query
->lookup
);
1780 lookup
->doing_xfr
= ISC_FALSE
;
1781 if (!lookup
->trace_root
&&
1782 section
== DNS_SECTION_ANSWER
)
1783 lookup
->trace
= ISC_FALSE
;
1785 lookup
->trace
= query
->lookup
->trace
;
1786 lookup
->ns_search_only
=
1787 query
->lookup
->ns_search_only
;
1788 lookup
->trace_root
= ISC_FALSE
;
1789 if (lookup
->ns_search_only
)
1790 lookup
->recurse
= ISC_FALSE
;
1791 dns_fixedname_init(&lookup
->fdomain
);
1792 domain
= dns_fixedname_name(&lookup
->fdomain
);
1793 dns_name_copy(name
, domain
, NULL
);
1795 srv
= make_server(namestr
, namestr
);
1796 debug("adding server %s", srv
->servername
);
1797 ISC_LIST_APPEND(lookup
->my_server_list
, srv
, link
);
1798 dns_rdata_reset(&rdata
);
1802 if (lookup
== NULL
&&
1803 section
== DNS_SECTION_ANSWER
&&
1804 (query
->lookup
->trace
|| query
->lookup
->ns_search_only
))
1805 return (followup_lookup(msg
, query
, DNS_SECTION_AUTHORITY
));
1808 * Randomize the order the nameserver will be tried.
1810 if (numLookups
> 1) {
1812 dig_serverlist_t my_server_list
;
1814 ISC_LIST_INIT(my_server_list
);
1816 for (i
= numLookups
; i
> 0; i
--) {
1819 srv
= ISC_LIST_HEAD(lookup
->my_server_list
);
1821 srv
= ISC_LIST_NEXT(srv
, link
);
1822 ISC_LIST_DEQUEUE(lookup
->my_server_list
, srv
, link
);
1823 ISC_LIST_APPEND(my_server_list
, srv
, link
);
1825 ISC_LIST_APPENDLIST(lookup
->my_server_list
,
1826 my_server_list
, link
);
1829 return (numLookups
);
1833 * Create and queue a new lookup using the next origin from the search
1834 * list, read in setup_system().
1836 * Return ISC_TRUE iff there was another searchlist entry.
1838 static isc_boolean_t
1839 next_origin(dns_message_t
*msg
, dig_query_t
*query
) {
1840 dig_lookup_t
*lookup
;
1841 dig_searchlist_t
*search
;
1847 debug("next_origin()");
1848 debug("following up %s", query
->lookup
->textname
);
1852 * We're not using a search list, so don't even think
1853 * about finding the next entry.
1856 if (query
->lookup
->origin
== NULL
&& !query
->lookup
->need_search
)
1858 * Then we just did rootorg; there's nothing left.
1861 if (query
->lookup
->origin
== NULL
&& query
->lookup
->need_search
) {
1862 lookup
= requeue_lookup(query
->lookup
, ISC_TRUE
);
1863 lookup
->origin
= ISC_LIST_HEAD(search_list
);
1864 lookup
->need_search
= ISC_FALSE
;
1866 search
= ISC_LIST_NEXT(query
->lookup
->origin
, link
);
1867 if (search
== NULL
&& query
->lookup
->done_as_is
)
1869 lookup
= requeue_lookup(query
->lookup
, ISC_TRUE
);
1870 lookup
->origin
= search
;
1872 cancel_lookup(query
->lookup
);
1877 * Insert an SOA record into the sendmessage in a lookup. Used for
1878 * creating IXFR queries.
1881 insert_soa(dig_lookup_t
*lookup
) {
1882 isc_result_t result
;
1883 dns_rdata_soa_t soa
;
1884 dns_rdata_t
*rdata
= NULL
;
1885 dns_rdatalist_t
*rdatalist
= NULL
;
1886 dns_rdataset_t
*rdataset
= NULL
;
1887 dns_name_t
*soaname
= NULL
;
1889 debug("insert_soa()");
1891 soa
.serial
= lookup
->ixfr_serial
;
1896 soa
.common
.rdclass
= lookup
->rdclass
;
1897 soa
.common
.rdtype
= dns_rdatatype_soa
;
1899 dns_name_init(&soa
.origin
, NULL
);
1900 dns_name_init(&soa
.contact
, NULL
);
1902 dns_name_clone(dns_rootname
, &soa
.origin
);
1903 dns_name_clone(dns_rootname
, &soa
.contact
);
1905 isc_buffer_init(&lookup
->rdatabuf
, lookup
->rdatastore
,
1906 sizeof(lookup
->rdatastore
));
1908 result
= dns_message_gettemprdata(lookup
->sendmsg
, &rdata
);
1909 check_result(result
, "dns_message_gettemprdata");
1911 result
= dns_rdata_fromstruct(rdata
, lookup
->rdclass
,
1912 dns_rdatatype_soa
, &soa
,
1914 check_result(result
, "isc_rdata_fromstruct");
1916 result
= dns_message_gettemprdatalist(lookup
->sendmsg
, &rdatalist
);
1917 check_result(result
, "dns_message_gettemprdatalist");
1919 result
= dns_message_gettemprdataset(lookup
->sendmsg
, &rdataset
);
1920 check_result(result
, "dns_message_gettemprdataset");
1922 dns_rdatalist_init(rdatalist
);
1923 rdatalist
->type
= dns_rdatatype_soa
;
1924 rdatalist
->rdclass
= lookup
->rdclass
;
1925 rdatalist
->covers
= 0;
1927 ISC_LIST_INIT(rdatalist
->rdata
);
1928 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1930 dns_rdataset_init(rdataset
);
1931 dns_rdatalist_tordataset(rdatalist
, rdataset
);
1933 result
= dns_message_gettempname(lookup
->sendmsg
, &soaname
);
1934 check_result(result
, "dns_message_gettempname");
1935 dns_name_init(soaname
, NULL
);
1936 dns_name_clone(lookup
->name
, soaname
);
1937 ISC_LIST_INIT(soaname
->list
);
1938 ISC_LIST_APPEND(soaname
->list
, rdataset
, link
);
1939 dns_message_addname(lookup
->sendmsg
, soaname
, DNS_SECTION_AUTHORITY
);
1943 * Setup the supplied lookup structure, making it ready to start sending
1944 * queries to servers. Create and initialize the message to be sent as
1945 * well as the query structures and buffer space for the replies. If the
1946 * server list is empty, clone it from the system default list.
1949 setup_lookup(dig_lookup_t
*lookup
) {
1950 isc_result_t result
;
1956 dns_compress_t cctx
;
1960 char utf8_textname
[MXNAME
], utf8_origin
[MXNAME
], idn_textname
[MXNAME
];
1964 result
= dns_name_settotextfilter(output_filter
);
1965 check_result(result
, "dns_name_settotextfilter");
1968 REQUIRE(lookup
!= NULL
);
1971 debug("setup_lookup(%p)", lookup
);
1973 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTRENDER
,
1975 check_result(result
, "dns_message_create");
1977 if (lookup
->new_search
) {
1978 debug("resetting lookup counter.");
1982 if (ISC_LIST_EMPTY(lookup
->my_server_list
)) {
1983 debug("cloning server list");
1984 clone_server_list(server_list
, &lookup
->my_server_list
);
1986 result
= dns_message_gettempname(lookup
->sendmsg
, &lookup
->name
);
1987 check_result(result
, "dns_message_gettempname");
1988 dns_name_init(lookup
->name
, NULL
);
1990 isc_buffer_init(&lookup
->namebuf
, lookup
->namespace,
1991 sizeof(lookup
->namespace));
1992 isc_buffer_init(&lookup
->onamebuf
, lookup
->onamespace
,
1993 sizeof(lookup
->onamespace
));
1997 * We cannot convert `textname' and `origin' separately.
1998 * `textname' doesn't contain TLD, but local mapping needs
2001 mr
= idn_encodename(IDN_LOCALCONV
| IDN_DELIMMAP
, lookup
->textname
,
2002 utf8_textname
, sizeof(utf8_textname
));
2003 idn_check_result(mr
, "convert textname to UTF-8");
2007 * If the name has too many dots, force the origin to be NULL
2008 * (which produces an absolute lookup). Otherwise, take the origin
2009 * we have if there's one in the struct already. If it's NULL,
2010 * take the first entry in the searchlist iff either usesearch
2011 * is TRUE or we got a domain line in the resolv.conf file.
2013 if (lookup
->new_search
) {
2015 if ((count_dots(utf8_textname
) >= ndots
) || !usesearch
) {
2016 lookup
->origin
= NULL
; /* Force abs lookup */
2017 lookup
->done_as_is
= ISC_TRUE
;
2018 lookup
->need_search
= usesearch
;
2019 } else if (lookup
->origin
== NULL
&& usesearch
) {
2020 lookup
->origin
= ISC_LIST_HEAD(search_list
);
2021 lookup
->need_search
= ISC_FALSE
;
2024 if ((count_dots(lookup
->textname
) >= ndots
) || !usesearch
) {
2025 lookup
->origin
= NULL
; /* Force abs lookup */
2026 lookup
->done_as_is
= ISC_TRUE
;
2027 lookup
->need_search
= usesearch
;
2028 } else if (lookup
->origin
== NULL
&& usesearch
) {
2029 lookup
->origin
= ISC_LIST_HEAD(search_list
);
2030 lookup
->need_search
= ISC_FALSE
;
2036 if (lookup
->origin
!= NULL
) {
2037 mr
= idn_encodename(IDN_LOCALCONV
| IDN_DELIMMAP
,
2038 lookup
->origin
->origin
, utf8_origin
,
2039 sizeof(utf8_origin
));
2040 idn_check_result(mr
, "convert origin to UTF-8");
2041 mr
= append_textname(utf8_textname
, utf8_origin
,
2042 sizeof(utf8_textname
));
2043 idn_check_result(mr
, "append origin to textname");
2045 mr
= idn_encodename(idnoptions
| IDN_LOCALMAP
| IDN_NAMEPREP
|
2046 IDN_IDNCONV
| IDN_LENCHECK
, utf8_textname
,
2047 idn_textname
, sizeof(idn_textname
));
2048 idn_check_result(mr
, "convert UTF-8 textname to IDN encoding");
2050 if (lookup
->origin
!= NULL
) {
2051 debug("trying origin %s", lookup
->origin
->origin
);
2052 result
= dns_message_gettempname(lookup
->sendmsg
,
2054 check_result(result
, "dns_message_gettempname");
2055 dns_name_init(lookup
->oname
, NULL
);
2056 /* XXX Helper funct to conv char* to name? */
2057 len
= strlen(lookup
->origin
->origin
);
2058 isc_buffer_init(&b
, lookup
->origin
->origin
, len
);
2059 isc_buffer_add(&b
, len
);
2060 result
= dns_name_fromtext(lookup
->oname
, &b
, dns_rootname
,
2061 0, &lookup
->onamebuf
);
2062 if (result
!= ISC_R_SUCCESS
) {
2063 dns_message_puttempname(lookup
->sendmsg
,
2065 dns_message_puttempname(lookup
->sendmsg
,
2067 fatal("'%s' is not in legal name syntax (%s)",
2068 lookup
->origin
->origin
,
2069 isc_result_totext(result
));
2071 if (lookup
->trace
&& lookup
->trace_root
) {
2072 dns_name_clone(dns_rootname
, lookup
->name
);
2074 len
= strlen(lookup
->textname
);
2075 isc_buffer_init(&b
, lookup
->textname
, len
);
2076 isc_buffer_add(&b
, len
);
2077 result
= dns_name_fromtext(lookup
->name
, &b
,
2081 if (result
!= ISC_R_SUCCESS
) {
2082 dns_message_puttempname(lookup
->sendmsg
,
2084 dns_message_puttempname(lookup
->sendmsg
,
2086 fatal("'%s' is not in legal name syntax (%s)",
2087 lookup
->textname
, isc_result_totext(result
));
2089 dns_message_puttempname(lookup
->sendmsg
, &lookup
->oname
);
2093 debug("using root origin");
2094 if (lookup
->trace
&& lookup
->trace_root
)
2095 dns_name_clone(dns_rootname
, lookup
->name
);
2098 len
= strlen(idn_textname
);
2099 isc_buffer_init(&b
, idn_textname
, len
);
2100 isc_buffer_add(&b
, len
);
2101 result
= dns_name_fromtext(lookup
->name
, &b
,
2105 len
= strlen(lookup
->textname
);
2106 isc_buffer_init(&b
, lookup
->textname
, len
);
2107 isc_buffer_add(&b
, len
);
2108 result
= dns_name_fromtext(lookup
->name
, &b
,
2113 if (result
!= ISC_R_SUCCESS
) {
2114 dns_message_puttempname(lookup
->sendmsg
,
2116 isc_buffer_init(&b
, store
, MXNAME
);
2117 fatal("'%s' is not a legal name "
2118 "(%s)", lookup
->textname
,
2119 isc_result_totext(result
));
2122 dns_name_format(lookup
->name
, store
, sizeof(store
));
2123 trying(store
, lookup
);
2124 INSIST(dns_name_isabsolute(lookup
->name
));
2126 isc_random_get(&id
);
2127 lookup
->sendmsg
->id
= (unsigned short)id
& 0xFFFF;
2128 lookup
->sendmsg
->opcode
= dns_opcode_query
;
2129 lookup
->msgcounter
= 0;
2131 * If this is a trace request, completely disallow recursion, since
2132 * it's meaningless for traces.
2134 if (lookup
->trace
|| (lookup
->ns_search_only
&& !lookup
->trace_root
))
2135 lookup
->recurse
= ISC_FALSE
;
2137 if (lookup
->recurse
&&
2138 lookup
->rdtype
!= dns_rdatatype_axfr
&&
2139 lookup
->rdtype
!= dns_rdatatype_ixfr
) {
2140 debug("recursive query");
2141 lookup
->sendmsg
->flags
|= DNS_MESSAGEFLAG_RD
;
2145 if (lookup
->aaonly
) {
2147 lookup
->sendmsg
->flags
|= DNS_MESSAGEFLAG_AA
;
2150 if (lookup
->adflag
) {
2152 lookup
->sendmsg
->flags
|= DNS_MESSAGEFLAG_AD
;
2155 if (lookup
->cdflag
) {
2157 lookup
->sendmsg
->flags
|= DNS_MESSAGEFLAG_CD
;
2160 dns_message_addname(lookup
->sendmsg
, lookup
->name
,
2161 DNS_SECTION_QUESTION
);
2163 if (lookup
->trace
&& lookup
->trace_root
) {
2164 lookup
->qrdtype
= lookup
->rdtype
;
2165 lookup
->rdtype
= dns_rdatatype_ns
;
2168 if ((lookup
->rdtype
== dns_rdatatype_axfr
) ||
2169 (lookup
->rdtype
== dns_rdatatype_ixfr
)) {
2171 * Force TCP mode if we're doing an axfr.
2173 if (lookup
->rdtype
== dns_rdatatype_axfr
) {
2174 lookup
->doing_xfr
= ISC_TRUE
;
2175 lookup
->tcp_mode
= ISC_TRUE
;
2176 } else if (lookup
->tcp_mode
) {
2177 lookup
->doing_xfr
= ISC_TRUE
;
2181 add_question(lookup
->sendmsg
, lookup
->name
, lookup
->rdclass
,
2185 if (lookup
->rdtype
== dns_rdatatype_ixfr
)
2188 /* XXX Insist this? */
2189 lookup
->tsigctx
= NULL
;
2190 lookup
->querysig
= NULL
;
2192 debug("initializing keys");
2193 result
= dns_message_settsigkey(lookup
->sendmsg
, key
);
2194 check_result(result
, "dns_message_settsigkey");
2197 lookup
->sendspace
= isc_mempool_get(commctx
);
2198 if (lookup
->sendspace
== NULL
)
2199 fatal("memory allocation failure");
2201 result
= dns_compress_init(&cctx
, -1, mctx
);
2202 check_result(result
, "dns_compress_init");
2204 debug("starting to render the message");
2205 isc_buffer_init(&lookup
->renderbuf
, lookup
->sendspace
, COMMSIZE
);
2206 result
= dns_message_renderbegin(lookup
->sendmsg
, &cctx
,
2207 &lookup
->renderbuf
);
2208 check_result(result
, "dns_message_renderbegin");
2209 if (lookup
->udpsize
> 0 || lookup
->dnssec
|| lookup
->edns
> -1) {
2210 if (lookup
->udpsize
== 0)
2211 lookup
->udpsize
= 4096;
2212 if (lookup
->edns
< 0)
2214 add_opt(lookup
->sendmsg
, lookup
->udpsize
,
2215 lookup
->edns
, lookup
->dnssec
, lookup
->nsid
);
2218 result
= dns_message_rendersection(lookup
->sendmsg
,
2219 DNS_SECTION_QUESTION
, 0);
2220 check_result(result
, "dns_message_rendersection");
2221 result
= dns_message_rendersection(lookup
->sendmsg
,
2222 DNS_SECTION_AUTHORITY
, 0);
2223 check_result(result
, "dns_message_rendersection");
2224 result
= dns_message_renderend(lookup
->sendmsg
);
2225 check_result(result
, "dns_message_renderend");
2226 debug("done rendering");
2228 dns_compress_invalidate(&cctx
);
2231 * Force TCP mode if the request is larger than 512 bytes.
2233 if (isc_buffer_usedlength(&lookup
->renderbuf
) > 512)
2234 lookup
->tcp_mode
= ISC_TRUE
;
2236 lookup
->pending
= ISC_FALSE
;
2238 for (serv
= ISC_LIST_HEAD(lookup
->my_server_list
);
2240 serv
= ISC_LIST_NEXT(serv
, link
)) {
2241 query
= isc_mem_allocate(mctx
, sizeof(dig_query_t
));
2243 fatal("memory allocation failure in %s:%d",
2244 __FILE__
, __LINE__
);
2245 debug("create query %p linked to lookup %p",
2247 query
->lookup
= lookup
;
2248 query
->waiting_connect
= ISC_FALSE
;
2249 query
->waiting_senddone
= ISC_FALSE
;
2250 query
->pending_free
= ISC_FALSE
;
2251 query
->recv_made
= ISC_FALSE
;
2252 query
->first_pass
= ISC_TRUE
;
2253 query
->first_soa_rcvd
= ISC_FALSE
;
2254 query
->second_rr_rcvd
= ISC_FALSE
;
2255 query
->first_repeat_rcvd
= ISC_FALSE
;
2256 query
->warn_id
= ISC_TRUE
;
2257 query
->first_rr_serial
= 0;
2258 query
->second_rr_serial
= 0;
2259 query
->servname
= serv
->servername
;
2260 query
->userarg
= serv
->userarg
;
2261 query
->rr_count
= 0;
2262 query
->msg_count
= 0;
2263 query
->byte_count
= 0;
2264 ISC_LINK_INIT(query
, link
);
2265 ISC_LIST_INIT(query
->recvlist
);
2266 ISC_LIST_INIT(query
->lengthlist
);
2268 query
->recvspace
= isc_mempool_get(commctx
);
2269 if (query
->recvspace
== NULL
)
2270 fatal("memory allocation failure");
2272 isc_buffer_init(&query
->recvbuf
, query
->recvspace
, COMMSIZE
);
2273 isc_buffer_init(&query
->lengthbuf
, query
->lengthspace
, 2);
2274 isc_buffer_init(&query
->slbuf
, query
->slspace
, 2);
2275 query
->sendbuf
= lookup
->renderbuf
;
2277 ISC_LINK_INIT(query
, link
);
2278 ISC_LIST_ENQUEUE(lookup
->q
, query
, link
);
2280 /* XXX qrflag, print_query, etc... */
2281 if (!ISC_LIST_EMPTY(lookup
->q
) && qr
) {
2283 printmessage(ISC_LIST_HEAD(lookup
->q
), lookup
->sendmsg
,
2289 * Event handler for send completion. Track send counter, and clear out
2290 * the query if the send was canceled.
2293 send_done(isc_task_t
*_task
, isc_event_t
*event
) {
2294 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
2295 isc_buffer_t
*b
= NULL
;
2296 dig_query_t
*query
, *next
;
2299 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
2305 debug("send_done()");
2307 debug("sendcount=%d", sendcount
);
2308 INSIST(sendcount
>= 0);
2310 for (b
= ISC_LIST_HEAD(sevent
->bufferlist
);
2312 b
= ISC_LIST_HEAD(sevent
->bufferlist
))
2313 ISC_LIST_DEQUEUE(sevent
->bufferlist
, b
, link
);
2315 query
= event
->ev_arg
;
2316 query
->waiting_senddone
= ISC_FALSE
;
2319 if (l
->ns_search_only
&& !l
->trace_root
) {
2320 debug("sending next, since searching");
2321 next
= ISC_LIST_NEXT(query
, link
);
2326 isc_event_free(&event
);
2328 if (query
->pending_free
)
2329 isc_mem_free(mctx
, query
);
2336 * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
2337 * IO sockets. The cancel handlers should take care of cleaning up the
2338 * query and lookup structures
2341 cancel_lookup(dig_lookup_t
*lookup
) {
2342 dig_query_t
*query
, *next
;
2344 debug("cancel_lookup()");
2345 query
= ISC_LIST_HEAD(lookup
->q
);
2346 while (query
!= NULL
) {
2347 next
= ISC_LIST_NEXT(query
, link
);
2348 if (query
->sock
!= NULL
) {
2349 isc_socket_cancel(query
->sock
, global_task
,
2350 ISC_SOCKCANCEL_ALL
);
2357 if (lookup
->timer
!= NULL
)
2358 isc_timer_detach(&lookup
->timer
);
2359 lookup
->pending
= ISC_FALSE
;
2360 lookup
->retries
= 0;
2364 bringup_timer(dig_query_t
*query
, unsigned int default_timeout
) {
2366 unsigned int local_timeout
;
2367 isc_result_t result
;
2369 debug("bringup_timer()");
2371 * If the timer already exists, that means we're calling this
2372 * a second time (for a retry). Don't need to recreate it,
2376 if (ISC_LIST_NEXT(query
, link
) != NULL
)
2377 local_timeout
= SERVER_TIMEOUT
;
2380 local_timeout
= default_timeout
;
2382 local_timeout
= timeout
;
2384 debug("have local timeout of %d", local_timeout
);
2385 isc_interval_set(&l
->interval
, local_timeout
, 0);
2386 if (l
->timer
!= NULL
)
2387 isc_timer_detach(&l
->timer
);
2388 result
= isc_timer_create(timermgr
, isc_timertype_once
, NULL
,
2389 &l
->interval
, global_task
, connect_timeout
,
2391 check_result(result
, "isc_timer_create");
2395 force_timeout(dig_lookup_t
*l
, dig_query_t
*query
) {
2398 event
= isc_event_allocate(mctx
, query
, ISC_TIMEREVENT_IDLE
,
2400 sizeof(isc_event_t
));
2401 if (event
== NULL
) {
2402 fatal("isc_event_allocate: %s",
2403 isc_result_totext(ISC_R_NOMEMORY
));
2405 isc_task_send(global_task
, &event
);
2410 connect_done(isc_task_t
*task
, isc_event_t
*event
);
2413 * Unlike send_udp, this can't be called multiple times with the same
2414 * query. When we retry TCP, we requeue the whole lookup, which should
2418 send_tcp_connect(dig_query_t
*query
) {
2419 isc_result_t result
;
2423 debug("send_tcp_connect(%p)", query
);
2426 query
->waiting_connect
= ISC_TRUE
;
2427 query
->lookup
->current_query
= query
;
2428 result
= get_address(query
->servname
, port
, &query
->sockaddr
);
2429 if (result
== ISC_R_NOTFOUND
) {
2431 * This servname doesn't have an address. Try the next server
2432 * by triggering an immediate 'timeout' (we lie, but the effect
2435 force_timeout(l
, query
);
2439 if (specified_source
&&
2440 (isc_sockaddr_pf(&query
->sockaddr
) !=
2441 isc_sockaddr_pf(&bind_address
))) {
2442 printf(";; Skipping server %s, incompatible "
2443 "address family\n", query
->servname
);
2444 query
->waiting_connect
= ISC_FALSE
;
2445 next
= ISC_LIST_NEXT(query
, link
);
2449 printf(";; No acceptable nameservers\n");
2450 check_next_lookup(l
);
2453 send_tcp_connect(next
);
2456 INSIST(query
->sock
== NULL
);
2457 result
= isc_socket_create(socketmgr
,
2458 isc_sockaddr_pf(&query
->sockaddr
),
2459 isc_sockettype_tcp
, &query
->sock
);
2460 check_result(result
, "isc_socket_create");
2462 debug("sockcount=%d", sockcount
);
2463 if (specified_source
)
2464 result
= isc_socket_bind(query
->sock
, &bind_address
,
2465 ISC_SOCKET_REUSEADDRESS
);
2467 if ((isc_sockaddr_pf(&query
->sockaddr
) == AF_INET
) &&
2469 isc_sockaddr_any(&bind_any
);
2471 isc_sockaddr_any6(&bind_any
);
2472 result
= isc_socket_bind(query
->sock
, &bind_any
, 0);
2474 check_result(result
, "isc_socket_bind");
2475 bringup_timer(query
, TCP_TIMEOUT
);
2476 result
= isc_socket_connect(query
->sock
, &query
->sockaddr
,
2477 global_task
, connect_done
, query
);
2478 check_result(result
, "isc_socket_connect");
2480 * If we're at the endgame of a nameserver search, we need to
2481 * immediately bring up all the queries. Do it here.
2483 if (l
->ns_search_only
&& !l
->trace_root
) {
2484 debug("sending next, since searching");
2485 next
= ISC_LIST_NEXT(query
, link
);
2487 send_tcp_connect(next
);
2492 * Send a UDP packet to the remote nameserver, possible starting the
2493 * recv action as well. Also make sure that the timer is running and
2494 * is properly reset.
2497 send_udp(dig_query_t
*query
) {
2498 dig_lookup_t
*l
= NULL
;
2499 isc_result_t result
;
2501 debug("send_udp(%p)", query
);
2504 bringup_timer(query
, UDP_TIMEOUT
);
2505 l
->current_query
= query
;
2506 debug("working on lookup %p, query %p", query
->lookup
, query
);
2507 if (!query
->recv_made
) {
2508 /* XXX Check the sense of this, need assertion? */
2509 query
->waiting_connect
= ISC_FALSE
;
2510 result
= get_address(query
->servname
, port
, &query
->sockaddr
);
2511 if (result
== ISC_R_NOTFOUND
) {
2512 /* This servname doesn't have an address. */
2513 force_timeout(l
, query
);
2517 result
= isc_socket_create(socketmgr
,
2518 isc_sockaddr_pf(&query
->sockaddr
),
2519 isc_sockettype_udp
, &query
->sock
);
2520 check_result(result
, "isc_socket_create");
2522 debug("sockcount=%d", sockcount
);
2523 if (specified_source
) {
2524 result
= isc_socket_bind(query
->sock
, &bind_address
,
2525 ISC_SOCKET_REUSEADDRESS
);
2527 isc_sockaddr_anyofpf(&bind_any
,
2528 isc_sockaddr_pf(&query
->sockaddr
));
2529 result
= isc_socket_bind(query
->sock
, &bind_any
, 0);
2531 check_result(result
, "isc_socket_bind");
2533 query
->recv_made
= ISC_TRUE
;
2534 ISC_LINK_INIT(&query
->recvbuf
, link
);
2535 ISC_LIST_ENQUEUE(query
->recvlist
, &query
->recvbuf
,
2537 debug("recving with lookup=%p, query=%p, sock=%p",
2538 query
->lookup
, query
, query
->sock
);
2539 result
= isc_socket_recvv(query
->sock
, &query
->recvlist
, 1,
2540 global_task
, recv_done
, query
);
2541 check_result(result
, "isc_socket_recvv");
2543 debug("recvcount=%d", recvcount
);
2545 ISC_LIST_INIT(query
->sendlist
);
2546 ISC_LIST_ENQUEUE(query
->sendlist
, &query
->sendbuf
, link
);
2547 debug("sending a request");
2548 TIME_NOW(&query
->time_sent
);
2549 INSIST(query
->sock
!= NULL
);
2550 query
->waiting_senddone
= ISC_TRUE
;
2551 result
= isc_socket_sendtov(query
->sock
, &query
->sendlist
,
2552 global_task
, send_done
, query
,
2553 &query
->sockaddr
, NULL
);
2554 check_result(result
, "isc_socket_sendtov");
2559 * IO timeout handler, used for both connect and recv timeouts. If
2560 * retries are still allowed, either resend the UDP packet or queue a
2561 * new TCP lookup. Otherwise, cancel the lookup.
2564 connect_timeout(isc_task_t
*task
, isc_event_t
*event
) {
2565 dig_lookup_t
*l
= NULL
;
2566 dig_query_t
*query
= NULL
, *cq
;
2569 REQUIRE(event
->ev_type
== ISC_TIMEREVENT_IDLE
);
2571 debug("connect_timeout()");
2575 query
= l
->current_query
;
2576 isc_event_free(&event
);
2580 if ((query
!= NULL
) && (query
->lookup
->current_query
!= NULL
) &&
2581 (ISC_LIST_NEXT(query
->lookup
->current_query
, link
) != NULL
)) {
2582 debug("trying next server...");
2583 cq
= query
->lookup
->current_query
;
2585 send_udp(ISC_LIST_NEXT(cq
, link
));
2587 if (query
->sock
!= NULL
)
2588 isc_socket_cancel(query
->sock
, NULL
,
2589 ISC_SOCKCANCEL_ALL
);
2590 send_tcp_connect(ISC_LIST_NEXT(cq
, link
));
2596 if (l
->retries
> 1) {
2599 debug("resending UDP request to first server");
2600 send_udp(ISC_LIST_HEAD(l
->q
));
2602 debug("making new TCP request, %d tries left",
2605 requeue_lookup(l
, ISC_TRUE
);
2607 check_next_lookup(l
);
2610 fputs(l
->cmdline
, stdout
);
2611 printf(";; connection timed out; no servers could be "
2614 check_next_lookup(l
);
2622 * Event handler for the TCP recv which gets the length header of TCP
2623 * packets. Start the next recv of length bytes.
2626 tcp_length_done(isc_task_t
*task
, isc_event_t
*event
) {
2627 isc_socketevent_t
*sevent
;
2628 isc_buffer_t
*b
= NULL
;
2629 isc_result_t result
;
2630 dig_query_t
*query
= NULL
;
2632 isc_uint16_t length
;
2634 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_RECVDONE
);
2639 debug("tcp_length_done()");
2642 sevent
= (isc_socketevent_t
*)event
;
2643 query
= event
->ev_arg
;
2646 INSIST(recvcount
>= 0);
2648 b
= ISC_LIST_HEAD(sevent
->bufferlist
);
2649 INSIST(b
== &query
->lengthbuf
);
2650 ISC_LIST_DEQUEUE(sevent
->bufferlist
, b
, link
);
2652 if (sevent
->result
== ISC_R_CANCELED
) {
2653 isc_event_free(&event
);
2656 check_next_lookup(l
);
2660 if (sevent
->result
!= ISC_R_SUCCESS
) {
2661 char sockstr
[ISC_SOCKADDR_FORMATSIZE
];
2662 isc_sockaddr_format(&query
->sockaddr
, sockstr
,
2664 printf(";; communications error to %s: %s\n",
2665 sockstr
, isc_result_totext(sevent
->result
));
2667 isc_socket_detach(&query
->sock
);
2669 debug("sockcount=%d", sockcount
);
2670 INSIST(sockcount
>= 0);
2671 isc_event_free(&event
);
2673 check_next_lookup(l
);
2677 length
= isc_buffer_getuint16(b
);
2679 isc_event_free(&event
);
2680 launch_next_query(query
, ISC_FALSE
);
2686 * Even though the buffer was already init'ed, we need
2687 * to redo it now, to force the length we want.
2689 isc_buffer_invalidate(&query
->recvbuf
);
2690 isc_buffer_init(&query
->recvbuf
, query
->recvspace
, length
);
2691 ENSURE(ISC_LIST_EMPTY(query
->recvlist
));
2692 ISC_LINK_INIT(&query
->recvbuf
, link
);
2693 ISC_LIST_ENQUEUE(query
->recvlist
, &query
->recvbuf
, link
);
2694 debug("recving with lookup=%p, query=%p", query
->lookup
, query
);
2695 result
= isc_socket_recvv(query
->sock
, &query
->recvlist
, length
, task
,
2697 check_result(result
, "isc_socket_recvv");
2699 debug("resubmitted recv request with length %d, recvcount=%d",
2701 isc_event_free(&event
);
2706 * For transfers that involve multiple recvs (XFR's in particular),
2707 * launch the next recv.
2710 launch_next_query(dig_query_t
*query
, isc_boolean_t include_question
) {
2711 isc_result_t result
;
2716 debug("launch_next_query()");
2718 if (!query
->lookup
->pending
) {
2719 debug("ignoring launch_next_query because !pending");
2720 isc_socket_detach(&query
->sock
);
2722 debug("sockcount=%d", sockcount
);
2723 INSIST(sockcount
>= 0);
2724 query
->waiting_connect
= ISC_FALSE
;
2727 check_next_lookup(l
);
2731 isc_buffer_clear(&query
->slbuf
);
2732 isc_buffer_clear(&query
->lengthbuf
);
2733 isc_buffer_putuint16(&query
->slbuf
, (isc_uint16_t
) query
->sendbuf
.used
);
2734 ISC_LIST_INIT(query
->sendlist
);
2735 ISC_LINK_INIT(&query
->slbuf
, link
);
2736 ISC_LIST_ENQUEUE(query
->sendlist
, &query
->slbuf
, link
);
2737 if (include_question
)
2738 ISC_LIST_ENQUEUE(query
->sendlist
, &query
->sendbuf
, link
);
2739 ISC_LINK_INIT(&query
->lengthbuf
, link
);
2740 ISC_LIST_ENQUEUE(query
->lengthlist
, &query
->lengthbuf
, link
);
2742 result
= isc_socket_recvv(query
->sock
, &query
->lengthlist
, 0,
2743 global_task
, tcp_length_done
, query
);
2744 check_result(result
, "isc_socket_recvv");
2746 debug("recvcount=%d", recvcount
);
2747 if (!query
->first_soa_rcvd
) {
2748 debug("sending a request in launch_next_query");
2749 TIME_NOW(&query
->time_sent
);
2750 query
->waiting_senddone
= ISC_TRUE
;
2751 result
= isc_socket_sendv(query
->sock
, &query
->sendlist
,
2752 global_task
, send_done
, query
);
2753 check_result(result
, "isc_socket_sendv");
2755 debug("sendcount=%d", sendcount
);
2757 query
->waiting_connect
= ISC_FALSE
;
2759 check_next_lookup(query
->lookup
);
2765 * Event handler for TCP connect complete. Make sure the connection was
2766 * successful, then pass into launch_next_query to actually send the
2770 connect_done(isc_task_t
*task
, isc_event_t
*event
) {
2771 isc_socketevent_t
*sevent
= NULL
;
2772 dig_query_t
*query
= NULL
, *next
;
2777 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_CONNECT
);
2780 debug("connect_done()");
2783 sevent
= (isc_socketevent_t
*)event
;
2784 query
= sevent
->ev_arg
;
2786 INSIST(query
->waiting_connect
);
2788 query
->waiting_connect
= ISC_FALSE
;
2790 if (sevent
->result
== ISC_R_CANCELED
) {
2791 debug("in cancel handler");
2792 isc_socket_detach(&query
->sock
);
2793 INSIST(sockcount
> 0);
2795 debug("sockcount=%d", sockcount
);
2796 query
->waiting_connect
= ISC_FALSE
;
2797 isc_event_free(&event
);
2800 check_next_lookup(l
);
2804 if (sevent
->result
!= ISC_R_SUCCESS
) {
2805 char sockstr
[ISC_SOCKADDR_FORMATSIZE
];
2807 debug("unsuccessful connection: %s",
2808 isc_result_totext(sevent
->result
));
2809 isc_sockaddr_format(&query
->sockaddr
, sockstr
, sizeof(sockstr
));
2810 if (sevent
->result
!= ISC_R_CANCELED
)
2811 printf(";; Connection to %s(%s) for %s failed: "
2813 query
->servname
, query
->lookup
->textname
,
2814 isc_result_totext(sevent
->result
));
2815 isc_socket_detach(&query
->sock
);
2817 INSIST(sockcount
>= 0);
2818 /* XXX Clean up exitcodes */
2821 debug("sockcount=%d", sockcount
);
2822 query
->waiting_connect
= ISC_FALSE
;
2823 isc_event_free(&event
);
2825 if (l
->current_query
!= NULL
)
2826 next
= ISC_LIST_NEXT(l
->current_query
, link
);
2831 bringup_timer(next
, TCP_TIMEOUT
);
2832 send_tcp_connect(next
);
2834 check_next_lookup(l
);
2839 launch_next_query(query
, ISC_TRUE
);
2840 isc_event_free(&event
);
2845 * Check if the ongoing XFR needs more data before it's complete, using
2846 * the semantics of IXFR and AXFR protocols. Much of the complexity of
2847 * this routine comes from determining when an IXFR is complete.
2848 * ISC_FALSE means more data is on the way, and the recv has been issued.
2850 static isc_boolean_t
2851 check_for_more_data(dig_query_t
*query
, dns_message_t
*msg
,
2852 isc_socketevent_t
*sevent
)
2854 dns_rdataset_t
*rdataset
= NULL
;
2855 dns_rdata_t rdata
= DNS_RDATA_INIT
;
2856 dns_rdata_soa_t soa
;
2857 isc_uint32_t serial
;
2858 isc_result_t result
;
2860 debug("check_for_more_data()");
2863 * By the time we're in this routine, we know we're doing
2864 * either an AXFR or IXFR. If there's no second_rr_type,
2865 * then we don't yet know which kind of answer we got back
2866 * from the server. Here, we're going to walk through the
2867 * rr's in the message, acting as necessary whenever we hit
2872 query
->byte_count
+= sevent
->n
;
2873 result
= dns_message_firstname(msg
, DNS_SECTION_ANSWER
);
2874 if (result
!= ISC_R_SUCCESS
) {
2875 puts("; Transfer failed.");
2881 dns_message_currentname(msg
, DNS_SECTION_ANSWER
,
2883 for (rdataset
= ISC_LIST_HEAD(name
->list
);
2885 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
2886 result
= dns_rdataset_first(rdataset
);
2887 if (result
!= ISC_R_SUCCESS
)
2891 dns_rdata_reset(&rdata
);
2892 dns_rdataset_current(rdataset
, &rdata
);
2894 * If this is the first rr, make sure
2897 if ((!query
->first_soa_rcvd
) &&
2898 (rdata
.type
!= dns_rdatatype_soa
)) {
2899 puts("; Transfer failed. "
2900 "Didn't start with SOA answer.");
2903 if ((!query
->second_rr_rcvd
) &&
2904 (rdata
.type
!= dns_rdatatype_soa
)) {
2905 query
->second_rr_rcvd
= ISC_TRUE
;
2906 query
->second_rr_serial
= 0;
2907 debug("got the second rr as nonsoa");
2912 * If the record is anything except an SOA
2913 * now, just continue on...
2915 if (rdata
.type
!= dns_rdatatype_soa
)
2917 /* Now we have an SOA. Work with it. */
2918 debug("got an SOA");
2919 result
= dns_rdata_tostruct(&rdata
, &soa
, NULL
);
2920 check_result(result
, "dns_rdata_tostruct");
2921 serial
= soa
.serial
;
2922 dns_rdata_freestruct(&soa
);
2923 if (!query
->first_soa_rcvd
) {
2924 query
->first_soa_rcvd
= ISC_TRUE
;
2925 query
->first_rr_serial
= serial
;
2926 debug("this is the first %d",
2927 query
->lookup
->ixfr_serial
);
2928 if (query
->lookup
->ixfr_serial
>=
2933 if (query
->lookup
->rdtype
==
2934 dns_rdatatype_axfr
) {
2935 debug("doing axfr, got second SOA");
2938 if (!query
->second_rr_rcvd
) {
2939 if (query
->first_rr_serial
== serial
) {
2940 debug("doing ixfr, got "
2944 debug("this is the second %d",
2945 query
->lookup
->ixfr_serial
);
2946 query
->second_rr_rcvd
= ISC_TRUE
;
2947 query
->second_rr_serial
= serial
;
2950 if (query
->second_rr_serial
== 0) {
2952 * If the second RR was a non-SOA
2953 * record, and we're getting any
2954 * other SOA, then this is an
2955 * AXFR, and we're done.
2957 debug("done, since axfr");
2961 * If we get to this point, we're doing an
2962 * IXFR and have to start really looking
2963 * at serial numbers.
2965 if (query
->first_rr_serial
== serial
) {
2966 debug("got a match for ixfr");
2967 if (!query
->first_repeat_rcvd
) {
2968 query
->first_repeat_rcvd
=
2972 debug("done with ixfr");
2975 debug("meaningless soa %d", serial
);
2977 result
= dns_rdataset_next(rdataset
);
2978 } while (result
== ISC_R_SUCCESS
);
2980 result
= dns_message_nextname(msg
, DNS_SECTION_ANSWER
);
2981 } while (result
== ISC_R_SUCCESS
);
2982 launch_next_query(query
, ISC_FALSE
);
2985 received(sevent
->n
, &sevent
->address
, query
);
2990 * Event handler for recv complete. Perform whatever actions are necessary,
2991 * based on the specifics of the user's request.
2994 recv_done(isc_task_t
*task
, isc_event_t
*event
) {
2995 isc_socketevent_t
*sevent
= NULL
;
2996 dig_query_t
*query
= NULL
;
2997 isc_buffer_t
*b
= NULL
;
2998 dns_message_t
*msg
= NULL
;
3000 dig_message_t
*chase_msg
= NULL
;
3001 dig_message_t
*chase_msg2
= NULL
;
3003 isc_result_t result
;
3004 dig_lookup_t
*n
, *l
;
3005 isc_boolean_t docancel
= ISC_FALSE
;
3006 isc_boolean_t match
= ISC_TRUE
;
3007 unsigned int parseflags
;
3009 unsigned int msgflags
;
3011 isc_result_t do_sigchase
= ISC_FALSE
;
3013 dns_message_t
*msg_temp
= NULL
;
3015 isc_buffer_t
*buf
= NULL
;
3021 debug("recv_done()");
3025 debug("recvcount=%d", recvcount
);
3026 INSIST(recvcount
>= 0);
3028 query
= event
->ev_arg
;
3029 debug("lookup=%p, query=%p", query
->lookup
, query
);
3033 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_RECVDONE
);
3034 sevent
= (isc_socketevent_t
*)event
;
3036 b
= ISC_LIST_HEAD(sevent
->bufferlist
);
3037 INSIST(b
== &query
->recvbuf
);
3038 ISC_LIST_DEQUEUE(sevent
->bufferlist
, &query
->recvbuf
, link
);
3040 if ((l
->tcp_mode
) && (l
->timer
!= NULL
))
3041 isc_timer_touch(l
->timer
);
3042 if ((!l
->pending
&& !l
->ns_search_only
) || cancel_now
) {
3043 debug("no longer pending. Got %s",
3044 isc_result_totext(sevent
->result
));
3045 query
->waiting_connect
= ISC_FALSE
;
3047 isc_event_free(&event
);
3049 check_next_lookup(l
);
3054 if (sevent
->result
!= ISC_R_SUCCESS
) {
3055 if (sevent
->result
== ISC_R_CANCELED
) {
3056 debug("in recv cancel handler");
3057 query
->waiting_connect
= ISC_FALSE
;
3059 printf(";; communications error: %s\n",
3060 isc_result_totext(sevent
->result
));
3061 isc_socket_detach(&query
->sock
);
3063 debug("sockcount=%d", sockcount
);
3064 INSIST(sockcount
>= 0);
3066 isc_event_free(&event
);
3068 check_next_lookup(l
);
3074 !isc_sockaddr_compare(&sevent
->address
, &query
->sockaddr
,
3075 ISC_SOCKADDR_CMPADDR
|
3076 ISC_SOCKADDR_CMPPORT
|
3077 ISC_SOCKADDR_CMPSCOPE
|
3078 ISC_SOCKADDR_CMPSCOPEZERO
)) {
3079 char buf1
[ISC_SOCKADDR_FORMATSIZE
];
3080 char buf2
[ISC_SOCKADDR_FORMATSIZE
];
3083 if (isc_sockaddr_pf(&query
->sockaddr
) == AF_INET
)
3084 isc_sockaddr_any(&any
);
3086 isc_sockaddr_any6(&any
);
3089 * We don't expect a match when the packet is
3090 * sent to 0.0.0.0, :: or to a multicast addresses.
3091 * XXXMPA broadcast needs to be handled here as well.
3093 if ((!isc_sockaddr_eqaddr(&query
->sockaddr
, &any
) &&
3094 !isc_sockaddr_ismulticast(&query
->sockaddr
)) ||
3095 isc_sockaddr_getport(&query
->sockaddr
) !=
3096 isc_sockaddr_getport(&sevent
->address
)) {
3097 isc_sockaddr_format(&sevent
->address
, buf1
,
3099 isc_sockaddr_format(&query
->sockaddr
, buf2
,
3101 printf(";; reply from unexpected source: %s,"
3102 " expected %s\n", buf1
, buf2
);
3107 result
= dns_message_peekheader(b
, &id
, &msgflags
);
3108 if (result
!= ISC_R_SUCCESS
|| l
->sendmsg
->id
!= id
) {
3111 isc_boolean_t fail
= ISC_TRUE
;
3112 if (result
== ISC_R_SUCCESS
) {
3113 if (!query
->first_soa_rcvd
||
3115 printf(";; %s: ID mismatch: "
3116 "expected ID %u, got %u\n",
3117 query
->first_soa_rcvd
?
3118 "WARNING" : "ERROR",
3119 l
->sendmsg
->id
, id
);
3120 if (query
->first_soa_rcvd
)
3122 query
->warn_id
= ISC_FALSE
;
3124 printf(";; ERROR: short "
3125 "(< header size) message\n");
3127 isc_event_free(&event
);
3129 check_next_lookup(l
);
3134 } else if (result
== ISC_R_SUCCESS
)
3135 printf(";; Warning: ID mismatch: "
3136 "expected ID %u, got %u\n", l
->sendmsg
->id
, id
);
3138 printf(";; Warning: short "
3139 "(< header size) message received\n");
3142 if (result
== ISC_R_SUCCESS
&& (msgflags
& DNS_MESSAGEFLAG_QR
) == 0)
3143 printf(";; Warning: query response not set\n");
3148 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
, &msg
);
3149 check_result(result
, "dns_message_create");
3152 if (l
->querysig
== NULL
) {
3153 debug("getting initial querysig");
3154 result
= dns_message_getquerytsig(l
->sendmsg
, mctx
,
3156 check_result(result
, "dns_message_getquerytsig");
3158 result
= dns_message_setquerytsig(msg
, l
->querysig
);
3159 check_result(result
, "dns_message_setquerytsig");
3160 result
= dns_message_settsigkey(msg
, key
);
3161 check_result(result
, "dns_message_settsigkey");
3162 msg
->tsigctx
= l
->tsigctx
;
3164 if (l
->msgcounter
!= 0)
3165 msg
->tcp_continuation
= 1;
3169 debug("before parse starts");
3170 parseflags
= DNS_MESSAGEPARSE_PRESERVEORDER
;
3173 do_sigchase
= ISC_FALSE
;
3176 do_sigchase
= ISC_TRUE
;
3179 if (l
->besteffort
) {
3180 parseflags
|= DNS_MESSAGEPARSE_BESTEFFORT
;
3181 parseflags
|= DNS_MESSAGEPARSE_IGNORETRUNCATION
;
3183 result
= dns_message_parse(msg
, b
, parseflags
);
3184 if (result
== DNS_R_RECOVERABLE
) {
3185 printf(";; Warning: Message parser reports malformed "
3186 "message packet.\n");
3187 result
= ISC_R_SUCCESS
;
3189 if (result
!= ISC_R_SUCCESS
) {
3190 printf(";; Got bad packet: %s\n", isc_result_totext(result
));
3192 query
->waiting_connect
= ISC_FALSE
;
3193 dns_message_destroy(&msg
);
3194 isc_event_free(&event
);
3197 check_next_lookup(l
);
3201 if (msg
->counts
[DNS_SECTION_QUESTION
] != 0) {
3203 for (result
= dns_message_firstname(msg
, DNS_SECTION_QUESTION
);
3204 result
== ISC_R_SUCCESS
&& match
;
3205 result
= dns_message_nextname(msg
, DNS_SECTION_QUESTION
)) {
3206 dns_name_t
*name
= NULL
;
3207 dns_rdataset_t
*rdataset
;
3209 dns_message_currentname(msg
, DNS_SECTION_QUESTION
,
3211 for (rdataset
= ISC_LIST_HEAD(name
->list
);
3213 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3214 if (l
->rdtype
!= rdataset
->type
||
3215 l
->rdclass
!= rdataset
->rdclass
||
3216 !dns_name_equal(l
->name
, name
)) {
3217 char namestr
[DNS_NAME_FORMATSIZE
];
3218 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
3219 char classbuf
[DNS_RDATACLASS_FORMATSIZE
];
3220 dns_name_format(name
, namestr
,
3222 dns_rdatatype_format(rdataset
->type
,
3225 dns_rdataclass_format(rdataset
->rdclass
,
3228 printf(";; Question section mismatch: "
3230 namestr
, typebuf
, classbuf
);
3236 dns_message_destroy(&msg
);
3238 isc_event_free(&event
);
3240 check_next_lookup(l
);
3247 if ((msg
->flags
& DNS_MESSAGEFLAG_TC
) != 0 &&
3248 !l
->ignore
&& !l
->tcp_mode
) {
3249 printf(";; Truncated, retrying in TCP mode.\n");
3250 n
= requeue_lookup(l
, ISC_TRUE
);
3251 n
->tcp_mode
= ISC_TRUE
;
3252 n
->origin
= query
->lookup
->origin
;
3253 dns_message_destroy(&msg
);
3254 isc_event_free(&event
);
3257 check_next_lookup(l
);
3261 if ((msg
->rcode
== dns_rcode_servfail
&& !l
->servfail_stops
) ||
3262 (check_ra
&& (msg
->flags
& DNS_MESSAGEFLAG_RA
) == 0 && l
->recurse
))
3264 dig_query_t
*next
= ISC_LIST_NEXT(query
, link
);
3265 if (l
->current_query
== query
)
3266 l
->current_query
= NULL
;
3268 debug("sending query %p\n", next
);
3270 send_tcp_connect(next
);
3275 * If our query is at the head of the list and there
3276 * is no next, we're the only one left, so fall
3277 * through to print the message.
3279 if ((ISC_LIST_HEAD(l
->q
) != query
) ||
3280 (ISC_LIST_NEXT(query
, link
) != NULL
)) {
3281 if( l
->comments
== ISC_TRUE
)
3282 printf(";; Got %s from %s, "
3283 "trying next server\n",
3284 msg
->rcode
== dns_rcode_servfail
?
3286 "recursion not available",
3289 check_next_lookup(l
);
3290 dns_message_destroy(&msg
);
3291 isc_event_free(&event
);
3298 result
= dns_tsig_verify(&query
->recvbuf
, msg
, NULL
, NULL
);
3299 if (result
!= ISC_R_SUCCESS
) {
3300 printf(";; Couldn't verify signature: %s\n",
3301 isc_result_totext(result
));
3302 validated
= ISC_FALSE
;
3304 l
->tsigctx
= msg
->tsigctx
;
3305 msg
->tsigctx
= NULL
;
3306 if (l
->querysig
!= NULL
) {
3307 debug("freeing querysig buffer %p", l
->querysig
);
3308 isc_buffer_free(&l
->querysig
);
3310 result
= dns_message_getquerytsig(msg
, mctx
, &l
->querysig
);
3311 check_result(result
,"dns_message_getquerytsig");
3314 extrabytes
= isc_buffer_remaininglength(b
);
3316 debug("after parse");
3317 if (l
->doing_xfr
&& l
->xfr_q
== NULL
) {
3320 * Once we are in the XFR message, increase
3321 * the timeout to much longer, so brief network
3322 * outages won't cause the XFR to abort
3324 if (timeout
!= INT_MAX
&& l
->timer
!= NULL
) {
3325 unsigned int local_timeout
;
3329 local_timeout
= TCP_TIMEOUT
* 4;
3331 local_timeout
= UDP_TIMEOUT
* 4;
3333 if (timeout
< (INT_MAX
/ 4))
3334 local_timeout
= timeout
* 4;
3336 local_timeout
= INT_MAX
;
3338 debug("have local timeout of %d", local_timeout
);
3339 isc_interval_set(&l
->interval
, local_timeout
, 0);
3340 result
= isc_timer_reset(l
->timer
,
3345 check_result(result
, "isc_timer_reset");
3349 if (!l
->doing_xfr
|| l
->xfr_q
== query
) {
3350 if (msg
->rcode
!= dns_rcode_noerror
&&
3351 (l
->origin
!= NULL
|| l
->need_search
)) {
3352 if (!next_origin(msg
, query
) || showsearch
) {
3353 printmessage(query
, msg
, ISC_TRUE
);
3354 received(b
->used
, &sevent
->address
, query
);
3356 } else if (!l
->trace
&& !l
->ns_search_only
) {
3360 printmessage(query
, msg
, ISC_TRUE
);
3361 } else if (l
->trace
) {
3363 int count
= msg
->counts
[DNS_SECTION_ANSWER
];
3365 debug("in TRACE code");
3366 if (!l
->ns_search_only
)
3367 printmessage(query
, msg
, ISC_TRUE
);
3369 l
->rdtype
= l
->qrdtype
;
3370 if (l
->trace_root
|| (l
->ns_search_only
&& count
> 0)) {
3372 l
->rdtype
= dns_rdatatype_soa
;
3373 n
= followup_lookup(msg
, query
,
3374 DNS_SECTION_ANSWER
);
3375 l
->trace_root
= ISC_FALSE
;
3376 } else if (count
== 0)
3377 n
= followup_lookup(msg
, query
,
3378 DNS_SECTION_AUTHORITY
);
3380 docancel
= ISC_TRUE
;
3382 debug("in NSSEARCH code");
3384 if (l
->trace_root
) {
3386 * This is the initial NS query.
3390 l
->rdtype
= dns_rdatatype_soa
;
3391 n
= followup_lookup(msg
, query
,
3392 DNS_SECTION_ANSWER
);
3394 docancel
= ISC_TRUE
;
3395 l
->trace_root
= ISC_FALSE
;
3400 printmessage(query
, msg
, ISC_TRUE
);
3404 chase_msg
= isc_mem_allocate(mctx
,
3405 sizeof(dig_message_t
));
3406 if (chase_msg
== NULL
) {
3407 fatal("Memory allocation failure in %s:%d",
3408 __FILE__
, __LINE__
);
3410 ISC_LIST_INITANDAPPEND(chase_message_list
, chase_msg
,
3412 if (dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
,
3413 &msg_temp
) != ISC_R_SUCCESS
) {
3414 fatal("dns_message_create in %s:%d",
3415 __FILE__
, __LINE__
);
3418 isc_buffer_usedregion(b
, &r
);
3419 result
= isc_buffer_allocate(mctx
, &buf
, r
.length
);
3421 check_result(result
, "isc_buffer_allocate");
3422 result
= isc_buffer_copyregion(buf
, &r
);
3423 check_result(result
, "isc_buffer_copyregion");
3425 result
= dns_message_parse(msg_temp
, buf
, 0);
3427 isc_buffer_free(&buf
);
3428 chase_msg
->msg
= msg_temp
;
3430 chase_msg2
= isc_mem_allocate(mctx
,
3431 sizeof(dig_message_t
));
3432 if (chase_msg2
== NULL
) {
3433 fatal("Memory allocation failure in %s:%d",
3434 __FILE__
, __LINE__
);
3436 ISC_LIST_INITANDAPPEND(chase_message_list2
, chase_msg2
,
3438 chase_msg2
->msg
= msg
;
3444 if (l
->sigchase
&& ISC_LIST_EMPTY(lookup_list
)) {
3450 debug("still pending.");
3452 if (query
!= l
->xfr_q
) {
3453 dns_message_destroy(&msg
);
3454 isc_event_free(&event
);
3455 query
->waiting_connect
= ISC_FALSE
;
3460 docancel
= check_for_more_data(query
, msg
, sevent
);
3462 dns_message_destroy(&msg
);
3465 check_next_lookup(l
);
3469 if (msg
->rcode
== dns_rcode_noerror
|| l
->origin
== NULL
) {
3474 received(b
->used
, &sevent
->address
, query
);
3477 if (!query
->lookup
->ns_search_only
)
3478 query
->lookup
->pending
= ISC_FALSE
;
3479 if (!query
->lookup
->ns_search_only
||
3480 query
->lookup
->trace_root
|| docancel
) {
3484 dns_message_destroy(&msg
);
3489 check_next_lookup(l
);
3497 dns_message_destroy(&msg
);
3499 isc_event_free(&event
);
3504 isc_buffer_invalidate(&query
->recvbuf
);
3505 isc_buffer_init(&query
->recvbuf
, query
->recvspace
, COMMSIZE
);
3506 ISC_LIST_ENQUEUE(query
->recvlist
, &query
->recvbuf
, link
);
3507 result
= isc_socket_recvv(query
->sock
, &query
->recvlist
, 1,
3508 global_task
, recv_done
, query
);
3509 check_result(result
, "isc_socket_recvv");
3511 isc_event_free(&event
);
3517 * Turn a name into an address, using system-supplied routines. This is
3518 * used in looking up server names, etc... and needs to use system-supplied
3519 * routines, since they may be using a non-DNS system for these lookups.
3522 get_address(char *host
, in_port_t port
, isc_sockaddr_t
*sockaddr
) {
3524 isc_result_t result
;
3527 result
= bind9_getaddresses(host
, port
, sockaddr
, 1, &count
);
3529 if (result
!= ISC_R_SUCCESS
)
3534 return (ISC_R_SUCCESS
);
3538 * Initiate either a TCP or UDP lookup
3541 do_lookup(dig_lookup_t
*lookup
) {
3543 REQUIRE(lookup
!= NULL
);
3545 debug("do_lookup()");
3546 lookup
->pending
= ISC_TRUE
;
3547 if (lookup
->tcp_mode
)
3548 send_tcp_connect(ISC_LIST_HEAD(lookup
->q
));
3550 send_udp(ISC_LIST_HEAD(lookup
->q
));
3554 * Start everything in action upon task startup.
3557 onrun_callback(isc_task_t
*task
, isc_event_t
*event
) {
3560 isc_event_free(&event
);
3567 * Make everything on the lookup queue go away. Mainly used by the
3572 dig_lookup_t
*l
, *n
;
3573 dig_query_t
*q
, *nq
;
3575 debug("cancel_all()");
3582 cancel_now
= ISC_TRUE
;
3583 if (current_lookup
!= NULL
) {
3584 if (current_lookup
->timer
!= NULL
)
3585 isc_timer_detach(¤t_lookup
->timer
);
3586 q
= ISC_LIST_HEAD(current_lookup
->q
);
3588 debug("canceling query %p, belonging to %p",
3590 nq
= ISC_LIST_NEXT(q
, link
);
3591 if (q
->sock
!= NULL
) {
3592 isc_socket_cancel(q
->sock
, NULL
,
3593 ISC_SOCKCANCEL_ALL
);
3600 l
= ISC_LIST_HEAD(lookup_list
);
3602 n
= ISC_LIST_NEXT(l
, link
);
3603 ISC_LIST_DEQUEUE(lookup_list
, l
, link
);
3604 try_clear_lookup(l
);
3611 * Destroy all of the libs we are using, and get everything ready for a
3615 destroy_libs(void) {
3618 dig_message_t
*chase_msg
;
3621 isc_result_t result
;
3624 debug("destroy_libs()");
3625 if (global_task
!= NULL
) {
3626 debug("freeing task");
3627 isc_task_detach(&global_task
);
3630 * The taskmgr_destroy() call blocks until all events are cleared
3633 if (taskmgr
!= NULL
) {
3634 debug("freeing taskmgr");
3635 isc_taskmgr_destroy(&taskmgr
);
3638 REQUIRE(sockcount
== 0);
3639 REQUIRE(recvcount
== 0);
3640 REQUIRE(sendcount
== 0);
3642 INSIST(ISC_LIST_HEAD(lookup_list
) == NULL
);
3643 INSIST(current_lookup
== NULL
);
3646 free_now
= ISC_TRUE
;
3648 lwres_conf_clear(lwctx
);
3649 lwres_context_destroy(&lwctx
);
3651 flush_server_list();
3656 result
= dns_name_settotextfilter(NULL
);
3657 check_result(result
, "dns_name_settotextfilter");
3661 if (commctx
!= NULL
) {
3662 debug("freeing commctx");
3663 isc_mempool_destroy(&commctx
);
3665 if (socketmgr
!= NULL
) {
3666 debug("freeing socketmgr");
3667 isc_socketmgr_destroy(&socketmgr
);
3669 if (timermgr
!= NULL
) {
3670 debug("freeing timermgr");
3671 isc_timermgr_destroy(&timermgr
);
3674 debug("freeing key %p", key
);
3675 dns_tsigkey_detach(&key
);
3677 if (namebuf
!= NULL
)
3678 isc_buffer_free(&namebuf
);
3681 debug("destroy DST lib");
3683 is_dst_up
= ISC_FALSE
;
3686 debug("detach from entropy");
3687 isc_entropy_detach(&entp
);
3691 DESTROYLOCK(&lookup_lock
);
3694 debug("Destroy the messages kept for sigchase");
3695 /* Destroy the messages kept for sigchase */
3696 chase_msg
= ISC_LIST_HEAD(chase_message_list
);
3698 while (chase_msg
!= NULL
) {
3699 INSIST(chase_msg
->msg
!= NULL
);
3700 dns_message_destroy(&(chase_msg
->msg
));
3702 chase_msg
= ISC_LIST_NEXT(chase_msg
, link
);
3703 isc_mem_free(mctx
, ptr
);
3706 chase_msg
= ISC_LIST_HEAD(chase_message_list2
);
3708 while (chase_msg
!= NULL
) {
3709 INSIST(chase_msg
->msg
!= NULL
);
3710 dns_message_destroy(&(chase_msg
->msg
));
3712 chase_msg
= ISC_LIST_NEXT(chase_msg
, link
);
3713 isc_mem_free(mctx
, ptr
);
3715 if (dns_name_dynamic(&chase_name
))
3716 free_name(&chase_name
, mctx
);
3718 if (dns_name_dynamic(&chase_current_name
))
3719 free_name(&chase_current_name
, mctx
);
3720 if (dns_name_dynamic(&chase_authority_name
))
3721 free_name(&chase_authority_name
, mctx
);
3724 if (dns_name_dynamic(&chase_signame
))
3725 free_name(&chase_signame
, mctx
);
3729 debug("Removing log context");
3730 isc_log_destroy(&lctx
);
3732 debug("Destroy memory");
3733 if (memdebugging
!= 0)
3734 isc_mem_stats(mctx
, stderr
);
3736 isc_mem_destroy(&mctx
);
3741 initialize_idn(void) {
3743 isc_result_t result
;
3745 #ifdef HAVE_SETLOCALE
3747 (void)setlocale(LC_ALL
, "");
3749 /* Create configuration context. */
3750 r
= idn_nameinit(1);
3751 if (r
!= idn_success
)
3752 fatal("idn api initialization failed: %s",
3753 idn_result_tostring(r
));
3755 /* Set domain name -> text post-conversion filter. */
3756 result
= dns_name_settotextfilter(output_filter
);
3757 check_result(result
, "dns_name_settotextfilter");
3761 output_filter(isc_buffer_t
*buffer
, unsigned int used_org
,
3762 isc_boolean_t absolute
)
3764 char tmp1
[MAXDLEN
], tmp2
[MAXDLEN
];
3765 size_t fromlen
, tolen
;
3766 isc_boolean_t end_with_dot
;
3769 * Copy contents of 'buffer' to 'tmp1', supply trailing dot
3770 * if 'absolute' is true, and terminate with NUL.
3772 fromlen
= isc_buffer_usedlength(buffer
) - used_org
;
3773 if (fromlen
>= MAXDLEN
)
3774 return (ISC_R_SUCCESS
);
3775 memcpy(tmp1
, (char *)isc_buffer_base(buffer
) + used_org
, fromlen
);
3776 end_with_dot
= (tmp1
[fromlen
- 1] == '.') ? ISC_TRUE
: ISC_FALSE
;
3777 if (absolute
&& !end_with_dot
) {
3779 if (fromlen
>= MAXDLEN
)
3780 return (ISC_R_SUCCESS
);
3781 tmp1
[fromlen
- 1] = '.';
3783 tmp1
[fromlen
] = '\0';
3786 * Convert contents of 'tmp1' to local encoding.
3788 if (idn_decodename(IDN_DECODE_APP
, tmp1
, tmp2
, MAXDLEN
) != idn_success
)
3789 return (ISC_R_SUCCESS
);
3793 * Copy the converted contents in 'tmp1' back to 'buffer'.
3794 * If we have appended trailing dot, remove it.
3796 tolen
= strlen(tmp1
);
3797 if (absolute
&& !end_with_dot
&& tmp1
[tolen
- 1] == '.')
3800 if (isc_buffer_length(buffer
) < used_org
+ tolen
)
3801 return (ISC_R_NOSPACE
);
3803 isc_buffer_subtract(buffer
, isc_buffer_usedlength(buffer
) - used_org
);
3804 memcpy(isc_buffer_used(buffer
), tmp1
, tolen
);
3805 isc_buffer_add(buffer
, tolen
);
3807 return (ISC_R_SUCCESS
);
3811 append_textname(char *name
, const char *origin
, size_t namesize
) {
3812 size_t namelen
= strlen(name
);
3813 size_t originlen
= strlen(origin
);
3815 /* Already absolute? */
3816 if (namelen
> 0 && name
[namelen
- 1] == '.')
3819 /* Append dot and origin */
3821 if (namelen
+ 1 + originlen
>= namesize
)
3822 return idn_buffer_overflow
;
3824 name
[namelen
++] = '.';
3825 (void)strcpy(name
+ namelen
, origin
);
3830 idn_check_result(idn_result_t r
, const char *msg
) {
3831 if (r
!= idn_success
) {
3833 fatal("%s: %s", msg
, idn_result_tostring(r
));
3836 #endif /* WITH_IDN */
3840 print_type(dns_rdatatype_t type
)
3842 isc_buffer_t
* b
= NULL
;
3843 isc_result_t result
;
3846 result
= isc_buffer_allocate(mctx
, &b
, 4000);
3847 check_result(result
, "isc_buffer_allocate");
3849 result
= dns_rdatatype_totext(type
, b
);
3850 check_result(result
, "print_type");
3852 isc_buffer_usedregion(b
, &r
);
3853 r
.base
[r
.length
] = '\0';
3855 printf("%s", r
.base
);
3857 isc_buffer_free(&b
);
3861 dump_database_section(dns_message_t
*msg
, int section
)
3863 dns_name_t
*msg_name
=NULL
;
3865 dns_rdataset_t
*rdataset
;
3868 dns_message_currentname(msg
, section
, &msg_name
);
3870 for (rdataset
= ISC_LIST_HEAD(msg_name
->list
); rdataset
!= NULL
;
3871 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3872 dns_name_print(msg_name
, stdout
);
3874 print_rdataset(msg_name
, rdataset
, mctx
);
3878 } while (dns_message_nextname(msg
, section
) == ISC_R_SUCCESS
);
3882 dump_database(void) {
3883 dig_message_t
* msg
;
3885 for (msg
= ISC_LIST_HEAD(chase_message_list
); msg
!= NULL
;
3886 msg
= ISC_LIST_NEXT(msg
, link
)) {
3887 if (dns_message_firstname(msg
->msg
, DNS_SECTION_ANSWER
)
3889 dump_database_section(msg
->msg
, DNS_SECTION_ANSWER
);
3891 if (dns_message_firstname(msg
->msg
, DNS_SECTION_AUTHORITY
)
3893 dump_database_section(msg
->msg
, DNS_SECTION_AUTHORITY
);
3895 if (dns_message_firstname(msg
->msg
, DNS_SECTION_ADDITIONAL
)
3897 dump_database_section(msg
->msg
, DNS_SECTION_ADDITIONAL
);
3903 search_type(dns_name_t
*name
, dns_rdatatype_t type
, dns_rdatatype_t covers
) {
3904 dns_rdataset_t
*rdataset
;
3905 dns_rdata_sig_t siginfo
;
3906 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
3907 isc_result_t result
;
3909 for (rdataset
= ISC_LIST_HEAD(name
->list
); rdataset
!= NULL
;
3910 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3911 if (type
== dns_rdatatype_any
) {
3912 if (rdataset
->type
!= dns_rdatatype_rrsig
)
3914 } else if ((type
== dns_rdatatype_rrsig
) &&
3915 (rdataset
->type
== dns_rdatatype_rrsig
)) {
3916 result
= dns_rdataset_first(rdataset
);
3917 check_result(result
, "empty rdataset");
3918 dns_rdataset_current(rdataset
, &sigrdata
);
3919 result
= dns_rdata_tostruct(&sigrdata
, &siginfo
, NULL
);
3920 check_result(result
, "sigrdata tostruct siginfo");
3922 if ((siginfo
.covered
== covers
) ||
3923 (covers
== dns_rdatatype_any
)) {
3924 dns_rdata_reset(&sigrdata
);
3925 dns_rdata_freestruct(&siginfo
);
3928 dns_rdata_reset(&sigrdata
);
3929 dns_rdata_freestruct(&siginfo
);
3930 } else if (rdataset
->type
== type
)
3937 chase_scanname_section(dns_message_t
*msg
, dns_name_t
*name
,
3938 dns_rdatatype_t type
, dns_rdatatype_t covers
,
3941 dns_rdataset_t
*rdataset
;
3942 dns_name_t
*msg_name
= NULL
;
3945 dns_message_currentname(msg
, section
, &msg_name
);
3946 if (dns_name_compare(msg_name
, name
) == 0) {
3947 rdataset
= search_type(msg_name
, type
, covers
);
3948 if (rdataset
!= NULL
)
3952 } while (dns_message_nextname(msg
, section
) == ISC_R_SUCCESS
);
3959 chase_scanname(dns_name_t
*name
, dns_rdatatype_t type
, dns_rdatatype_t covers
)
3961 dns_rdataset_t
*rdataset
= NULL
;
3962 dig_message_t
* msg
;
3964 for (msg
= ISC_LIST_HEAD(chase_message_list2
); msg
!= NULL
;
3965 msg
= ISC_LIST_NEXT(msg
, link
)) {
3966 if (dns_message_firstname(msg
->msg
, DNS_SECTION_ANSWER
)
3968 rdataset
= chase_scanname_section(msg
->msg
, name
,
3970 DNS_SECTION_ANSWER
);
3971 if (rdataset
!= NULL
)
3973 if (dns_message_firstname(msg
->msg
, DNS_SECTION_AUTHORITY
)
3976 chase_scanname_section(msg
->msg
, name
,
3978 DNS_SECTION_AUTHORITY
);
3979 if (rdataset
!= NULL
)
3981 if (dns_message_firstname(msg
->msg
, DNS_SECTION_ADDITIONAL
)
3984 chase_scanname_section(msg
->msg
, name
, type
,
3986 DNS_SECTION_ADDITIONAL
);
3987 if (rdataset
!= NULL
)
3995 sigchase_scanname(dns_rdatatype_t type
, dns_rdatatype_t covers
,
3996 isc_boolean_t
* lookedup
, dns_name_t
*rdata_name
)
3998 dig_lookup_t
*lookup
;
3999 isc_buffer_t
*b
= NULL
;
4001 isc_result_t result
;
4002 dns_rdataset_t
* temp
;
4003 dns_rdatatype_t querytype
;
4005 temp
= chase_scanname(rdata_name
, type
, covers
);
4009 if (*lookedup
== ISC_TRUE
)
4012 lookup
= clone_lookup(current_lookup
, ISC_TRUE
);
4013 lookup
->trace_root
= ISC_FALSE
;
4014 lookup
->new_search
= ISC_TRUE
;
4016 result
= isc_buffer_allocate(mctx
, &b
, BUFSIZE
);
4017 check_result(result
, "isc_buffer_allocate");
4018 result
= dns_name_totext(rdata_name
, ISC_FALSE
, b
);
4019 check_result(result
, "dns_name_totext");
4020 isc_buffer_usedregion(b
, &r
);
4021 r
.base
[r
.length
] = '\0';
4022 strcpy(lookup
->textname
, (char*)r
.base
);
4023 isc_buffer_free(&b
);
4025 if (type
== dns_rdatatype_rrsig
)
4030 if (querytype
== 0 || querytype
== 255) {
4031 printf("Error in the queried type: %d\n", querytype
);
4035 lookup
->rdtype
= querytype
;
4036 lookup
->rdtypeset
= ISC_TRUE
;
4037 lookup
->qrdtype
= querytype
;
4038 *lookedup
= ISC_TRUE
;
4040 ISC_LIST_APPEND(lookup_list
, lookup
, link
);
4041 printf("\n\nLaunch a query to find a RRset of type ");
4043 printf(" for zone: %s\n", lookup
->textname
);
4048 insert_trustedkey(dst_key_t
* key
)
4052 if (tk_list
.nb_tk
>= MAX_TRUSTED_KEY
)
4055 tk_list
.key
[tk_list
.nb_tk
++] = key
;
4064 for (i
= 0; i
< MAX_TRUSTED_KEY
; i
++) {
4065 if (tk_list
.key
[i
] != NULL
) {
4066 dst_key_free(&tk_list
.key
[i
]);
4067 tk_list
.key
[i
] = NULL
;
4076 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
4079 removetmpkey(isc_mem_t
*mctx
, const char *file
)
4081 char *tempnamekey
= NULL
;
4083 isc_result_t result
;
4085 tempnamekeylen
= strlen(file
)+10;
4087 tempnamekey
= isc_mem_allocate(mctx
, tempnamekeylen
);
4088 if (tempnamekey
== NULL
)
4089 return (ISC_R_NOMEMORY
);
4091 memset(tempnamekey
, 0, tempnamekeylen
);
4093 strcat(tempnamekey
, file
);
4094 strcat(tempnamekey
,".key");
4095 isc_file_remove(tempnamekey
);
4097 result
= isc_file_remove(tempnamekey
);
4098 isc_mem_free(mctx
, tempnamekey
);
4103 opentmpkey(isc_mem_t
*mctx
, const char *file
, char **tempp
, FILE **fp
) {
4105 isc_result_t result
;
4106 char *tempname
= NULL
;
4107 char *tempnamekey
= NULL
;
4115 tempnamelen
= strlen(file
) + 20;
4116 tempname
= isc_mem_allocate(mctx
, tempnamelen
);
4117 if (tempname
== NULL
)
4118 return (ISC_R_NOMEMORY
);
4119 memset(tempname
, 0, tempnamelen
);
4121 result
= isc_file_mktemplate(file
, tempname
, tempnamelen
);
4122 if (result
!= ISC_R_SUCCESS
)
4128 if (cp
== tempname
) {
4129 isc_mem_free(mctx
, tempname
);
4130 return (ISC_R_FAILURE
);
4134 while (cp
>= tempname
&& *cp
== 'X') {
4135 isc_random_get(&which
);
4136 *cp
= alphnum
[which
% (sizeof(alphnum
) - 1)];
4140 tempnamekeylen
= tempnamelen
+5;
4141 tempnamekey
= isc_mem_allocate(mctx
, tempnamekeylen
);
4142 if (tempnamekey
== NULL
)
4143 return (ISC_R_NOMEMORY
);
4145 memset(tempnamekey
, 0, tempnamekeylen
);
4146 strncpy(tempnamekey
, tempname
, tempnamelen
);
4147 strcat(tempnamekey
,".key");
4150 if (isc_file_exists(tempnamekey
)) {
4151 isc_mem_free(mctx
, tempnamekey
);
4152 isc_mem_free(mctx
, tempname
);
4156 if ((f
= fopen(tempnamekey
, "w")) == NULL
) {
4157 printf("get_trusted_key(): trusted key not found %s\n",
4159 return (ISC_R_FAILURE
);
4163 isc_mem_free(mctx
, tempnamekey
);
4166 return (ISC_R_SUCCESS
);
4169 isc_mem_free(mctx
, tempname
);
4176 get_trusted_key(isc_mem_t
*mctx
)
4178 isc_result_t result
;
4179 const char *filename
= NULL
;
4180 char *filetemp
= NULL
;
4183 dst_key_t
*key
= NULL
;
4185 result
= isc_file_exists(trustedkey
);
4186 if (result
!= ISC_TRUE
) {
4187 result
= isc_file_exists("/etc/trusted-key.key");
4188 if (result
!= ISC_TRUE
) {
4189 result
= isc_file_exists("./trusted-key.key");
4190 if (result
!= ISC_TRUE
)
4191 return (ISC_R_FAILURE
);
4193 filename
= "./trusted-key.key";
4195 filename
= "/etc/trusted-key.key";
4197 filename
= trustedkey
;
4199 if (filename
== NULL
) {
4200 printf("No trusted key\n");
4201 return (ISC_R_FAILURE
);
4204 if ((fp
= fopen(filename
, "r")) == NULL
) {
4205 printf("get_trusted_key(): trusted key not found %s\n",
4207 return (ISC_R_FAILURE
);
4209 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
4210 result
= opentmpkey(mctx
,"tmp_file", &filetemp
, &fptemp
);
4211 if (result
!= ISC_R_SUCCESS
) {
4213 return (ISC_R_FAILURE
);
4215 if (fputs(buf
, fptemp
) < 0) {
4218 return (ISC_R_FAILURE
);
4221 result
= dst_key_fromnamedfile(filetemp
, NULL
, DST_TYPE_PUBLIC
,
4223 removetmpkey(mctx
, filetemp
);
4224 isc_mem_free(mctx
, filetemp
);
4225 if (result
!= ISC_R_SUCCESS
) {
4227 return (ISC_R_FAILURE
);
4229 insert_trustedkey(key
);
4231 dst_key_tofile(key
, DST_TYPE_PUBLIC
,"/tmp");
4235 return (ISC_R_SUCCESS
);
4240 nameFromString(const char *str
, dns_name_t
*p_ret
) {
4241 size_t len
= strlen(str
);
4242 isc_result_t result
;
4243 isc_buffer_t buffer
;
4244 dns_fixedname_t fixedname
;
4246 REQUIRE(p_ret
!= NULL
);
4247 REQUIRE(str
!= NULL
);
4249 isc_buffer_init(&buffer
, str
, len
);
4250 isc_buffer_add(&buffer
, len
);
4252 dns_fixedname_init(&fixedname
);
4253 result
= dns_name_fromtext(dns_fixedname_name(&fixedname
), &buffer
,
4254 dns_rootname
, DNS_NAME_DOWNCASE
, NULL
);
4255 check_result(result
, "nameFromString");
4257 if (dns_name_dynamic(p_ret
))
4258 free_name(p_ret
, mctx
);
4260 result
= dns_name_dup(dns_fixedname_name(&fixedname
), mctx
, p_ret
);
4261 check_result(result
, "nameFromString");
4267 prepare_lookup(dns_name_t
*name
)
4269 isc_result_t result
;
4270 dig_lookup_t
*lookup
= NULL
;
4274 lookup
= clone_lookup(current_lookup
, ISC_TRUE
);
4275 lookup
->trace_root
= ISC_FALSE
;
4276 lookup
->new_search
= ISC_TRUE
;
4277 lookup
->trace_root_sigchase
= ISC_FALSE
;
4279 strncpy(lookup
->textname
, lookup
->textnamesigchase
, MXNAME
);
4281 lookup
->rdtype
= lookup
->rdtype_sigchase
;
4282 lookup
->rdtypeset
= ISC_TRUE
;
4283 lookup
->qrdtype
= lookup
->qrdtype_sigchase
;
4285 s
= ISC_LIST_HEAD(lookup
->my_server_list
);
4287 debug("freeing server %p belonging to %p",
4290 s
= ISC_LIST_NEXT(s
, link
);
4291 ISC_LIST_DEQUEUE(lookup
->my_server_list
,
4292 (dig_server_t
*)ptr
, link
);
4293 isc_mem_free(mctx
, ptr
);
4297 for (result
= dns_rdataset_first(chase_nsrdataset
);
4298 result
== ISC_R_SUCCESS
;
4299 result
= dns_rdataset_next(chase_nsrdataset
)) {
4300 char namestr
[DNS_NAME_FORMATSIZE
];
4302 dns_rdata_t rdata
= DNS_RDATA_INIT
;
4303 dig_server_t
* srv
= NULL
;
4304 #define __FOLLOW_GLUE__
4305 #ifdef __FOLLOW_GLUE__
4306 isc_buffer_t
*b
= NULL
;
4307 isc_result_t result
;
4309 dns_rdataset_t
*rdataset
= NULL
;
4310 isc_boolean_t
true = ISC_TRUE
;
4313 memset(namestr
, 0, DNS_NAME_FORMATSIZE
);
4315 dns_rdataset_current(chase_nsrdataset
, &rdata
);
4317 result
= dns_rdata_tostruct(&rdata
, &ns
, NULL
);
4318 check_result(result
, "dns_rdata_tostruct");
4320 #ifdef __FOLLOW_GLUE__
4322 result
= advanced_rrsearch(&rdataset
, &ns
.name
,
4324 dns_rdatatype_any
, &true);
4325 if (result
== ISC_R_SUCCESS
) {
4326 for (result
= dns_rdataset_first(rdataset
);
4327 result
== ISC_R_SUCCESS
;
4328 result
= dns_rdataset_next(rdataset
)) {
4329 dns_rdata_t aaaa
= DNS_RDATA_INIT
;
4330 dns_rdataset_current(rdataset
, &aaaa
);
4332 result
= isc_buffer_allocate(mctx
, &b
, 80);
4333 check_result(result
, "isc_buffer_allocate");
4335 dns_rdata_totext(&aaaa
, &ns
.name
, b
);
4336 isc_buffer_usedregion(b
, &r
);
4337 r
.base
[r
.length
] = '\0';
4338 strncpy(namestr
, (char*)r
.base
,
4339 DNS_NAME_FORMATSIZE
);
4340 isc_buffer_free(&b
);
4341 dns_rdata_reset(&aaaa
);
4344 srv
= make_server(namestr
, namestr
);
4346 ISC_LIST_APPEND(lookup
->my_server_list
,
4352 result
= advanced_rrsearch(&rdataset
, &ns
.name
, dns_rdatatype_a
,
4353 dns_rdatatype_any
, &true);
4354 if (result
== ISC_R_SUCCESS
) {
4355 for (result
= dns_rdataset_first(rdataset
);
4356 result
== ISC_R_SUCCESS
;
4357 result
= dns_rdataset_next(rdataset
)) {
4358 dns_rdata_t a
= DNS_RDATA_INIT
;
4359 dns_rdataset_current(rdataset
, &a
);
4361 result
= isc_buffer_allocate(mctx
, &b
, 80);
4362 check_result(result
, "isc_buffer_allocate");
4364 dns_rdata_totext(&a
, &ns
.name
, b
);
4365 isc_buffer_usedregion(b
, &r
);
4366 r
.base
[r
.length
] = '\0';
4367 strncpy(namestr
, (char*)r
.base
,
4368 DNS_NAME_FORMATSIZE
);
4369 isc_buffer_free(&b
);
4370 dns_rdata_reset(&a
);
4371 printf("ns name: %s\n", namestr
);
4374 srv
= make_server(namestr
, namestr
);
4376 ISC_LIST_APPEND(lookup
->my_server_list
,
4382 dns_name_format(&ns
.name
, namestr
, sizeof(namestr
));
4383 printf("ns name: ");
4384 dns_name_print(&ns
.name
, stdout
);
4386 srv
= make_server(namestr
, namestr
);
4388 ISC_LIST_APPEND(lookup
->my_server_list
, srv
, link
);
4391 dns_rdata_freestruct(&ns
);
4392 dns_rdata_reset(&rdata
);
4396 ISC_LIST_APPEND(lookup_list
, lookup
, link
);
4397 printf("\nLaunch a query to find a RRset of type ");
4398 print_type(lookup
->rdtype
);
4399 printf(" for zone: %s", lookup
->textname
);
4400 printf(" with nameservers:");
4402 print_rdataset(name
, chase_nsrdataset
, mctx
);
4403 return (ISC_R_SUCCESS
);
4408 child_of_zone(dns_name_t
* name
, dns_name_t
* zone_name
,
4409 dns_name_t
* child_name
)
4411 dns_namereln_t name_reln
;
4413 unsigned int nlabelsp
;
4415 name_reln
= dns_name_fullcompare(name
, zone_name
, &orderp
, &nlabelsp
);
4416 if (name_reln
!= dns_namereln_subdomain
||
4417 dns_name_countlabels(name
) <= dns_name_countlabels(zone_name
) + 1) {
4418 printf("\n;; ERROR : ");
4419 dns_name_print(name
, stdout
);
4420 printf(" is not a subdomain of: ");
4421 dns_name_print(zone_name
, stdout
);
4422 printf(" FAILED\n\n");
4423 return (ISC_R_FAILURE
);
4426 dns_name_getlabelsequence(name
,
4427 dns_name_countlabels(name
) -
4428 dns_name_countlabels(zone_name
) -1,
4429 dns_name_countlabels(zone_name
) +1,
4431 return (ISC_R_SUCCESS
);
4435 grandfather_pb_test(dns_name_t
*zone_name
, dns_rdataset_t
*sigrdataset
)
4437 isc_result_t result
;
4438 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
4439 dns_rdata_sig_t siginfo
;
4441 result
= dns_rdataset_first(sigrdataset
);
4442 check_result(result
, "empty RRSIG dataset");
4443 dns_rdata_init(&sigrdata
);
4446 dns_rdataset_current(sigrdataset
, &sigrdata
);
4448 result
= dns_rdata_tostruct(&sigrdata
, &siginfo
, NULL
);
4449 check_result(result
, "sigrdata tostruct siginfo");
4451 if (dns_name_compare(&siginfo
.signer
, zone_name
) == 0) {
4452 dns_rdata_freestruct(&siginfo
);
4453 dns_rdata_reset(&sigrdata
);
4454 return (ISC_R_SUCCESS
);
4457 dns_rdata_freestruct(&siginfo
);
4458 dns_rdata_reset(&sigrdata
);
4460 } while (dns_rdataset_next(chase_sigkeyrdataset
) == ISC_R_SUCCESS
);
4462 dns_rdata_reset(&sigrdata
);
4464 return (ISC_R_FAILURE
);
4469 initialization(dns_name_t
*name
)
4471 isc_result_t result
;
4472 isc_boolean_t
true = ISC_TRUE
;
4474 chase_nsrdataset
= NULL
;
4475 result
= advanced_rrsearch(&chase_nsrdataset
, name
, dns_rdatatype_ns
,
4476 dns_rdatatype_any
, &true);
4477 if (result
!= ISC_R_SUCCESS
) {
4478 printf("\n;; NS RRset is missing to continue validation:"
4480 return (ISC_R_FAILURE
);
4482 INSIST(chase_nsrdataset
!= NULL
);
4483 prepare_lookup(name
);
4485 dup_name(name
, &chase_current_name
, mctx
);
4487 return (ISC_R_SUCCESS
);
4492 print_rdataset(dns_name_t
*name
, dns_rdataset_t
*rdataset
, isc_mem_t
*mctx
)
4494 isc_buffer_t
*b
= NULL
;
4495 isc_result_t result
;
4498 result
= isc_buffer_allocate(mctx
, &b
, 9000);
4499 check_result(result
, "isc_buffer_allocate");
4501 printrdataset(name
, rdataset
, b
);
4503 isc_buffer_usedregion(b
, &r
);
4504 r
.base
[r
.length
] = '\0';
4507 printf("%s\n", r
.base
);
4509 isc_buffer_free(&b
);
4514 dup_name(dns_name_t
*source
, dns_name_t
*target
, isc_mem_t
*mctx
) {
4515 isc_result_t result
;
4517 if (dns_name_dynamic(target
))
4518 free_name(target
, mctx
);
4519 result
= dns_name_dup(source
, mctx
, target
);
4520 check_result(result
, "dns_name_dup");
4524 free_name(dns_name_t
*name
, isc_mem_t
*mctx
) {
4525 dns_name_free(name
, mctx
);
4526 dns_name_init(name
, NULL
);
4531 * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter
4532 * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key
4533 * and the RRset is valid
4534 * return ISC_R_NOTFOUND if not contains trusted key
4535 or if the RRset isn't valid
4536 * return ISC_R_FAILURE if problem
4540 contains_trusted_key(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
4541 dns_rdataset_t
*sigrdataset
,
4544 isc_result_t result
;
4545 dns_rdata_t rdata
= DNS_RDATA_INIT
;
4546 dst_key_t
*trustedKey
= NULL
;
4547 dst_key_t
*dnsseckey
= NULL
;
4550 if (name
== NULL
|| rdataset
== NULL
)
4551 return (ISC_R_FAILURE
);
4553 result
= dns_rdataset_first(rdataset
);
4554 check_result(result
, "empty rdataset");
4557 dns_rdataset_current(rdataset
, &rdata
);
4558 INSIST(rdata
.type
== dns_rdatatype_dnskey
);
4560 result
= dns_dnssec_keyfromrdata(name
, &rdata
,
4562 check_result(result
, "dns_dnssec_keyfromrdata");
4565 for (i
= 0; i
< tk_list
.nb_tk
; i
++) {
4566 if (dst_key_compare(tk_list
.key
[i
], dnsseckey
)
4568 dns_rdata_reset(&rdata
);
4570 printf(";; Ok, find a Trusted Key in the "
4571 "DNSKEY RRset: %d\n",
4572 dst_key_id(dnsseckey
));
4573 if (sigchase_verify_sig_key(name
, rdataset
,
4578 dst_key_free(&dnsseckey
);
4580 return (ISC_R_SUCCESS
);
4585 dns_rdata_reset(&rdata
);
4586 if (dnsseckey
!= NULL
)
4587 dst_key_free(&dnsseckey
);
4588 } while (dns_rdataset_next(rdataset
) == ISC_R_SUCCESS
);
4590 if (trustedKey
!= NULL
)
4591 dst_key_free(&trustedKey
);
4594 return (ISC_R_NOTFOUND
);
4598 sigchase_verify_sig(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
4599 dns_rdataset_t
*keyrdataset
,
4600 dns_rdataset_t
*sigrdataset
,
4603 isc_result_t result
;
4604 dns_rdata_t keyrdata
= DNS_RDATA_INIT
;
4605 dst_key_t
*dnsseckey
= NULL
;
4607 result
= dns_rdataset_first(keyrdataset
);
4608 check_result(result
, "empty DNSKEY dataset");
4609 dns_rdata_init(&keyrdata
);
4612 dns_rdataset_current(keyrdataset
, &keyrdata
);
4613 INSIST(keyrdata
.type
== dns_rdatatype_dnskey
);
4615 result
= dns_dnssec_keyfromrdata(name
, &keyrdata
,
4617 check_result(result
, "dns_dnssec_keyfromrdata");
4619 result
= sigchase_verify_sig_key(name
, rdataset
, dnsseckey
,
4621 if (result
== ISC_R_SUCCESS
) {
4622 dns_rdata_reset(&keyrdata
);
4623 dst_key_free(&dnsseckey
);
4624 return (ISC_R_SUCCESS
);
4626 dst_key_free(&dnsseckey
);
4627 dns_rdata_reset(&keyrdata
);
4628 } while (dns_rdataset_next(chase_keyrdataset
) == ISC_R_SUCCESS
);
4630 dns_rdata_reset(&keyrdata
);
4632 return (ISC_R_NOTFOUND
);
4636 sigchase_verify_sig_key(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
4637 dst_key_t
*dnsseckey
, dns_rdataset_t
*sigrdataset
,
4640 isc_result_t result
;
4641 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
4642 dns_rdata_sig_t siginfo
;
4644 result
= dns_rdataset_first(sigrdataset
);
4645 check_result(result
, "empty RRSIG dataset");
4646 dns_rdata_init(&sigrdata
);
4649 dns_rdataset_current(sigrdataset
, &sigrdata
);
4651 result
= dns_rdata_tostruct(&sigrdata
, &siginfo
, NULL
);
4652 check_result(result
, "sigrdata tostruct siginfo");
4655 * Test if the id of the DNSKEY is
4656 * the id of the DNSKEY signer's
4658 if (siginfo
.keyid
== dst_key_id(dnsseckey
)) {
4660 result
= dns_rdataset_first(rdataset
);
4661 check_result(result
, "empty DS dataset");
4663 result
= dns_dnssec_verify(name
, rdataset
, dnsseckey
,
4664 ISC_FALSE
, mctx
, &sigrdata
);
4666 printf(";; VERIFYING ");
4667 print_type(rdataset
->type
);
4668 printf(" RRset for ");
4669 dns_name_print(name
, stdout
);
4670 printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey
),
4671 isc_result_totext(result
));
4673 if (result
== ISC_R_SUCCESS
) {
4674 dns_rdata_reset(&sigrdata
);
4678 dns_rdata_freestruct(&siginfo
);
4679 dns_rdata_reset(&sigrdata
);
4681 } while (dns_rdataset_next(chase_sigkeyrdataset
) == ISC_R_SUCCESS
);
4683 dns_rdata_reset(&sigrdata
);
4685 return (ISC_R_NOTFOUND
);
4690 sigchase_verify_ds(dns_name_t
*name
, dns_rdataset_t
*keyrdataset
,
4691 dns_rdataset_t
*dsrdataset
, isc_mem_t
*mctx
)
4693 isc_result_t result
;
4694 dns_rdata_t keyrdata
= DNS_RDATA_INIT
;
4695 dns_rdata_t newdsrdata
= DNS_RDATA_INIT
;
4696 dns_rdata_t dsrdata
= DNS_RDATA_INIT
;
4697 dns_rdata_ds_t dsinfo
;
4698 dst_key_t
*dnsseckey
= NULL
;
4699 unsigned char dsbuf
[DNS_DS_BUFFERSIZE
];
4701 result
= dns_rdataset_first(dsrdataset
);
4702 check_result(result
, "empty DSset dataset");
4704 dns_rdataset_current(dsrdataset
, &dsrdata
);
4706 result
= dns_rdata_tostruct(&dsrdata
, &dsinfo
, NULL
);
4707 check_result(result
, "dns_rdata_tostruct for DS");
4709 result
= dns_rdataset_first(keyrdataset
);
4710 check_result(result
, "empty KEY dataset");
4713 dns_rdataset_current(keyrdataset
, &keyrdata
);
4714 INSIST(keyrdata
.type
== dns_rdatatype_dnskey
);
4716 result
= dns_dnssec_keyfromrdata(name
, &keyrdata
,
4718 check_result(result
, "dns_dnssec_keyfromrdata");
4721 * Test if the id of the DNSKEY is the
4722 * id of DNSKEY referenced by the DS
4724 if (dsinfo
.key_tag
== dst_key_id(dnsseckey
)) {
4726 result
= dns_ds_buildrdata(name
, &keyrdata
,
4728 dsbuf
, &newdsrdata
);
4729 dns_rdata_freestruct(&dsinfo
);
4731 if (result
!= ISC_R_SUCCESS
) {
4732 dns_rdata_reset(&keyrdata
);
4733 dns_rdata_reset(&newdsrdata
);
4734 dns_rdata_reset(&dsrdata
);
4735 dst_key_free(&dnsseckey
);
4736 dns_rdata_freestruct(&dsinfo
);
4737 printf("Oops: impossible to build"
4743 if (dns_rdata_compare(&dsrdata
,
4744 &newdsrdata
) == 0) {
4745 printf(";; OK a DS valids a DNSKEY"
4747 printf(";; Now verify that this"
4748 " DNSKEY validates the "
4751 result
= sigchase_verify_sig_key(name
,
4754 chase_sigkeyrdataset
,
4756 if (result
== ISC_R_SUCCESS
) {
4757 dns_rdata_reset(&keyrdata
);
4758 dns_rdata_reset(&newdsrdata
);
4759 dns_rdata_reset(&dsrdata
);
4760 dst_key_free(&dnsseckey
);
4765 printf(";; This DS is NOT the DS for"
4766 " the chasing KEY: FAILED\n");
4769 dns_rdata_reset(&newdsrdata
);
4771 dst_key_free(&dnsseckey
);
4772 dns_rdata_reset(&keyrdata
);
4774 } while (dns_rdataset_next(chase_keyrdataset
) == ISC_R_SUCCESS
);
4775 dns_rdata_reset(&dsrdata
);
4777 } while (dns_rdataset_next(chase_dsrdataset
) == ISC_R_SUCCESS
);
4779 dns_rdata_reset(&keyrdata
);
4780 dns_rdata_reset(&newdsrdata
);
4781 dns_rdata_reset(&dsrdata
);
4783 return (ISC_R_NOTFOUND
);
4788 * take a pointer on a rdataset in parameter and try to resolv it.
4789 * the searched rrset is a rrset on 'name' with type 'type'
4790 * (and if the type is a rrsig the signature cover 'covers').
4791 * the lookedup is to known if you have already done the query on the net.
4792 * ISC_R_SUCCESS: if we found the rrset
4793 * ISC_R_NOTFOUND: we do not found the rrset in cache
4794 * and we do a query on the net
4795 * ISC_R_FAILURE: rrset not found
4798 advanced_rrsearch(dns_rdataset_t
**rdataset
, dns_name_t
*name
,
4799 dns_rdatatype_t type
, dns_rdatatype_t covers
,
4800 isc_boolean_t
*lookedup
)
4802 isc_boolean_t tmplookedup
;
4804 INSIST(rdataset
!= NULL
);
4806 if (*rdataset
!= NULL
)
4807 return (ISC_R_SUCCESS
);
4809 tmplookedup
= *lookedup
;
4810 if ((*rdataset
= sigchase_scanname(type
, covers
,
4811 lookedup
, name
)) == NULL
) {
4813 return (ISC_R_FAILURE
);
4814 return (ISC_R_NOTFOUND
);
4816 *lookedup
= ISC_FALSE
;
4817 return (ISC_R_SUCCESS
);
4824 sigchase_td(dns_message_t
*msg
)
4826 isc_result_t result
;
4827 dns_name_t
*name
= NULL
;
4828 isc_boolean_t have_answer
= ISC_FALSE
;
4829 isc_boolean_t
true = ISC_TRUE
;
4831 if ((result
= dns_message_firstname(msg
, DNS_SECTION_ANSWER
))
4833 dns_message_currentname(msg
, DNS_SECTION_ANSWER
, &name
);
4834 if (current_lookup
->trace_root_sigchase
) {
4835 initialization(name
);
4840 if (!current_lookup
->trace_root_sigchase
) {
4841 result
= dns_message_firstname(msg
,
4842 DNS_SECTION_AUTHORITY
);
4843 if (result
== ISC_R_SUCCESS
)
4844 dns_message_currentname(msg
,
4845 DNS_SECTION_AUTHORITY
,
4848 = chase_scanname_section(msg
, name
,
4851 DNS_SECTION_AUTHORITY
);
4852 dup_name(name
, &chase_authority_name
, mctx
);
4853 if (chase_nsrdataset
!= NULL
) {
4854 have_delegation_ns
= ISC_TRUE
;
4855 printf("no response but there is a delegation"
4856 " in authority section:");
4857 dns_name_print(name
, stdout
);
4860 printf("no response and no delegation in "
4861 "authority section but a reference"
4863 dns_name_print(name
, stdout
);
4865 error_message
= msg
;
4868 printf(";; NO ANSWERS: %s\n",
4869 isc_result_totext(result
));
4870 free_name(&chase_name
, mctx
);
4879 = chase_scanname_section(msg
, &chase_name
,
4883 DNS_SECTION_ANSWER
);
4884 if (chase_rdataset
!= NULL
)
4885 have_response
= ISC_TRUE
;
4888 result
= advanced_rrsearch(&chase_keyrdataset
,
4889 &chase_current_name
,
4890 dns_rdatatype_dnskey
,
4892 &chase_keylookedup
);
4893 if (result
== ISC_R_FAILURE
) {
4894 printf("\n;; DNSKEY is missing to continue validation:"
4898 if (result
== ISC_R_NOTFOUND
)
4900 INSIST(chase_keyrdataset
!= NULL
);
4901 printf("\n;; DNSKEYset:\n");
4902 print_rdataset(&chase_current_name
, chase_keyrdataset
, mctx
);
4905 result
= advanced_rrsearch(&chase_sigkeyrdataset
,
4906 &chase_current_name
,
4907 dns_rdatatype_rrsig
,
4908 dns_rdatatype_dnskey
,
4909 &chase_sigkeylookedup
);
4910 if (result
== ISC_R_FAILURE
) {
4911 printf("\n;; RRSIG of DNSKEY is missing to continue validation:"
4915 if (result
== ISC_R_NOTFOUND
)
4917 INSIST(chase_sigkeyrdataset
!= NULL
);
4918 printf("\n;; RRSIG of the DNSKEYset:\n");
4919 print_rdataset(&chase_current_name
, chase_sigkeyrdataset
, mctx
);
4922 if (!chase_dslookedup
&& !chase_nslookedup
) {
4923 if (!delegation_follow
) {
4924 result
= contains_trusted_key(&chase_current_name
,
4926 chase_sigkeyrdataset
,
4929 INSIST(chase_dsrdataset
!= NULL
);
4930 INSIST(chase_sigdsrdataset
!= NULL
);
4931 result
= sigchase_verify_ds(&chase_current_name
,
4937 if (result
!= ISC_R_SUCCESS
) {
4938 printf("\n;; chain of trust can't be validated:"
4942 chase_dsrdataset
= NULL
;
4943 chase_sigdsrdataset
= NULL
;
4947 if (have_response
|| (!have_delegation_ns
&& !have_response
)) {
4948 /* test if it's a grand father case */
4950 if (have_response
) {
4951 result
= advanced_rrsearch(&chase_sigrdataset
,
4953 dns_rdatatype_rrsig
,
4957 if (result
== ISC_R_FAILURE
) {
4958 printf("\n;; RRset is missing to continue"
4959 " validation SHOULD NOT APPEND:"
4965 result
= advanced_rrsearch(&chase_sigrdataset
,
4966 &chase_authority_name
,
4967 dns_rdatatype_rrsig
,
4970 if (result
== ISC_R_FAILURE
) {
4971 printf("\n;; RRSIG is missing to continue"
4972 " validation SHOULD NOT APPEND:"
4977 result
= grandfather_pb_test(&chase_current_name
,
4979 if (result
!= ISC_R_SUCCESS
) {
4980 dns_name_t tmp_name
;
4982 printf("\n;; We are in a Grand Father Problem:"
4983 " See 2.2.1 in RFC 3568\n");
4984 chase_rdataset
= NULL
;
4985 chase_sigrdataset
= NULL
;
4986 have_response
= ISC_FALSE
;
4987 have_delegation_ns
= ISC_FALSE
;
4989 dns_name_init(&tmp_name
, NULL
);
4990 result
= child_of_zone(&chase_name
, &chase_current_name
,
4992 if (dns_name_dynamic(&chase_authority_name
))
4993 free_name(&chase_authority_name
, mctx
);
4994 dup_name(&tmp_name
, &chase_authority_name
, mctx
);
4995 printf(";; and we try to continue chain of trust"
4996 " validation of the zone: ");
4997 dns_name_print(&chase_authority_name
, stdout
);
4999 have_delegation_ns
= ISC_TRUE
;
5004 chase_sigrdataset
= NULL
;
5008 if (have_delegation_ns
) {
5009 chase_nsrdataset
= NULL
;
5010 result
= advanced_rrsearch(&chase_nsrdataset
,
5011 &chase_authority_name
,
5015 if (result
== ISC_R_FAILURE
) {
5016 printf("\n;;NSset is missing to continue validation:"
5020 if (result
== ISC_R_NOTFOUND
) {
5023 INSIST(chase_nsrdataset
!= NULL
);
5025 result
= advanced_rrsearch(&chase_dsrdataset
,
5026 &chase_authority_name
,
5030 if (result
== ISC_R_FAILURE
) {
5031 printf("\n;; DSset is missing to continue validation:"
5035 if (result
== ISC_R_NOTFOUND
)
5037 INSIST(chase_dsrdataset
!= NULL
);
5038 printf("\n;; DSset:\n");
5039 print_rdataset(&chase_authority_name
, chase_dsrdataset
, mctx
);
5041 result
= advanced_rrsearch(&chase_sigdsrdataset
,
5042 &chase_authority_name
,
5043 dns_rdatatype_rrsig
,
5046 if (result
!= ISC_R_SUCCESS
) {
5047 printf("\n;; DSset is missing to continue validation:"
5051 printf("\n;; RRSIGset of DSset\n");
5052 print_rdataset(&chase_authority_name
,
5053 chase_sigdsrdataset
, mctx
);
5054 INSIST(chase_sigdsrdataset
!= NULL
);
5056 result
= sigchase_verify_sig(&chase_authority_name
,
5059 chase_sigdsrdataset
, mctx
);
5060 if (result
!= ISC_R_SUCCESS
) {
5061 printf("\n;; Impossible to verify the DSset:"
5065 chase_keyrdataset
= NULL
;
5066 chase_sigkeyrdataset
= NULL
;
5069 prepare_lookup(&chase_authority_name
);
5071 have_response
= ISC_FALSE
;
5072 have_delegation_ns
= ISC_FALSE
;
5073 delegation_follow
= ISC_TRUE
;
5074 error_message
= NULL
;
5075 dup_name(&chase_authority_name
, &chase_current_name
, mctx
);
5076 free_name(&chase_authority_name
, mctx
);
5081 if (error_message
!= NULL
) {
5082 dns_rdataset_t
*rdataset
;
5083 dns_rdataset_t
*sigrdataset
;
5084 dns_name_t rdata_name
;
5085 isc_result_t ret
= ISC_R_FAILURE
;
5087 dns_name_init(&rdata_name
, NULL
);
5088 result
= prove_nx(error_message
, &chase_name
,
5089 current_lookup
->rdclass_sigchase
,
5090 current_lookup
->rdtype_sigchase
, &rdata_name
,
5091 &rdataset
, &sigrdataset
);
5092 if (rdataset
== NULL
|| sigrdataset
== NULL
||
5093 dns_name_countlabels(&rdata_name
) == 0) {
5094 printf("\n;; Impossible to verify the non-existence,"
5095 " the NSEC RRset can't be validated:"
5099 ret
= sigchase_verify_sig(&rdata_name
, rdataset
,
5102 if (ret
!= ISC_R_SUCCESS
) {
5103 free_name(&rdata_name
, mctx
);
5104 printf("\n;; Impossible to verify the NSEC RR to prove"
5105 " the non-existence : FAILED\n\n");
5108 free_name(&rdata_name
, mctx
);
5109 if (result
!= ISC_R_SUCCESS
) {
5110 printf("\n;; Impossible to verify the non-existence:"
5114 printf("\n;; OK the query doesn't have response but"
5115 " we have validate this fact : SUCCESS\n\n");
5121 printf(";; cleanandgo \n");
5122 if (dns_name_dynamic(&chase_current_name
))
5123 free_name(&chase_current_name
, mctx
);
5124 if (dns_name_dynamic(&chase_authority_name
))
5125 free_name(&chase_authority_name
, mctx
);
5130 result
= advanced_rrsearch(&chase_rdataset
, &chase_name
,
5131 current_lookup
->rdtype_sigchase
,
5134 if (result
== ISC_R_FAILURE
) {
5135 printf("\n;; RRsig of RRset is missing to continue validation"
5136 " SHOULD NOT APPEND: FAILED\n\n");
5139 result
= sigchase_verify_sig(&chase_name
, chase_rdataset
,
5141 chase_sigrdataset
, mctx
);
5142 if (result
!= ISC_R_SUCCESS
) {
5143 printf("\n;; Impossible to verify the RRset : FAILED\n\n");
5146 print_rdataset(&chase_name , chase_rdataset, mctx);
5147 printf("DNSKEYset:\n");
5148 print_rdataset(&chase_name , chase_keyrdataset, mctx);
5149 printf("RRSIG of RRset:\n");
5150 print_rdataset(&chase_name , chase_sigrdataset, mctx);
5155 printf("\n;; The Answer:\n");
5156 print_rdataset(&chase_name
, chase_rdataset
, mctx
);
5158 printf("\n;; FINISH : we have validate the DNSSEC chain"
5159 " of trust: SUCCESS\n\n");
5170 getneededrr(dns_message_t
*msg
)
5172 isc_result_t result
;
5173 dns_name_t
*name
= NULL
;
5174 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
5175 dns_rdata_sig_t siginfo
;
5176 isc_boolean_t
true = ISC_TRUE
;
5178 if ((result
= dns_message_firstname(msg
, DNS_SECTION_ANSWER
))
5180 printf(";; NO ANSWERS: %s\n", isc_result_totext(result
));
5182 if (chase_name
.ndata
== NULL
)
5183 return (ISC_R_ADDRNOTAVAIL
);
5185 dns_message_currentname(msg
, DNS_SECTION_ANSWER
, &name
);
5188 /* What do we chase? */
5189 if (chase_rdataset
== NULL
) {
5190 result
= advanced_rrsearch(&chase_rdataset
, name
,
5192 dns_rdatatype_any
, &true);
5193 if (result
!= ISC_R_SUCCESS
) {
5194 printf("\n;; No Answers: Validation FAILED\n\n");
5195 return (ISC_R_NOTFOUND
);
5197 dup_name(name
, &chase_name
, mctx
);
5198 printf(";; RRset to chase:\n");
5199 print_rdataset(&chase_name
, chase_rdataset
, mctx
);
5201 INSIST(chase_rdataset
!= NULL
);
5204 if (chase_sigrdataset
== NULL
) {
5205 result
= advanced_rrsearch(&chase_sigrdataset
, name
,
5206 dns_rdatatype_rrsig
,
5207 chase_rdataset
->type
,
5208 &chase_siglookedup
);
5209 if (result
== ISC_R_FAILURE
) {
5210 printf("\n;; RRSIG is missing for continue validation:"
5212 if (dns_name_dynamic(&chase_name
))
5213 free_name(&chase_name
, mctx
);
5214 return (ISC_R_NOTFOUND
);
5216 if (result
== ISC_R_NOTFOUND
) {
5217 return (ISC_R_NOTFOUND
);
5219 printf("\n;; RRSIG of the RRset to chase:\n");
5220 print_rdataset(&chase_name
, chase_sigrdataset
, mctx
);
5222 INSIST(chase_sigrdataset
!= NULL
);
5225 /* first find the DNSKEY name */
5226 result
= dns_rdataset_first(chase_sigrdataset
);
5227 check_result(result
, "empty RRSIG dataset");
5228 dns_rdataset_current(chase_sigrdataset
, &sigrdata
);
5229 result
= dns_rdata_tostruct(&sigrdata
, &siginfo
, NULL
);
5230 check_result(result
, "sigrdata tostruct siginfo");
5231 dup_name(&siginfo
.signer
, &chase_signame
, mctx
);
5232 dns_rdata_freestruct(&siginfo
);
5233 dns_rdata_reset(&sigrdata
);
5235 /* Do we have a key? */
5236 if (chase_keyrdataset
== NULL
) {
5237 result
= advanced_rrsearch(&chase_keyrdataset
,
5239 dns_rdatatype_dnskey
,
5241 &chase_keylookedup
);
5242 if (result
== ISC_R_FAILURE
) {
5243 printf("\n;; DNSKEY is missing to continue validation:"
5245 free_name(&chase_signame
, mctx
);
5246 if (dns_name_dynamic(&chase_name
))
5247 free_name(&chase_name
, mctx
);
5248 return (ISC_R_NOTFOUND
);
5250 if (result
== ISC_R_NOTFOUND
) {
5251 free_name(&chase_signame
, mctx
);
5252 return (ISC_R_NOTFOUND
);
5254 printf("\n;; DNSKEYset that signs the RRset to chase:\n");
5255 print_rdataset(&chase_signame
, chase_keyrdataset
, mctx
);
5257 INSIST(chase_keyrdataset
!= NULL
);
5259 if (chase_sigkeyrdataset
== NULL
) {
5260 result
= advanced_rrsearch(&chase_sigkeyrdataset
,
5262 dns_rdatatype_rrsig
,
5263 dns_rdatatype_dnskey
,
5264 &chase_sigkeylookedup
);
5265 if (result
== ISC_R_FAILURE
) {
5266 printf("\n;; RRSIG for DNSKEY is missing to continue"
5267 " validation : FAILED\n\n");
5268 free_name(&chase_signame
, mctx
);
5269 if (dns_name_dynamic(&chase_name
))
5270 free_name(&chase_name
, mctx
);
5271 return (ISC_R_NOTFOUND
);
5273 if (result
== ISC_R_NOTFOUND
) {
5274 free_name(&chase_signame
, mctx
);
5275 return (ISC_R_NOTFOUND
);
5277 printf("\n;; RRSIG of the DNSKEYset that signs the "
5278 "RRset to chase:\n");
5279 print_rdataset(&chase_signame
, chase_sigkeyrdataset
, mctx
);
5281 INSIST(chase_sigkeyrdataset
!= NULL
);
5284 if (chase_dsrdataset
== NULL
) {
5285 result
= advanced_rrsearch(&chase_dsrdataset
, &chase_signame
,
5289 if (result
== ISC_R_FAILURE
) {
5290 printf("\n;; WARNING There is no DS for the zone: ");
5291 dns_name_print(&chase_signame
, stdout
);
5294 if (result
== ISC_R_NOTFOUND
) {
5295 free_name(&chase_signame
, mctx
);
5296 return (ISC_R_NOTFOUND
);
5298 if (chase_dsrdataset
!= NULL
) {
5299 printf("\n;; DSset of the DNSKEYset\n");
5300 print_rdataset(&chase_signame
, chase_dsrdataset
, mctx
);
5304 if (chase_dsrdataset
!= NULL
) {
5306 * if there is no RRSIG of DS,
5307 * we don't want to search on the network
5309 result
= advanced_rrsearch(&chase_sigdsrdataset
,
5311 dns_rdatatype_rrsig
,
5312 dns_rdatatype_ds
, &true);
5313 if (result
== ISC_R_FAILURE
) {
5314 printf(";; WARNING : NO RRSIG DS : RRSIG DS"
5315 " should come with DS\n");
5317 * We continue even the DS couldn't be validated,
5318 * because the DNSKEY could be a Trusted Key.
5320 chase_dsrdataset
= NULL
;
5322 printf("\n;; RRSIG of the DSset of the DNSKEYset\n");
5323 print_rdataset(&chase_signame
, chase_sigdsrdataset
,
5333 sigchase_bu(dns_message_t
*msg
)
5335 isc_result_t result
;
5338 if (tk_list
.nb_tk
== 0) {
5339 result
= get_trusted_key(mctx
);
5340 if (result
!= ISC_R_SUCCESS
) {
5341 printf("No trusted keys present\n");
5347 ret
= getneededrr(msg
);
5348 if (ret
== ISC_R_NOTFOUND
)
5351 if (ret
== ISC_R_ADDRNOTAVAIL
) {
5352 /* We have no response */
5353 dns_rdataset_t
*rdataset
;
5354 dns_rdataset_t
*sigrdataset
;
5355 dns_name_t rdata_name
;
5356 dns_name_t query_name
;
5359 dns_name_init(&query_name
, NULL
);
5360 dns_name_init(&rdata_name
, NULL
);
5361 nameFromString(current_lookup
->textname
, &query_name
);
5363 result
= prove_nx(msg
, &query_name
, current_lookup
->rdclass
,
5364 current_lookup
->rdtype
, &rdata_name
,
5365 &rdataset
, &sigrdataset
);
5366 free_name(&query_name
, mctx
);
5367 if (rdataset
== NULL
|| sigrdataset
== NULL
||
5368 dns_name_countlabels(&rdata_name
) == 0) {
5369 printf("\n;; Impossible to verify the Non-existence,"
5370 " the NSEC RRset can't be validated: "
5376 if (result
!= ISC_R_SUCCESS
) {
5377 printf("\n No Answers and impossible to prove the"
5378 " unsecurity : Validation FAILED\n\n");
5382 printf(";; An NSEC prove the non-existence of a answers,"
5383 " Now we want validate this NSEC\n");
5385 dup_name(&rdata_name
, &chase_name
, mctx
);
5386 free_name(&rdata_name
, mctx
);
5387 chase_rdataset
= rdataset
;
5388 chase_sigrdataset
= sigrdataset
;
5389 chase_keyrdataset
= NULL
;
5390 chase_sigkeyrdataset
= NULL
;
5391 chase_dsrdataset
= NULL
;
5392 chase_sigdsrdataset
= NULL
;
5393 chase_siglookedup
= ISC_FALSE
;
5394 chase_keylookedup
= ISC_FALSE
;
5395 chase_dslookedup
= ISC_FALSE
;
5396 chase_sigdslookedup
= ISC_FALSE
;
5403 printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n");
5405 result
= sigchase_verify_sig(&chase_name
, chase_rdataset
,
5407 chase_sigrdataset
, mctx
);
5408 if (result
!= ISC_R_SUCCESS
) {
5409 free_name(&chase_name
, mctx
);
5410 free_name(&chase_signame
, mctx
);
5411 printf(";; No DNSKEY is valid to check the RRSIG"
5412 " of the RRset: FAILED\n");
5416 printf(";; OK We found DNSKEY (or more) to validate the RRset\n");
5418 result
= contains_trusted_key(&chase_signame
, chase_keyrdataset
,
5419 chase_sigkeyrdataset
, mctx
);
5420 if (result
== ISC_R_SUCCESS
) {
5421 free_name(&chase_name
, mctx
);
5422 free_name(&chase_signame
, mctx
);
5423 printf("\n;; Ok this DNSKEY is a Trusted Key,"
5424 " DNSSEC validation is ok: SUCCESS\n\n");
5429 printf(";; Now, we are going to validate this DNSKEY by the DS\n");
5431 if (chase_dsrdataset
== NULL
) {
5432 free_name(&chase_name
, mctx
);
5433 free_name(&chase_signame
, mctx
);
5434 printf(";; the DNSKEY isn't trusted-key and there isn't"
5435 " DS to validate the DNSKEY: FAILED\n");
5440 result
= sigchase_verify_ds(&chase_signame
, chase_keyrdataset
,
5441 chase_dsrdataset
, mctx
);
5442 if (result
!= ISC_R_SUCCESS
) {
5443 free_name(&chase_signame
, mctx
);
5444 free_name(&chase_name
, mctx
);
5445 printf(";; ERROR no DS validates a DNSKEY in the"
5446 " DNSKEY RRset: FAILED\n");
5450 printf(";; OK this DNSKEY (validated by the DS) validates"
5451 " the RRset of the DNSKEYs, thus the DNSKEY validates"
5453 INSIST(chase_sigdsrdataset
!= NULL
);
5455 dup_name(&chase_signame
, &chase_name
, mctx
);
5456 free_name(&chase_signame
, mctx
);
5457 chase_rdataset
= chase_dsrdataset
;
5458 chase_sigrdataset
= chase_sigdsrdataset
;
5459 chase_keyrdataset
= NULL
;
5460 chase_sigkeyrdataset
= NULL
;
5461 chase_dsrdataset
= NULL
;
5462 chase_sigdsrdataset
= NULL
;
5463 chase_siglookedup
= chase_keylookedup
= ISC_FALSE
;
5464 chase_dslookedup
= chase_sigdslookedup
= ISC_FALSE
;
5466 printf(";; Now, we want to validate the DS : recursive call\n");
5473 sigchase(dns_message_t
*msg
) {
5475 if (current_lookup
->do_topdown
) {
5488 * return 1 if name1 < name2
5489 * 0 if name1 == name2
5490 * -1 if name1 > name2
5494 inf_name(dns_name_t
*name1
, dns_name_t
*name2
)
5498 unsigned int nblabel1
;
5499 unsigned int nblabel2
;
5504 nblabel1
= dns_name_countlabels(name1
);
5505 nblabel2
= dns_name_countlabels(name2
);
5507 if (nblabel1
>= nblabel2
)
5508 min_lum_label
= nblabel2
;
5510 min_lum_label
= nblabel1
;
5513 for (i
=1 ; i
< min_lum_label
; i
++) {
5514 dns_name_getlabel(name1
, nblabel1
-1 - i
, &label1
);
5515 dns_name_getlabel(name2
, nblabel2
-1 - i
, &label2
);
5516 if ((ret
= isc_region_compare(&label1
, &label2
)) != 0) {
5523 if (nblabel1
== nblabel2
)
5526 if (nblabel1
< nblabel2
)
5538 prove_nx_domain(dns_message_t
*msg
,
5540 dns_name_t
*rdata_name
,
5541 dns_rdataset_t
**rdataset
,
5542 dns_rdataset_t
**sigrdataset
)
5544 isc_result_t ret
= ISC_R_FAILURE
;
5545 isc_result_t result
= ISC_R_NOTFOUND
;
5546 dns_rdataset_t
*nsecset
= NULL
;
5547 dns_rdataset_t
*signsecset
= NULL
;
5548 dns_rdata_t nsec
= DNS_RDATA_INIT
;
5549 dns_name_t
*nsecname
;
5550 dns_rdata_nsec_t nsecstruct
;
5552 if ((result
= dns_message_firstname(msg
, DNS_SECTION_AUTHORITY
))
5554 printf(";; nothing in authority section : impossible to"
5555 " validate the non-existence : FAILED\n");
5556 return (ISC_R_FAILURE
);
5561 dns_message_currentname(msg
, DNS_SECTION_AUTHORITY
, &nsecname
);
5562 nsecset
= search_type(nsecname
, dns_rdatatype_nsec
,
5564 if (nsecset
== NULL
)
5567 printf("There is a NSEC for this zone in the"
5568 " AUTHORITY section:\n");
5569 print_rdataset(nsecname
, nsecset
, mctx
);
5571 for (result
= dns_rdataset_first(nsecset
);
5572 result
== ISC_R_SUCCESS
;
5573 result
= dns_rdataset_next(nsecset
)) {
5574 dns_rdataset_current(nsecset
, &nsec
);
5578 = chase_scanname_section(msg
, nsecname
,
5579 dns_rdatatype_rrsig
,
5581 DNS_SECTION_AUTHORITY
);
5582 if (signsecset
== NULL
) {
5583 printf(";; no RRSIG NSEC in authority section:"
5584 " impossible to validate the "
5585 "non-existence: FAILED\n");
5586 return (ISC_R_FAILURE
);
5589 ret
= dns_rdata_tostruct(&nsec
, &nsecstruct
, NULL
);
5590 check_result(ret
,"dns_rdata_tostruct");
5592 if ((inf_name(nsecname
, &nsecstruct
.next
) == 1 &&
5593 inf_name(name
, &nsecstruct
.next
) == 1) ||
5594 (inf_name(name
, nsecname
) == 1 &&
5595 inf_name(&nsecstruct
.next
, name
) == 1)) {
5596 dns_rdata_freestruct(&nsecstruct
);
5597 *rdataset
= nsecset
;
5598 *sigrdataset
= signsecset
;
5599 dup_name(nsecname
, rdata_name
, mctx
);
5601 return (ISC_R_SUCCESS
);
5604 dns_rdata_freestruct(&nsecstruct
);
5605 dns_rdata_reset(&nsec
);
5607 } while (dns_message_nextname(msg
, DNS_SECTION_AUTHORITY
)
5611 *sigrdataset
= NULL
;
5613 return (ISC_R_FAILURE
);
5624 prove_nx_type(dns_message_t
*msg
, dns_name_t
*name
, dns_rdataset_t
*nsecset
,
5625 dns_rdataclass_t
class, dns_rdatatype_t type
,
5626 dns_name_t
*rdata_name
, dns_rdataset_t
**rdataset
,
5627 dns_rdataset_t
**sigrdataset
)
5630 dns_rdataset_t
*signsecset
;
5631 dns_rdata_t nsec
= DNS_RDATA_INIT
;
5635 ret
= dns_rdataset_first(nsecset
);
5636 check_result(ret
,"dns_rdataset_first");
5638 dns_rdataset_current(nsecset
, &nsec
);
5640 ret
= dns_nsec_typepresent(&nsec
, type
);
5641 if (ret
== ISC_R_SUCCESS
)
5642 printf("OK the NSEC said that the type doesn't exist \n");
5644 signsecset
= chase_scanname_section(msg
, name
,
5645 dns_rdatatype_rrsig
,
5647 DNS_SECTION_AUTHORITY
);
5648 if (signsecset
== NULL
) {
5649 printf("There isn't RRSIG NSEC for the zone \n");
5650 return (ISC_R_FAILURE
);
5652 dup_name(name
, rdata_name
, mctx
);
5653 *rdataset
= nsecset
;
5654 *sigrdataset
= signsecset
;
5666 prove_nx(dns_message_t
*msg
, dns_name_t
*name
, dns_rdataclass_t
class,
5667 dns_rdatatype_t type
, dns_name_t
*rdata_name
,
5668 dns_rdataset_t
**rdataset
, dns_rdataset_t
**sigrdataset
)
5671 dns_rdataset_t
*nsecset
= NULL
;
5673 printf("We want to prove the non-existence of a type of rdata %d"
5674 " or of the zone: \n", type
);
5676 if ((ret
= dns_message_firstname(msg
, DNS_SECTION_AUTHORITY
))
5678 printf(";; nothing in authority section : impossible to"
5679 " validate the non-existence : FAILED\n");
5680 return (ISC_R_FAILURE
);
5683 nsecset
= chase_scanname_section(msg
, name
, dns_rdatatype_nsec
,
5685 DNS_SECTION_AUTHORITY
);
5686 if (nsecset
!= NULL
) {
5687 printf("We have a NSEC for this zone :OK\n");
5688 ret
= prove_nx_type(msg
, name
, nsecset
, class,
5689 type
, rdata_name
, rdataset
,
5691 if (ret
!= ISC_R_SUCCESS
) {
5692 printf("prove_nx: ERROR type exist\n");
5695 printf("prove_nx: OK type does not exist\n");
5696 return (ISC_R_SUCCESS
);
5699 printf("there is no NSEC for this zone: validating "
5700 "that the zone doesn't exist\n");
5701 ret
= prove_nx_domain(msg
, name
, rdata_name
,
5702 rdataset
, sigrdataset
);
5705 /* Never get here */