1 /* $NetBSD: dighost.c,v 1.15 2015/07/08 17:28:54 christos Exp $ */
4 * Copyright (C) 2004-2015 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.345 2011/12/07 17:23:28 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/callbacks.h>
52 #include <dns/dnssec.h>
54 #include <dns/master.h>
56 #include <isc/random.h>
59 #include <dns/fixedname.h>
61 #include <dns/message.h>
63 #include <dns/rcode.h>
64 #include <dns/rdata.h>
65 #include <dns/rdataclass.h>
66 #include <dns/rdatalist.h>
67 #include <dns/rdataset.h>
68 #include <dns/rdatastruct.h>
69 #include <dns/rdatatype.h>
70 #include <dns/result.h>
74 #include <dst/result.h>
77 #include <isc/base64.h>
78 #include <isc/entropy.h>
83 #include <isc/netaddr.h>
84 #include <isc/netdb.h>
85 #include <isc/parseint.h>
86 #include <isc/print.h>
87 #include <isc/random.h>
88 #include <isc/result.h>
89 #include <isc/serial.h>
90 #include <isc/sockaddr.h>
91 #include <isc/string.h>
93 #include <isc/timer.h>
94 #include <isc/types.h>
97 #include <isccfg/namedconf.h>
99 #include <lwres/lwres.h>
100 #include <lwres/net.h>
102 #include <bind9/getaddresses.h>
107 #include <pk11/result.h>
110 #if ! defined(NS_INADDRSZ)
111 #define NS_INADDRSZ 4
114 #if ! defined(NS_IN6ADDRSZ)
115 #define NS_IN6ADDRSZ 16
118 static lwres_context_t
*lwctx
= NULL
;
119 static lwres_conf_t
*lwconf
;
121 dig_lookuplist_t lookup_list
;
122 dig_serverlist_t server_list
;
123 dig_searchlistlist_t search_list
;
126 check_ra
= ISC_FALSE
,
127 have_ipv4
= ISC_FALSE
,
128 have_ipv6
= ISC_FALSE
,
129 specified_source
= ISC_FALSE
,
130 free_now
= ISC_FALSE
,
131 cancel_now
= ISC_FALSE
,
132 usesearch
= ISC_FALSE
,
133 showsearch
= ISC_FALSE
,
135 is_dst_up
= ISC_FALSE
,
136 keep_open
= ISC_FALSE
;
138 unsigned int timeout
= 0;
139 unsigned int extrabytes
;
140 isc_mem_t
*mctx
= NULL
;
141 isc_log_t
*lctx
= NULL
;
142 isc_taskmgr_t
*taskmgr
= NULL
;
143 isc_task_t
*global_task
= NULL
;
144 isc_timermgr_t
*timermgr
= NULL
;
145 isc_socketmgr_t
*socketmgr
= NULL
;
146 isc_sockaddr_t bind_address
;
147 isc_sockaddr_t bind_any
;
153 int lookup_counter
= 0;
156 static void initialize_idn(void);
157 static isc_result_t
output_filter(isc_buffer_t
*buffer
,
158 unsigned int used_org
,
159 isc_boolean_t absolute
);
160 static idn_result_t
append_textname(char *name
, const char *origin
,
162 static void idn_check_result(idn_result_t r
, const char *msg
);
168 isc_socket_t
*keep
= NULL
;
169 isc_sockaddr_t keepaddr
;
174 *\li 0 Everything went well, including things like NXDOMAIN
176 *\li 7 Got too many RR's or Names
177 *\li 8 Couldn't open batch file
178 *\li 9 No reply from server
179 *\li 10 Internal error
183 char keynametext
[MXNAME
];
184 char keyfile
[MXNAME
] = "";
185 char keysecret
[MXNAME
] = "";
186 unsigned char cookie_secret
[33];
187 unsigned char cookie
[8];
188 dns_name_t
*hmacname
= NULL
;
189 unsigned int digestbits
= 0;
190 isc_buffer_t
*namebuf
= NULL
;
191 dns_tsigkey_t
*key
= NULL
;
192 isc_boolean_t validated
= ISC_TRUE
;
193 isc_entropy_t
*entp
= NULL
;
194 isc_mempool_t
*commctx
= NULL
;
195 isc_boolean_t debugging
= ISC_FALSE
;
196 isc_boolean_t debugtiming
= ISC_FALSE
;
197 isc_boolean_t memdebugging
= ISC_FALSE
;
198 const char *progname
= NULL
;
199 isc_mutex_t lookup_lock
;
200 dig_lookup_t
*current_lookup
= NULL
;
204 isc_result_t
get_trusted_key(isc_mem_t
*mctx
);
205 dns_rdataset_t
* sigchase_scanname(dns_rdatatype_t type
,
206 dns_rdatatype_t covers
,
207 isc_boolean_t
*lookedup
,
208 dns_name_t
*rdata_name
);
209 dns_rdataset_t
* chase_scanname_section(dns_message_t
*msg
,
211 dns_rdatatype_t type
,
212 dns_rdatatype_t covers
,
214 isc_result_t
advanced_rrsearch(dns_rdataset_t
**rdataset
,
216 dns_rdatatype_t type
,
217 dns_rdatatype_t covers
,
218 isc_boolean_t
*lookedup
);
219 isc_result_t
sigchase_verify_sig_key(dns_name_t
*name
,
220 dns_rdataset_t
*rdataset
,
221 dst_key_t
* dnsseckey
,
222 dns_rdataset_t
*sigrdataset
,
224 isc_result_t
sigchase_verify_sig(dns_name_t
*name
,
225 dns_rdataset_t
*rdataset
,
226 dns_rdataset_t
*keyrdataset
,
227 dns_rdataset_t
*sigrdataset
,
229 isc_result_t
sigchase_verify_ds(dns_name_t
*name
,
230 dns_rdataset_t
*keyrdataset
,
231 dns_rdataset_t
*dsrdataset
,
233 void sigchase(dns_message_t
*msg
);
234 void print_rdata(dns_rdata_t
*rdata
, isc_mem_t
*mctx
);
235 void print_rdataset(dns_name_t
*name
,
236 dns_rdataset_t
*rdataset
, isc_mem_t
*mctx
);
237 void dup_name(dns_name_t
*source
, dns_name_t
* target
,
239 void free_name(dns_name_t
*name
, isc_mem_t
*mctx
);
240 void dump_database(void);
241 void dump_database_section(dns_message_t
*msg
, int section
);
242 dns_rdataset_t
* search_type(dns_name_t
*name
, dns_rdatatype_t type
,
243 dns_rdatatype_t covers
);
244 isc_result_t
contains_trusted_key(dns_name_t
*name
,
245 dns_rdataset_t
*rdataset
,
246 dns_rdataset_t
*sigrdataset
,
248 void print_type(dns_rdatatype_t type
);
249 isc_result_t
prove_nx_domain(dns_message_t
* msg
,
251 dns_name_t
* rdata_name
,
252 dns_rdataset_t
** rdataset
,
253 dns_rdataset_t
** sigrdataset
);
254 isc_result_t
prove_nx_type(dns_message_t
* msg
, dns_name_t
*name
,
255 dns_rdataset_t
*nsec
,
256 dns_rdataclass_t
class,
257 dns_rdatatype_t type
,
258 dns_name_t
* rdata_name
,
259 dns_rdataset_t
** rdataset
,
260 dns_rdataset_t
** sigrdataset
);
261 isc_result_t
prove_nx(dns_message_t
* msg
, dns_name_t
* name
,
262 dns_rdataclass_t
class,
263 dns_rdatatype_t type
,
264 dns_name_t
* rdata_name
,
265 dns_rdataset_t
** rdataset
,
266 dns_rdataset_t
** sigrdataset
);
267 static void nameFromString(const char *str
, dns_name_t
*p_ret
);
268 int inf_name(dns_name_t
* name1
, dns_name_t
* name2
);
269 isc_result_t
removetmpkey(isc_mem_t
*mctx
, const char *file
);
270 void clean_trustedkey(void);
271 isc_result_t
insert_trustedkey(void *arg
, dns_name_t
*name
,
272 dns_rdataset_t
*rdataset
);
274 isc_result_t
getneededrr(dns_message_t
*msg
);
275 void sigchase_bottom_up(dns_message_t
*msg
);
276 void sigchase_bu(dns_message_t
*msg
);
279 isc_result_t
initialization(dns_name_t
*name
);
280 isc_result_t
prepare_lookup(dns_name_t
*name
);
281 isc_result_t
grandfather_pb_test(dns_name_t
* zone_name
,
282 dns_rdataset_t
*sigrdataset
);
283 isc_result_t
child_of_zone(dns_name_t
*name
,
284 dns_name_t
*zone_name
,
285 dns_name_t
*child_name
);
286 void sigchase_td(dns_message_t
*msg
);
288 char trustedkey
[MXNAME
] = "";
290 dns_rdataset_t
*chase_rdataset
= NULL
;
291 dns_rdataset_t
*chase_sigrdataset
= NULL
;
292 dns_rdataset_t
*chase_dsrdataset
= NULL
;
293 dns_rdataset_t
*chase_sigdsrdataset
= NULL
;
294 dns_rdataset_t
*chase_keyrdataset
= NULL
;
295 dns_rdataset_t
*chase_sigkeyrdataset
= NULL
;
296 dns_rdataset_t
*chase_nsrdataset
= NULL
;
298 dns_name_t chase_name
; /* the query name */
301 * the current name is the parent name when we follow delegation
303 dns_name_t chase_current_name
;
305 * the child name is used for delegation (NS DS responses in AUTHORITY section)
307 dns_name_t chase_authority_name
;
310 dns_name_t chase_signame
;
314 isc_boolean_t chase_siglookedup
= ISC_FALSE
;
315 isc_boolean_t chase_keylookedup
= ISC_FALSE
;
316 isc_boolean_t chase_sigkeylookedup
= ISC_FALSE
;
317 isc_boolean_t chase_dslookedup
= ISC_FALSE
;
318 isc_boolean_t chase_sigdslookedup
= ISC_FALSE
;
320 isc_boolean_t chase_nslookedup
= ISC_FALSE
;
321 isc_boolean_t chase_lookedup
= ISC_FALSE
;
324 isc_boolean_t delegation_follow
= ISC_FALSE
;
325 isc_boolean_t grandfather_pb
= ISC_FALSE
;
326 isc_boolean_t have_response
= ISC_FALSE
;
327 isc_boolean_t have_delegation_ns
= ISC_FALSE
;
328 dns_message_t
* error_message
= NULL
;
331 isc_boolean_t dsvalidating
= ISC_FALSE
;
332 isc_boolean_t chase_name_dup
= ISC_FALSE
;
334 ISC_LIST(dig_message_t
) chase_message_list
;
335 ISC_LIST(dig_message_t
) chase_message_list2
;
338 #define MAX_TRUSTED_KEY 5
339 typedef struct struct_trusted_key_list
{
340 dst_key_t
* key
[MAX_TRUSTED_KEY
];
344 struct_tk_list tk_list
= { {NULL
, NULL
, NULL
, NULL
, NULL
}, 0};
348 #define DIG_MAX_ADDRESSES 20
351 * Apply and clear locks at the event level in global task.
352 * Can I get rid of these using shutdown events? XXX
354 #define LOCK_LOOKUP {\
355 debug("lock_lookup %s:%d", __FILE__, __LINE__);\
356 check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\
359 #define UNLOCK_LOOKUP {\
360 debug("unlock_lookup %s:%d", __FILE__, __LINE__);\
361 check_result(isc_mutex_unlock((&lookup_lock)),\
362 "isc_mutex_unlock");\
366 cancel_lookup(dig_lookup_t
*lookup
);
369 recv_done(isc_task_t
*task
, isc_event_t
*event
);
372 send_udp(dig_query_t
*query
);
375 connect_timeout(isc_task_t
*task
, isc_event_t
*event
);
378 launch_next_query(dig_query_t
*query
, isc_boolean_t include_question
);
381 check_next_lookup(dig_lookup_t
*lookup
);
384 next_origin(dig_lookup_t
*oldlookup
);
387 mem_alloc(void *arg
, size_t size
) {
388 return (isc_mem_get(arg
, size
));
392 mem_free(void *arg
, void *mem
, size_t size
) {
393 isc_mem_put(arg
, mem
, size
);
397 next_token(char **stringp
, const char *delim
) {
401 res
= strsep(stringp
, delim
);
404 } while (*res
== '\0');
409 count_dots(char *string
) {
423 hex_dump(isc_buffer_t
*b
) {
427 isc_buffer_usedregion(b
, &r
);
429 printf("%d bytes\n", r
.length
);
430 for (len
= 0; len
< r
.length
; len
++) {
431 printf("%02x ", r
.base
[len
]);
432 if (len
% 16 == 15) {
434 for (i
= len
- 15; i
<= len
; i
++) {
435 if (r
.base
[i
] >= '!' && r
.base
[i
] <= '}')
444 for (i
= len
; (i
% 16) != 0; i
++)
447 for (i
= ((len
>>4)<<4); i
< len
; i
++) {
448 if (r
.base
[i
] >= '!' && r
.base
[i
] <= '}')
458 * Append 'len' bytes of 'text' at '*p', failing with
459 * ISC_R_NOSPACE if that would advance p past 'end'.
462 append(const char *text
, int len
, char **p
, char *end
) {
464 return (ISC_R_NOSPACE
);
465 memmove(*p
, text
, len
);
467 return (ISC_R_SUCCESS
);
471 reverse_octets(const char *in
, char **p
, char *end
) {
472 char *dot
= strchr(in
, '.');
476 result
= reverse_octets(dot
+ 1, p
, end
);
477 if (result
!= ISC_R_SUCCESS
)
479 result
= append(".", 1, p
, end
);
480 if (result
!= ISC_R_SUCCESS
)
482 len
= (int)(dot
- in
);
486 return (append(in
, len
, p
, end
));
490 get_reverse(char *reverse
, size_t len
, char *value
, isc_boolean_t ip6_int
,
491 isc_boolean_t strict
)
497 addr
.family
= AF_INET6
;
498 r
= inet_pton(AF_INET6
, value
, &addr
.type
.in6
);
500 /* This is a valid IPv6 address. */
501 dns_fixedname_t fname
;
503 unsigned int options
= 0;
506 options
|= DNS_BYADDROPT_IPV6INT
;
507 dns_fixedname_init(&fname
);
508 name
= dns_fixedname_name(&fname
);
509 result
= dns_byaddr_createptrname2(&addr
, options
, name
);
510 if (result
!= ISC_R_SUCCESS
)
512 dns_name_format(name
, reverse
, (unsigned int)len
);
513 return (ISC_R_SUCCESS
);
516 * Not a valid IPv6 address. Assume IPv4.
517 * If 'strict' is not set, construct the
518 * in-addr.arpa name by blindly reversing
519 * octets whether or not they look like integers,
520 * so that this can be used for RFC2317 names
524 char *end
= reverse
+ len
;
525 if (strict
&& inet_pton(AF_INET
, value
, &addr
.type
.in
) != 1)
526 return (DNS_R_BADDOTTEDQUAD
);
527 result
= reverse_octets(value
, &p
, end
);
528 if (result
!= ISC_R_SUCCESS
)
530 /* Append .in-addr.arpa. and a terminating NUL. */
531 result
= append(".in-addr.arpa.", 15, &p
, end
);
532 if (result
!= ISC_R_SUCCESS
)
534 return (ISC_R_SUCCESS
);
539 fatal(const char *format
, ...) {
543 fprintf(stderr
, "%s: ", progname
);
544 va_start(args
, format
);
545 vfprintf(stderr
, format
, args
);
547 fprintf(stderr
, "\n");
551 exitcode
= fatalexit
;
556 debug(const char *format
, ...) {
564 fprintf(stderr
, "%d.%06d: ", isc_time_seconds(&t
),
565 isc_time_nanoseconds(&t
) / 1000);
567 va_start(args
, format
);
568 vfprintf(stderr
, format
, args
);
570 fprintf(stderr
, "\n");
575 check_result(isc_result_t result
, const char *msg
) {
576 if (result
!= ISC_R_SUCCESS
) {
577 fatal("%s: %s", msg
, isc_result_totext(result
));
582 * Create a server structure, which is part of the lookup structure.
583 * This is little more than a linked list of servers to query in hopes
584 * of finding the answer the user is looking for
587 make_server(const char *servname
, const char *userarg
) {
590 REQUIRE(servname
!= NULL
);
592 debug("make_server(%s)", servname
);
593 srv
= isc_mem_allocate(mctx
, sizeof(struct dig_server
));
595 fatal("memory allocation failure in %s:%d",
597 strlcpy(srv
->servername
, servname
, MXNAME
);
598 strlcpy(srv
->userarg
, userarg
, MXNAME
);
599 ISC_LINK_INIT(srv
, link
);
604 addr2af(int lwresaddrtype
)
608 switch (lwresaddrtype
) {
609 case LWRES_ADDRTYPE_V4
:
613 case LWRES_ADDRTYPE_V6
:
622 * Create a copy of the server list from the lwres configuration structure.
623 * The dest list must have already had ISC_LIST_INIT applied.
626 copy_server_list(lwres_conf_t
*confdata
, dig_serverlist_t
*dest
) {
627 dig_server_t
*newsrv
;
628 char tmp
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") +
629 sizeof("%4000000000")];
633 debug("copy_server_list()");
634 for (i
= 0; i
< confdata
->nsnext
; i
++) {
635 af
= addr2af(confdata
->nameservers
[i
].family
);
637 if (af
== AF_INET
&& !have_ipv4
)
639 if (af
== AF_INET6
&& !have_ipv6
)
642 lwres_net_ntop(af
, confdata
->nameservers
[i
].address
,
644 if (af
== AF_INET6
&& confdata
->nameservers
[i
].zone
!= 0) {
645 char buf
[sizeof("%4000000000")];
646 snprintf(buf
, sizeof(buf
), "%%%u",
647 confdata
->nameservers
[i
].zone
);
648 strlcat(tmp
, buf
, sizeof(tmp
));
650 newsrv
= make_server(tmp
, tmp
);
651 ISC_LINK_INIT(newsrv
, link
);
652 ISC_LIST_ENQUEUE(*dest
, newsrv
, link
);
657 flush_server_list(void) {
658 dig_server_t
*s
, *ps
;
660 debug("flush_server_list()");
661 s
= ISC_LIST_HEAD(server_list
);
664 s
= ISC_LIST_NEXT(s
, link
);
665 ISC_LIST_DEQUEUE(server_list
, ps
, link
);
666 isc_mem_free(mctx
, ps
);
671 set_nameserver(char *opt
) {
673 isc_sockaddr_t sockaddrs
[DIG_MAX_ADDRESSES
];
674 isc_netaddr_t netaddr
;
677 char tmp
[ISC_NETADDR_FORMATSIZE
];
682 result
= bind9_getaddresses(opt
, 0, sockaddrs
,
683 DIG_MAX_ADDRESSES
, &count
);
684 if (result
!= ISC_R_SUCCESS
)
685 fatal("couldn't get address for '%s': %s",
686 opt
, isc_result_totext(result
));
690 for (i
= 0; i
< count
; i
++) {
691 isc_netaddr_fromsockaddr(&netaddr
, &sockaddrs
[i
]);
692 isc_netaddr_format(&netaddr
, tmp
, sizeof(tmp
));
693 srv
= make_server(tmp
, opt
);
695 fatal("memory allocation failure");
696 ISC_LIST_APPEND(server_list
, srv
, link
);
701 add_nameserver(lwres_conf_t
*confdata
, const char *addr
, int af
) {
703 int i
= confdata
->nsnext
;
705 if (confdata
->nsnext
>= LWRES_CONFMAXNAMESERVERS
)
706 return (ISC_R_FAILURE
);
710 confdata
->nameservers
[i
].family
= LWRES_ADDRTYPE_V4
;
711 confdata
->nameservers
[i
].length
= NS_INADDRSZ
;
714 confdata
->nameservers
[i
].family
= LWRES_ADDRTYPE_V6
;
715 confdata
->nameservers
[i
].length
= NS_IN6ADDRSZ
;
718 return (ISC_R_FAILURE
);
721 if (lwres_net_pton(af
, addr
, &confdata
->nameservers
[i
].address
) == 1) {
723 return (ISC_R_SUCCESS
);
725 return (ISC_R_FAILURE
);
729 * Produce a cloned server list. The dest list must have already had
730 * ISC_LIST_INIT applied.
733 clone_server_list(dig_serverlist_t src
, dig_serverlist_t
*dest
) {
734 dig_server_t
*srv
, *newsrv
;
736 debug("clone_server_list()");
737 srv
= ISC_LIST_HEAD(src
);
738 while (srv
!= NULL
) {
739 newsrv
= make_server(srv
->servername
, srv
->userarg
);
740 ISC_LINK_INIT(newsrv
, link
);
741 ISC_LIST_ENQUEUE(*dest
, newsrv
, link
);
742 srv
= ISC_LIST_NEXT(srv
, link
);
747 * Create an empty lookup structure, which holds all the information needed
748 * to get an answer to a user's question. This structure contains two
749 * linked lists: the server list (servers to query) and the query list
750 * (outstanding queries which have been made to the listed servers).
753 make_empty_lookup(void) {
754 dig_lookup_t
*looknew
;
756 debug("make_empty_lookup()");
760 looknew
= isc_mem_allocate(mctx
, sizeof(struct dig_lookup
));
762 fatal("memory allocation failure in %s:%d",
764 looknew
->pending
= ISC_TRUE
;
765 looknew
->textname
[0] = 0;
766 looknew
->cmdline
[0] = 0;
767 looknew
->rdtype
= dns_rdatatype_a
;
768 looknew
->qrdtype
= dns_rdatatype_a
;
769 looknew
->rdclass
= dns_rdataclass_in
;
770 looknew
->rdtypeset
= ISC_FALSE
;
771 looknew
->rdclassset
= ISC_FALSE
;
772 looknew
->sendspace
= NULL
;
773 looknew
->sendmsg
= NULL
;
774 looknew
->name
= NULL
;
775 looknew
->oname
= NULL
;
776 looknew
->timer
= NULL
;
777 looknew
->xfr_q
= NULL
;
778 looknew
->current_query
= NULL
;
779 looknew
->doing_xfr
= ISC_FALSE
;
780 looknew
->ixfr_serial
= 0;
781 looknew
->trace
= ISC_FALSE
;
782 looknew
->trace_root
= ISC_FALSE
;
783 looknew
->identify
= ISC_FALSE
;
784 looknew
->identify_previous_line
= ISC_FALSE
;
785 looknew
->ignore
= ISC_FALSE
;
786 looknew
->servfail_stops
= ISC_TRUE
;
787 looknew
->besteffort
= ISC_TRUE
;
788 looknew
->dnssec
= ISC_FALSE
;
789 looknew
->expire
= ISC_FALSE
;
790 looknew
->nsid
= ISC_FALSE
;
791 #ifdef ISC_PLATFORM_USESIT
792 looknew
->sit
= ISC_FALSE
;
795 looknew
->sigchase
= ISC_FALSE
;
797 looknew
->do_topdown
= ISC_FALSE
;
798 looknew
->trace_root_sigchase
= ISC_FALSE
;
799 looknew
->rdtype_sigchaseset
= ISC_FALSE
;
800 looknew
->rdtype_sigchase
= dns_rdatatype_any
;
801 looknew
->qrdtype_sigchase
= dns_rdatatype_any
;
802 looknew
->rdclass_sigchase
= dns_rdataclass_in
;
803 looknew
->rdclass_sigchaseset
= ISC_FALSE
;
806 looknew
->udpsize
= 0;
808 looknew
->recurse
= ISC_TRUE
;
809 looknew
->aaonly
= ISC_FALSE
;
810 looknew
->adflag
= ISC_FALSE
;
811 looknew
->cdflag
= ISC_FALSE
;
812 looknew
->ns_search_only
= ISC_FALSE
;
813 looknew
->origin
= NULL
;
814 looknew
->tsigctx
= NULL
;
815 looknew
->querysig
= NULL
;
816 looknew
->retries
= tries
;
817 looknew
->nsfound
= 0;
818 looknew
->tcp_mode
= ISC_FALSE
;
819 looknew
->tcp_mode_set
= ISC_FALSE
;
820 looknew
->ip6_int
= ISC_FALSE
;
821 looknew
->comments
= ISC_TRUE
;
822 looknew
->stats
= ISC_TRUE
;
823 looknew
->section_question
= ISC_TRUE
;
824 looknew
->section_answer
= ISC_TRUE
;
825 looknew
->section_authority
= ISC_TRUE
;
826 looknew
->section_additional
= ISC_TRUE
;
827 looknew
->new_search
= ISC_FALSE
;
828 looknew
->done_as_is
= ISC_FALSE
;
829 looknew
->need_search
= ISC_FALSE
;
830 looknew
->ecs_addr
= NULL
;
831 #ifdef ISC_PLATFORM_USESIT
832 looknew
->sitvalue
= NULL
;
834 dns_fixedname_init(&looknew
->fdomain
);
835 ISC_LINK_INIT(looknew
, link
);
836 ISC_LIST_INIT(looknew
->q
);
837 ISC_LIST_INIT(looknew
->connecting
);
838 ISC_LIST_INIT(looknew
->my_server_list
);
843 * Clone a lookup, perhaps copying the server list. This does not clone
844 * the query list, since it will be regenerated by the setup_lookup()
845 * function, nor does it queue up the new lookup for processing.
846 * Caution: If you don't clone the servers, you MUST clone the server
847 * list separately from somewhere else, or construct it by hand.
850 clone_lookup(dig_lookup_t
*lookold
, isc_boolean_t servers
) {
851 dig_lookup_t
*looknew
;
853 debug("clone_lookup()");
857 looknew
= make_empty_lookup();
858 INSIST(looknew
!= NULL
);
859 strlcpy(looknew
->textname
, lookold
->textname
, MXNAME
);
861 strlcpy(looknew
->textnamesigchase
, lookold
->textnamesigchase
, MXNAME
);
863 strlcpy(looknew
->cmdline
, lookold
->cmdline
, MXNAME
);
864 looknew
->textname
[MXNAME
-1] = 0;
865 looknew
->rdtype
= lookold
->rdtype
;
866 looknew
->qrdtype
= lookold
->qrdtype
;
867 looknew
->rdclass
= lookold
->rdclass
;
868 looknew
->rdtypeset
= lookold
->rdtypeset
;
869 looknew
->rdclassset
= lookold
->rdclassset
;
870 looknew
->doing_xfr
= lookold
->doing_xfr
;
871 looknew
->ixfr_serial
= lookold
->ixfr_serial
;
872 looknew
->trace
= lookold
->trace
;
873 looknew
->trace_root
= lookold
->trace_root
;
874 looknew
->identify
= lookold
->identify
;
875 looknew
->identify_previous_line
= lookold
->identify_previous_line
;
876 looknew
->ignore
= lookold
->ignore
;
877 looknew
->servfail_stops
= lookold
->servfail_stops
;
878 looknew
->besteffort
= lookold
->besteffort
;
879 looknew
->dnssec
= lookold
->dnssec
;
880 looknew
->expire
= lookold
->expire
;
881 looknew
->nsid
= lookold
->nsid
;
882 #ifdef ISC_PLATFORM_USESIT
883 looknew
->sit
= lookold
->sit
;
884 looknew
->sitvalue
= lookold
->sitvalue
;
887 looknew
->sigchase
= lookold
->sigchase
;
889 looknew
->do_topdown
= lookold
->do_topdown
;
890 looknew
->trace_root_sigchase
= lookold
->trace_root_sigchase
;
891 looknew
->rdtype_sigchaseset
= lookold
->rdtype_sigchaseset
;
892 looknew
->rdtype_sigchase
= lookold
->rdtype_sigchase
;
893 looknew
->qrdtype_sigchase
= lookold
->qrdtype_sigchase
;
894 looknew
->rdclass_sigchase
= lookold
->rdclass_sigchase
;
895 looknew
->rdclass_sigchaseset
= lookold
->rdclass_sigchaseset
;
898 looknew
->udpsize
= lookold
->udpsize
;
899 looknew
->edns
= lookold
->edns
;
900 looknew
->recurse
= lookold
->recurse
;
901 looknew
->aaonly
= lookold
->aaonly
;
902 looknew
->adflag
= lookold
->adflag
;
903 looknew
->cdflag
= lookold
->cdflag
;
904 looknew
->ns_search_only
= lookold
->ns_search_only
;
905 looknew
->tcp_mode
= lookold
->tcp_mode
;
906 looknew
->tcp_mode_set
= lookold
->tcp_mode_set
;
907 looknew
->comments
= lookold
->comments
;
908 looknew
->stats
= lookold
->stats
;
909 looknew
->section_question
= lookold
->section_question
;
910 looknew
->section_answer
= lookold
->section_answer
;
911 looknew
->section_authority
= lookold
->section_authority
;
912 looknew
->section_additional
= lookold
->section_additional
;
913 looknew
->retries
= lookold
->retries
;
914 looknew
->tsigctx
= NULL
;
915 looknew
->need_search
= lookold
->need_search
;
916 looknew
->done_as_is
= lookold
->done_as_is
;
918 if (lookold
->ecs_addr
!= NULL
) {
919 size_t len
= sizeof(isc_sockaddr_t
);
920 looknew
->ecs_addr
= isc_mem_allocate(mctx
, len
);
921 memmove(looknew
->ecs_addr
, lookold
->ecs_addr
, len
);
924 dns_name_copy(dns_fixedname_name(&lookold
->fdomain
),
925 dns_fixedname_name(&looknew
->fdomain
), NULL
);
928 clone_server_list(lookold
->my_server_list
,
929 &looknew
->my_server_list
);
934 * Requeue a lookup for further processing, perhaps copying the server
935 * list. The new lookup structure is returned to the caller, and is
936 * queued for processing. If servers are not cloned in the requeue, they
937 * must be added before allowing the current event to complete, since the
938 * completion of the event may result in the next entry on the lookup
942 requeue_lookup(dig_lookup_t
*lookold
, isc_boolean_t servers
) {
943 dig_lookup_t
*looknew
;
945 debug("requeue_lookup()");
948 if (lookup_counter
> LOOKUP_LIMIT
)
949 fatal("too many lookups");
951 looknew
= clone_lookup(lookold
, servers
);
952 INSIST(looknew
!= NULL
);
954 debug("before insertion, init@%p -> %p, new@%p -> %p",
955 lookold
, lookold
->link
.next
, looknew
, looknew
->link
.next
);
956 ISC_LIST_PREPEND(lookup_list
, looknew
, link
);
957 debug("after insertion, init -> %p, new = %p, new -> %p",
958 lookold
, looknew
, looknew
->link
.next
);
964 setup_text_key(void) {
967 isc_buffer_t secretbuf
;
969 unsigned char *secretstore
;
971 debug("setup_text_key()");
972 result
= isc_buffer_allocate(mctx
, &namebuf
, MXNAME
);
973 check_result(result
, "isc_buffer_allocate");
974 dns_name_init(&keyname
, NULL
);
975 check_result(result
, "dns_name_init");
976 isc_buffer_putstr(namebuf
, keynametext
);
977 secretsize
= strlen(keysecret
) * 3 / 4;
978 secretstore
= isc_mem_allocate(mctx
, secretsize
);
979 if (secretstore
== NULL
)
980 fatal("memory allocation failure in %s:%d",
982 isc_buffer_init(&secretbuf
, secretstore
, secretsize
);
983 result
= isc_base64_decodestring(keysecret
, &secretbuf
);
984 if (result
!= ISC_R_SUCCESS
)
987 secretsize
= isc_buffer_usedlength(&secretbuf
);
989 if (hmacname
== NULL
) {
990 result
= DST_R_UNSUPPORTEDALG
;
994 result
= dns_name_fromtext(&keyname
, namebuf
, dns_rootname
, 0, namebuf
);
995 if (result
!= ISC_R_SUCCESS
)
998 result
= dns_tsigkey_create(&keyname
, hmacname
, secretstore
,
999 secretsize
, ISC_FALSE
, NULL
, 0, 0, mctx
,
1002 if (result
!= ISC_R_SUCCESS
)
1003 printf(";; Couldn't create key %s: %s\n",
1004 keynametext
, isc_result_totext(result
));
1006 dst_key_setbits(key
->key
, digestbits
);
1008 isc_mem_free(mctx
, secretstore
);
1009 dns_name_invalidate(&keyname
);
1010 isc_buffer_free(&namebuf
);
1014 parse_uint(isc_uint32_t
*uip
, const char *value
, isc_uint32_t max
,
1017 isc_result_t result
= isc_parse_uint32(&n
, value
, 10);
1018 if (result
== ISC_R_SUCCESS
&& n
> max
)
1019 result
= ISC_R_RANGE
;
1020 if (result
!= ISC_R_SUCCESS
) {
1021 printf("invalid %s '%s': %s\n", desc
,
1022 value
, isc_result_totext(result
));
1026 return (ISC_R_SUCCESS
);
1030 parse_bits(char *arg
, const char *desc
, isc_uint32_t max
) {
1031 isc_result_t result
;
1034 result
= parse_uint(&tmp
, arg
, max
, desc
);
1035 if (result
!= ISC_R_SUCCESS
)
1036 fatal("couldn't parse digest bits");
1037 tmp
= (tmp
+ 7) & ~0x7U
;
1042 parse_netprefix(isc_sockaddr_t
**sap
, const char *value
) {
1043 isc_result_t result
= ISC_R_SUCCESS
;
1044 isc_sockaddr_t
*sa
= NULL
;
1046 struct in6_addr in6
;
1047 isc_uint32_t netmask
= 0;
1049 isc_boolean_t parsed
= ISC_FALSE
;
1051 if ((slash
= strchr(value
, '/'))) {
1053 result
= isc_parse_uint32(&netmask
, slash
+ 1, 10);
1054 if (result
!= ISC_R_SUCCESS
) {
1056 fatal("invalid prefix length '%s': %s\n",
1057 value
, isc_result_totext(result
));
1061 sa
= isc_mem_allocate(mctx
, sizeof(*sa
));
1062 if (inet_pton(AF_INET6
, value
, &in6
) == 1) {
1063 isc_sockaddr_fromin6(sa
, &in6
, 0);
1065 if (netmask
== 0 || netmask
> 128)
1067 } else if (inet_pton(AF_INET
, value
, &in4
) == 1) {
1069 isc_sockaddr_fromin(sa
, &in4
, 0);
1070 if (netmask
== 0 || netmask
> 32)
1072 } else if (netmask
!= 0) {
1076 strlcpy(buf
, value
, sizeof(buf
));
1077 for (i
= 0; i
< 3; i
++) {
1078 strlcat(buf
, ".0", sizeof(buf
));
1079 if (inet_pton(AF_INET
, buf
, &in4
) == 1) {
1081 isc_sockaddr_fromin(sa
, &in4
, 0);
1092 fatal("invalid address '%s'", value
);
1094 sa
->length
= netmask
;
1097 return (ISC_R_SUCCESS
);
1102 * Parse HMAC algorithm specification
1105 parse_hmac(const char *hmac
) {
1109 REQUIRE(hmac
!= NULL
);
1112 if (len
>= (int) sizeof(buf
))
1113 fatal("unknown key type '%.*s'", len
, hmac
);
1114 strlcpy(buf
, hmac
, sizeof(buf
));
1118 if (strcasecmp(buf
, "hmac-md5") == 0) {
1119 hmacname
= DNS_TSIG_HMACMD5_NAME
;
1120 } else if (strncasecmp(buf
, "hmac-md5-", 9) == 0) {
1121 hmacname
= DNS_TSIG_HMACMD5_NAME
;
1122 digestbits
= parse_bits(&buf
[9], "digest-bits [0..128]", 128);
1123 } else if (strcasecmp(buf
, "hmac-sha1") == 0) {
1124 hmacname
= DNS_TSIG_HMACSHA1_NAME
;
1126 } else if (strncasecmp(buf
, "hmac-sha1-", 10) == 0) {
1127 hmacname
= DNS_TSIG_HMACSHA1_NAME
;
1128 digestbits
= parse_bits(&buf
[10], "digest-bits [0..160]", 160);
1129 } else if (strcasecmp(buf
, "hmac-sha224") == 0) {
1130 hmacname
= DNS_TSIG_HMACSHA224_NAME
;
1131 } else if (strncasecmp(buf
, "hmac-sha224-", 12) == 0) {
1132 hmacname
= DNS_TSIG_HMACSHA224_NAME
;
1133 digestbits
= parse_bits(&buf
[12], "digest-bits [0..224]", 224);
1134 } else if (strcasecmp(buf
, "hmac-sha256") == 0) {
1135 hmacname
= DNS_TSIG_HMACSHA256_NAME
;
1136 } else if (strncasecmp(buf
, "hmac-sha256-", 12) == 0) {
1137 hmacname
= DNS_TSIG_HMACSHA256_NAME
;
1138 digestbits
= parse_bits(&buf
[12], "digest-bits [0..256]", 256);
1139 } else if (strcasecmp(buf
, "hmac-sha384") == 0) {
1140 hmacname
= DNS_TSIG_HMACSHA384_NAME
;
1141 } else if (strncasecmp(buf
, "hmac-sha384-", 12) == 0) {
1142 hmacname
= DNS_TSIG_HMACSHA384_NAME
;
1143 digestbits
= parse_bits(&buf
[12], "digest-bits [0..384]", 384);
1144 } else if (strcasecmp(buf
, "hmac-sha512") == 0) {
1145 hmacname
= DNS_TSIG_HMACSHA512_NAME
;
1146 } else if (strncasecmp(buf
, "hmac-sha512-", 12) == 0) {
1147 hmacname
= DNS_TSIG_HMACSHA512_NAME
;
1148 digestbits
= parse_bits(&buf
[12], "digest-bits [0..512]", 512);
1150 fprintf(stderr
, ";; Warning, ignoring "
1151 "invalid TSIG algorithm %s\n", buf
);
1156 * Get a key from a named.conf format keyfile
1159 read_confkey(void) {
1160 cfg_parser_t
*pctx
= NULL
;
1161 cfg_obj_t
*file
= NULL
;
1162 const cfg_obj_t
*keyobj
= NULL
;
1163 const cfg_obj_t
*secretobj
= NULL
;
1164 const cfg_obj_t
*algorithmobj
= NULL
;
1165 const char *keyname
;
1166 const char *secretstr
;
1167 const char *algorithm
;
1168 isc_result_t result
;
1170 if (! isc_file_exists(keyfile
))
1171 return (ISC_R_FILENOTFOUND
);
1173 result
= cfg_parser_create(mctx
, NULL
, &pctx
);
1174 if (result
!= ISC_R_SUCCESS
)
1177 result
= cfg_parse_file(pctx
, keyfile
, &cfg_type_sessionkey
,
1179 if (result
!= ISC_R_SUCCESS
)
1182 result
= cfg_map_get(file
, "key", &keyobj
);
1183 if (result
!= ISC_R_SUCCESS
)
1186 (void) cfg_map_get(keyobj
, "secret", &secretobj
);
1187 (void) cfg_map_get(keyobj
, "algorithm", &algorithmobj
);
1188 if (secretobj
== NULL
|| algorithmobj
== NULL
)
1189 fatal("key must have algorithm and secret");
1191 keyname
= cfg_obj_asstring(cfg_map_getname(keyobj
));
1192 secretstr
= cfg_obj_asstring(secretobj
);
1193 algorithm
= cfg_obj_asstring(algorithmobj
);
1195 strlcpy(keynametext
, keyname
, sizeof(keynametext
));
1196 strlcpy(keysecret
, secretstr
, sizeof(keysecret
));
1197 parse_hmac(algorithm
);
1203 cfg_obj_destroy(pctx
, &file
);
1204 cfg_parser_destroy(&pctx
);
1211 setup_file_key(void) {
1212 isc_result_t result
;
1213 dst_key_t
*dstkey
= NULL
;
1215 debug("setup_file_key()");
1217 /* Try reading the key from a K* pair */
1218 result
= dst_key_fromnamedfile(keyfile
, NULL
,
1219 DST_TYPE_PRIVATE
| DST_TYPE_KEY
, mctx
,
1222 /* If that didn't work, try reading it as a session.key keyfile */
1223 if (result
!= ISC_R_SUCCESS
) {
1224 result
= read_confkey();
1225 if (result
== ISC_R_SUCCESS
)
1229 if (result
!= ISC_R_SUCCESS
) {
1230 fprintf(stderr
, "Couldn't read key from %s: %s\n",
1231 keyfile
, isc_result_totext(result
));
1235 switch (dst_key_alg(dstkey
)) {
1236 case DST_ALG_HMACMD5
:
1237 hmacname
= DNS_TSIG_HMACMD5_NAME
;
1239 case DST_ALG_HMACSHA1
:
1240 hmacname
= DNS_TSIG_HMACSHA1_NAME
;
1242 case DST_ALG_HMACSHA224
:
1243 hmacname
= DNS_TSIG_HMACSHA224_NAME
;
1245 case DST_ALG_HMACSHA256
:
1246 hmacname
= DNS_TSIG_HMACSHA256_NAME
;
1248 case DST_ALG_HMACSHA384
:
1249 hmacname
= DNS_TSIG_HMACSHA384_NAME
;
1251 case DST_ALG_HMACSHA512
:
1252 hmacname
= DNS_TSIG_HMACSHA512_NAME
;
1255 printf(";; Couldn't create key %s: bad algorithm\n",
1259 result
= dns_tsigkey_createfromkey(dst_key_name(dstkey
), hmacname
,
1260 dstkey
, ISC_FALSE
, NULL
, 0, 0,
1262 if (result
!= ISC_R_SUCCESS
) {
1263 printf(";; Couldn't create key %s: %s\n",
1264 keynametext
, isc_result_totext(result
));
1269 dst_key_free(&dstkey
);
1272 static dig_searchlist_t
*
1273 make_searchlist_entry(char *domain
) {
1274 dig_searchlist_t
*search
;
1275 search
= isc_mem_allocate(mctx
, sizeof(*search
));
1277 fatal("memory allocation failure in %s:%d",
1278 __FILE__
, __LINE__
);
1279 strlcpy(search
->origin
, domain
, MXNAME
);
1280 search
->origin
[MXNAME
-1] = 0;
1281 ISC_LINK_INIT(search
, link
);
1286 clear_searchlist(void) {
1287 dig_searchlist_t
*search
;
1288 while ((search
= ISC_LIST_HEAD(search_list
)) != NULL
) {
1289 ISC_LIST_UNLINK(search_list
, search
, link
);
1290 isc_mem_free(mctx
, search
);
1295 create_search_list(lwres_conf_t
*confdata
) {
1297 dig_searchlist_t
*search
;
1299 debug("create_search_list()");
1302 for (i
= 0; i
< confdata
->searchnxt
; i
++) {
1303 search
= make_searchlist_entry(confdata
->search
[i
]);
1304 ISC_LIST_APPEND(search_list
, search
, link
);
1309 * Setup the system as a whole, reading key information and resolv.conf
1313 setup_system(void) {
1314 dig_searchlist_t
*domain
= NULL
;
1315 lwres_result_t lwresult
;
1316 unsigned int lwresflags
;
1317 isc_result_t result
;
1319 debug("setup_system()");
1321 lwresflags
= LWRES_CONTEXT_SERVERMODE
;
1323 lwresflags
|= LWRES_CONTEXT_USEIPV4
;
1325 lwresflags
|= LWRES_CONTEXT_USEIPV6
;
1327 lwresult
= lwres_context_create(&lwctx
, mctx
, mem_alloc
, mem_free
,
1329 if (lwresult
!= LWRES_R_SUCCESS
)
1330 fatal("lwres_context_create failed");
1332 lwresult
= lwres_conf_parse(lwctx
, RESOLV_CONF
);
1333 if (lwresult
!= LWRES_R_SUCCESS
&& lwresult
!= LWRES_R_NOTFOUND
)
1334 fatal("parse of %s failed", RESOLV_CONF
);
1336 lwconf
= lwres_conf_get(lwctx
);
1338 /* Make the search list */
1339 if (lwconf
->searchnxt
> 0)
1340 create_search_list(lwconf
);
1341 else { /* No search list. Use the domain name if any */
1342 if (lwconf
->domainname
!= NULL
) {
1343 domain
= make_searchlist_entry(lwconf
->domainname
);
1344 ISC_LIST_APPEND(search_list
, domain
, link
);
1350 ndots
= lwconf
->ndots
;
1351 debug("ndots is %d.", ndots
);
1354 /* If user doesn't specify server use nameservers from resolv.conf. */
1355 if (ISC_LIST_EMPTY(server_list
))
1356 copy_server_list(lwconf
, &server_list
);
1358 /* If we don't find a nameserver fall back to localhost */
1359 if (ISC_LIST_EMPTY(server_list
)) {
1361 lwresult
= add_nameserver(lwconf
, "127.0.0.1", AF_INET
);
1362 if (lwresult
!= ISC_R_SUCCESS
)
1363 fatal("add_nameserver failed");
1366 lwresult
= add_nameserver(lwconf
, "::1", AF_INET6
);
1367 if (lwresult
!= ISC_R_SUCCESS
)
1368 fatal("add_nameserver failed");
1371 copy_server_list(lwconf
, &server_list
);
1378 if (keyfile
[0] != 0)
1380 else if (keysecret
[0] != 0)
1383 /* Setup the list of messages for +sigchase */
1384 ISC_LIST_INIT(chase_message_list
);
1385 ISC_LIST_INIT(chase_message_list2
);
1386 dns_name_init(&chase_name
, NULL
);
1388 dns_name_init(&chase_current_name
, NULL
);
1389 dns_name_init(&chase_authority_name
, NULL
);
1392 dns_name_init(&chase_signame
, NULL
);
1396 result
= isc_entropy_getdata(entp
, cookie_secret
,
1397 sizeof(cookie_secret
), NULL
, 0);
1398 if (result
!= ISC_R_SUCCESS
)
1399 fatal("unable to generate cookie secret");
1403 * Override the search list derived from resolv.conf by 'domain'.
1406 set_search_domain(char *domain
) {
1407 dig_searchlist_t
*search
;
1410 search
= make_searchlist_entry(domain
);
1411 ISC_LIST_APPEND(search_list
, search
, link
);
1415 * Setup the ISC and DNS libraries for use by the system.
1419 isc_result_t result
;
1420 isc_logconfig_t
*logconfig
= NULL
;
1422 debug("setup_libs()");
1425 pk11_result_register();
1427 dns_result_register();
1429 result
= isc_net_probeipv4();
1430 if (result
== ISC_R_SUCCESS
)
1431 have_ipv4
= ISC_TRUE
;
1433 result
= isc_net_probeipv6();
1434 if (result
== ISC_R_SUCCESS
)
1435 have_ipv6
= ISC_TRUE
;
1436 if (!have_ipv6
&& !have_ipv4
)
1437 fatal("can't find either v4 or v6 networking");
1439 result
= isc_mem_create(0, 0, &mctx
);
1440 check_result(result
, "isc_mem_create");
1441 isc_mem_setname(mctx
, "dig", NULL
);
1443 result
= isc_log_create(mctx
, &lctx
, &logconfig
);
1444 check_result(result
, "isc_log_create");
1446 isc_log_setcontext(lctx
);
1448 dns_log_setcontext(lctx
);
1450 result
= isc_log_usechannel(logconfig
, "default_debug", NULL
, NULL
);
1451 check_result(result
, "isc_log_usechannel");
1453 isc_log_setdebuglevel(lctx
, 0);
1455 result
= isc_taskmgr_create(mctx
, 1, 0, &taskmgr
);
1456 check_result(result
, "isc_taskmgr_create");
1458 result
= isc_task_create(taskmgr
, 0, &global_task
);
1459 check_result(result
, "isc_task_create");
1460 isc_task_setname(global_task
, "dig", NULL
);
1462 result
= isc_timermgr_create(mctx
, &timermgr
);
1463 check_result(result
, "isc_timermgr_create");
1465 result
= isc_socketmgr_create(mctx
, &socketmgr
);
1466 check_result(result
, "isc_socketmgr_create");
1468 result
= isc_entropy_create(mctx
, &entp
);
1469 check_result(result
, "isc_entropy_create");
1471 result
= dst_lib_init(mctx
, entp
, 0);
1472 check_result(result
, "dst_lib_init");
1473 is_dst_up
= ISC_TRUE
;
1475 result
= isc_mempool_create(mctx
, COMMSIZE
, &commctx
);
1476 check_result(result
, "isc_mempool_create");
1477 isc_mempool_setname(commctx
, "COMMPOOL");
1479 * 6 and 2 set as reasonable parameters for 3 or 4 nameserver
1482 isc_mempool_setfreemax(commctx
, 6);
1483 isc_mempool_setfillcount(commctx
, 2);
1485 result
= isc_mutex_init(&lookup_lock
);
1486 check_result(result
, "isc_mutex_init");
1490 * Add EDNS0 option record to a message. Currently, the only supported
1491 * options are UDP buffer size, the DO bit, and EDNS options
1492 * (e.g., NSID, SIT, client-subnet)
1495 add_opt(dns_message_t
*msg
, isc_uint16_t udpsize
, isc_uint16_t edns
,
1496 isc_boolean_t dnssec
, dns_ednsopt_t
*opts
, size_t count
)
1498 dns_rdataset_t
*rdataset
= NULL
;
1499 isc_result_t result
;
1500 unsigned int flags
= 0;
1504 flags
|= DNS_MESSAGEEXTFLAG_DO
;
1505 result
= dns_message_buildopt(msg
, &rdataset
, edns
, udpsize
, flags
,
1507 check_result(result
, "dns_message_buildopt");
1508 result
= dns_message_setopt(msg
, rdataset
);
1509 check_result(result
, "dns_message_setopt");
1513 * Add a question section to a message, asking for the specified name,
1517 add_question(dns_message_t
*message
, dns_name_t
*name
,
1518 dns_rdataclass_t rdclass
, dns_rdatatype_t rdtype
)
1520 dns_rdataset_t
*rdataset
;
1521 isc_result_t result
;
1523 debug("add_question()");
1525 result
= dns_message_gettemprdataset(message
, &rdataset
);
1526 check_result(result
, "dns_message_gettemprdataset()");
1527 dns_rdataset_makequestion(rdataset
, rdclass
, rdtype
);
1528 ISC_LIST_APPEND(name
->list
, rdataset
, link
);
1532 * Check if we're done with all the queued lookups, which is true iff
1533 * all sockets, sends, and recvs are accounted for (counters == 0),
1534 * and the lookup list is empty.
1535 * If we are done, pass control back out to dighost_shutdown() (which is
1536 * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
1537 * a whole or reseed the lookup list.
1540 check_if_done(void) {
1541 debug("check_if_done()");
1542 debug("list %s", ISC_LIST_EMPTY(lookup_list
) ? "empty" : "full");
1543 if (ISC_LIST_EMPTY(lookup_list
) && current_lookup
== NULL
&&
1545 INSIST(sockcount
== 0);
1546 INSIST(recvcount
== 0);
1547 debug("shutting down");
1553 * Clear out a query when we're done with it. WARNING: This routine
1554 * WILL invalidate the query pointer.
1557 clear_query(dig_query_t
*query
) {
1558 dig_lookup_t
*lookup
;
1560 REQUIRE(query
!= NULL
);
1562 debug("clear_query(%p)", query
);
1564 lookup
= query
->lookup
;
1566 if (lookup
->current_query
== query
)
1567 lookup
->current_query
= NULL
;
1569 if (ISC_LINK_LINKED(query
, link
))
1570 ISC_LIST_UNLINK(lookup
->q
, query
, link
);
1571 if (ISC_LINK_LINKED(query
, clink
))
1572 ISC_LIST_UNLINK(lookup
->connecting
, query
, clink
);
1573 if (ISC_LINK_LINKED(&query
->recvbuf
, link
))
1574 ISC_LIST_DEQUEUE(query
->recvlist
, &query
->recvbuf
,
1576 if (ISC_LINK_LINKED(&query
->lengthbuf
, link
))
1577 ISC_LIST_DEQUEUE(query
->lengthlist
, &query
->lengthbuf
,
1579 INSIST(query
->recvspace
!= NULL
);
1581 if (query
->sock
!= NULL
) {
1582 isc_socket_detach(&query
->sock
);
1584 debug("sockcount=%d", sockcount
);
1586 isc_mempool_put(commctx
, query
->recvspace
);
1587 isc_buffer_invalidate(&query
->recvbuf
);
1588 isc_buffer_invalidate(&query
->lengthbuf
);
1589 if (query
->waiting_senddone
)
1590 query
->pending_free
= ISC_TRUE
;
1592 isc_mem_free(mctx
, query
);
1596 * Try and clear out a lookup if we're done with it. Return ISC_TRUE if
1597 * the lookup was successfully cleared. If ISC_TRUE is returned, the
1598 * lookup pointer has been invalidated.
1600 static isc_boolean_t
1601 try_clear_lookup(dig_lookup_t
*lookup
) {
1604 REQUIRE(lookup
!= NULL
);
1606 debug("try_clear_lookup(%p)", lookup
);
1608 if (ISC_LIST_HEAD(lookup
->q
) != NULL
||
1609 ISC_LIST_HEAD(lookup
->connecting
) != NULL
)
1612 q
= ISC_LIST_HEAD(lookup
->q
);
1614 debug("query to %s still pending", q
->servname
);
1615 q
= ISC_LIST_NEXT(q
, link
);
1618 q
= ISC_LIST_HEAD(lookup
->connecting
);
1620 debug("query to %s still connecting",
1622 q
= ISC_LIST_NEXT(q
, clink
);
1629 * At this point, we know there are no queries on the lookup,
1630 * so can make it go away also.
1632 destroy_lookup(lookup
);
1637 destroy_lookup(dig_lookup_t
*lookup
) {
1642 s
= ISC_LIST_HEAD(lookup
->my_server_list
);
1644 debug("freeing server %p belonging to %p", s
, lookup
);
1646 s
= ISC_LIST_NEXT(s
, link
);
1647 ISC_LIST_DEQUEUE(lookup
->my_server_list
,
1648 (dig_server_t
*)ptr
, link
);
1649 isc_mem_free(mctx
, ptr
);
1651 if (lookup
->sendmsg
!= NULL
)
1652 dns_message_destroy(&lookup
->sendmsg
);
1653 if (lookup
->querysig
!= NULL
) {
1654 debug("freeing buffer %p", lookup
->querysig
);
1655 isc_buffer_free(&lookup
->querysig
);
1657 if (lookup
->timer
!= NULL
)
1658 isc_timer_detach(&lookup
->timer
);
1659 if (lookup
->sendspace
!= NULL
)
1660 isc_mempool_put(commctx
, lookup
->sendspace
);
1662 if (lookup
->tsigctx
!= NULL
)
1663 dst_context_destroy(&lookup
->tsigctx
);
1665 if (lookup
->ecs_addr
!= NULL
)
1666 isc_mem_free(mctx
, lookup
->ecs_addr
);
1668 isc_mem_free(mctx
, lookup
);
1672 * If we can, start the next lookup in the queue running.
1673 * This assumes that the lookup on the head of the queue hasn't been
1674 * started yet. It also removes the lookup from the head of the queue,
1675 * setting the current_lookup pointer pointing to it.
1678 start_lookup(void) {
1679 debug("start_lookup()");
1684 * If there's a current lookup running, we really shouldn't get
1687 INSIST(current_lookup
== NULL
);
1689 current_lookup
= ISC_LIST_HEAD(lookup_list
);
1691 * Put the current lookup somewhere so cancel_all can find it
1693 if (current_lookup
!= NULL
) {
1694 ISC_LIST_DEQUEUE(lookup_list
, current_lookup
, link
);
1696 if (current_lookup
->do_topdown
&&
1697 !current_lookup
->rdtype_sigchaseset
) {
1698 dst_key_t
*trustedkey
= NULL
;
1699 isc_buffer_t
*b
= NULL
;
1701 isc_result_t result
;
1702 dns_name_t query_name
;
1703 dns_name_t
*key_name
;
1706 result
= get_trusted_key(mctx
);
1707 if (result
!= ISC_R_SUCCESS
) {
1708 printf("\n;; No trusted key, "
1709 "+sigchase option is disabled\n");
1710 current_lookup
->sigchase
= ISC_FALSE
;
1713 dns_name_init(&query_name
, NULL
);
1714 nameFromString(current_lookup
->textname
, &query_name
);
1716 for (i
= 0; i
< tk_list
.nb_tk
; i
++) {
1717 key_name
= dst_key_name(tk_list
.key
[i
]);
1719 if (dns_name_issubdomain(&query_name
,
1720 key_name
) == ISC_TRUE
)
1721 trustedkey
= tk_list
.key
[i
];
1723 * Verify temp is really the lowest
1727 if (trustedkey
== NULL
) {
1728 printf("\n;; The queried zone: ");
1729 dns_name_print(&query_name
, stdout
);
1730 printf(" isn't a subdomain of any Trusted Keys"
1731 ": +sigchase option is disable\n");
1732 current_lookup
->sigchase
= ISC_FALSE
;
1733 free_name(&query_name
, mctx
);
1736 free_name(&query_name
, mctx
);
1738 current_lookup
->rdtype_sigchase
1739 = current_lookup
->rdtype
;
1740 current_lookup
->rdtype_sigchaseset
1741 = current_lookup
->rdtypeset
;
1742 current_lookup
->rdtype
= dns_rdatatype_ns
;
1744 current_lookup
->qrdtype_sigchase
1745 = current_lookup
->qrdtype
;
1746 current_lookup
->qrdtype
= dns_rdatatype_ns
;
1748 current_lookup
->rdclass_sigchase
1749 = current_lookup
->rdclass
;
1750 current_lookup
->rdclass_sigchaseset
1751 = current_lookup
->rdclassset
;
1752 current_lookup
->rdclass
= dns_rdataclass_in
;
1754 strlcpy(current_lookup
->textnamesigchase
,
1755 current_lookup
->textname
, MXNAME
);
1757 current_lookup
->trace_root_sigchase
= ISC_TRUE
;
1759 result
= isc_buffer_allocate(mctx
, &b
, BUFSIZE
);
1760 check_result(result
, "isc_buffer_allocate");
1761 result
= dns_name_totext(dst_key_name(trustedkey
),
1763 check_result(result
, "dns_name_totext");
1764 isc_buffer_usedregion(b
, &r
);
1765 r
.base
[r
.length
] = '\0';
1766 strlcpy(current_lookup
->textname
, (char*)r
.base
,
1768 isc_buffer_free(&b
);
1770 nameFromString(current_lookup
->textnamesigchase
,
1773 dns_name_init(&chase_authority_name
, NULL
);
1777 if (setup_lookup(current_lookup
))
1778 do_lookup(current_lookup
);
1779 else if (next_origin(current_lookup
))
1780 check_next_lookup(current_lookup
);
1787 * If we can, clear the current lookup and start the next one running.
1788 * This calls try_clear_lookup, so may invalidate the lookup pointer.
1791 check_next_lookup(dig_lookup_t
*lookup
) {
1795 debug("check_next_lookup(%p)", lookup
);
1797 if (ISC_LIST_HEAD(lookup
->q
) != NULL
) {
1798 debug("still have a worker");
1801 if (try_clear_lookup(lookup
)) {
1802 current_lookup
= NULL
;
1808 * Create and queue a new lookup as a followup to the current lookup,
1809 * based on the supplied message and section. This is used in trace and
1810 * name server search modes to start a new lookup using servers from
1811 * NS records in a reply. Returns the number of followup lookups made.
1814 followup_lookup(dns_message_t
*msg
, dig_query_t
*query
, dns_section_t section
)
1816 dig_lookup_t
*lookup
= NULL
;
1817 dig_server_t
*srv
= NULL
;
1818 dns_rdataset_t
*rdataset
= NULL
;
1819 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1820 dns_name_t
*name
= NULL
;
1821 isc_result_t result
;
1822 isc_boolean_t success
= ISC_FALSE
;
1825 isc_result_t lresult
, addresses_result
;
1826 char bad_namestr
[DNS_NAME_FORMATSIZE
];
1828 isc_boolean_t horizontal
= ISC_FALSE
, bad
= ISC_FALSE
;
1832 debug("following up %s", query
->lookup
->textname
);
1834 addresses_result
= ISC_R_SUCCESS
;
1835 bad_namestr
[0] = '\0';
1836 for (result
= dns_message_firstname(msg
, section
);
1837 result
== ISC_R_SUCCESS
;
1838 result
= dns_message_nextname(msg
, section
)) {
1840 dns_message_currentname(msg
, section
, &name
);
1842 if (section
== DNS_SECTION_AUTHORITY
) {
1844 result
= dns_message_findtype(name
, dns_rdatatype_soa
,
1846 if (result
== ISC_R_SUCCESS
)
1850 result
= dns_message_findtype(name
, dns_rdatatype_ns
, 0,
1852 if (result
!= ISC_R_SUCCESS
)
1855 debug("found NS set");
1857 if (query
->lookup
->trace
&& !query
->lookup
->trace_root
) {
1858 dns_namereln_t namereln
;
1859 unsigned int nlabels
;
1862 domain
= dns_fixedname_name(&query
->lookup
->fdomain
);
1863 namereln
= dns_name_fullcompare(name
, domain
,
1865 if (namereln
== dns_namereln_equal
) {
1867 printf(";; BAD (HORIZONTAL) REFERRAL\n");
1868 horizontal
= ISC_TRUE
;
1869 } else if (namereln
!= dns_namereln_subdomain
) {
1871 printf(";; BAD REFERRAL\n");
1877 for (result
= dns_rdataset_first(rdataset
);
1878 result
== ISC_R_SUCCESS
;
1879 result
= dns_rdataset_next(rdataset
)) {
1880 char namestr
[DNS_NAME_FORMATSIZE
];
1883 if (query
->lookup
->trace_root
&&
1884 query
->lookup
->nsfound
>= MXSERV
)
1887 dns_rdataset_current(rdataset
, &rdata
);
1889 query
->lookup
->nsfound
++;
1890 result
= dns_rdata_tostruct(&rdata
, &ns
, NULL
);
1891 check_result(result
, "dns_rdata_tostruct");
1892 dns_name_format(&ns
.name
, namestr
, sizeof(namestr
));
1893 dns_rdata_freestruct(&ns
);
1895 /* Initialize lookup if we've not yet */
1896 debug("found NS %s", namestr
);
1900 lookup
= requeue_lookup(query
->lookup
,
1902 cancel_lookup(query
->lookup
);
1903 lookup
->doing_xfr
= ISC_FALSE
;
1904 if (!lookup
->trace_root
&&
1905 section
== DNS_SECTION_ANSWER
)
1906 lookup
->trace
= ISC_FALSE
;
1908 lookup
->trace
= query
->lookup
->trace
;
1909 lookup
->ns_search_only
=
1910 query
->lookup
->ns_search_only
;
1911 lookup
->trace_root
= ISC_FALSE
;
1912 if (lookup
->ns_search_only
)
1913 lookup
->recurse
= ISC_FALSE
;
1914 domain
= dns_fixedname_name(&lookup
->fdomain
);
1915 dns_name_copy(name
, domain
, NULL
);
1917 debug("adding server %s", namestr
);
1918 num
= getaddresses(lookup
, namestr
, &lresult
);
1919 if (lresult
!= ISC_R_SUCCESS
) {
1920 printf("couldn't get address for '%s': %s\n",
1921 namestr
, isc_result_totext(lresult
));
1922 if (addresses_result
== ISC_R_SUCCESS
) {
1923 addresses_result
= lresult
;
1924 strcpy(bad_namestr
, namestr
);
1928 dns_rdata_reset(&rdata
);
1931 if (numLookups
== 0 && addresses_result
!= ISC_R_SUCCESS
) {
1932 fatal("couldn't get address for '%s': %s",
1933 bad_namestr
, isc_result_totext(result
));
1936 if (lookup
== NULL
&&
1937 section
== DNS_SECTION_ANSWER
&&
1938 (query
->lookup
->trace
|| query
->lookup
->ns_search_only
))
1939 return (followup_lookup(msg
, query
, DNS_SECTION_AUTHORITY
));
1942 * Randomize the order the nameserver will be tried.
1944 if (numLookups
> 1) {
1946 dig_serverlist_t my_server_list
;
1949 ISC_LIST_INIT(my_server_list
);
1952 for (srv
= ISC_LIST_HEAD(lookup
->my_server_list
);
1954 srv
= ISC_LIST_HEAD(lookup
->my_server_list
)) {
1958 next
= ISC_LIST_NEXT(srv
, link
);
1959 while (j
-- > 0 && next
!= NULL
) {
1961 next
= ISC_LIST_NEXT(srv
, link
);
1963 ISC_LIST_DEQUEUE(lookup
->my_server_list
, srv
, link
);
1964 ISC_LIST_APPEND(my_server_list
, srv
, link
);
1967 ISC_LIST_APPENDLIST(lookup
->my_server_list
,
1968 my_server_list
, link
);
1971 return (numLookups
);
1975 * Create and queue a new lookup using the next origin from the search
1976 * list, read in setup_system().
1978 * Return ISC_TRUE iff there was another searchlist entry.
1980 static isc_boolean_t
1981 next_origin(dig_lookup_t
*oldlookup
) {
1982 dig_lookup_t
*newlookup
;
1983 dig_searchlist_t
*search
;
1984 dns_fixedname_t fixed
;
1986 isc_result_t result
;
1990 debug("next_origin()");
1991 debug("following up %s", oldlookup
->textname
);
1995 * We're not using a search list, so don't even think
1996 * about finding the next entry.
2001 * Check for a absolute name or ndots being met.
2003 dns_fixedname_init(&fixed
);
2004 name
= dns_fixedname_name(&fixed
);
2005 result
= dns_name_fromstring2(name
, oldlookup
->textname
, NULL
,
2007 if (result
== ISC_R_SUCCESS
&&
2008 (dns_name_isabsolute(name
) ||
2009 (int)dns_name_countlabels(name
) > ndots
))
2012 if (oldlookup
->origin
== NULL
&& !oldlookup
->need_search
)
2014 * Then we just did rootorg; there's nothing left.
2017 if (oldlookup
->origin
== NULL
&& oldlookup
->need_search
) {
2018 newlookup
= requeue_lookup(oldlookup
, ISC_TRUE
);
2019 newlookup
->origin
= ISC_LIST_HEAD(search_list
);
2020 newlookup
->need_search
= ISC_FALSE
;
2022 search
= ISC_LIST_NEXT(oldlookup
->origin
, link
);
2023 if (search
== NULL
&& oldlookup
->done_as_is
)
2025 newlookup
= requeue_lookup(oldlookup
, ISC_TRUE
);
2026 newlookup
->origin
= search
;
2028 cancel_lookup(oldlookup
);
2033 * Insert an SOA record into the sendmessage in a lookup. Used for
2034 * creating IXFR queries.
2037 insert_soa(dig_lookup_t
*lookup
) {
2038 isc_result_t result
;
2039 dns_rdata_soa_t soa
;
2040 dns_rdata_t
*rdata
= NULL
;
2041 dns_rdatalist_t
*rdatalist
= NULL
;
2042 dns_rdataset_t
*rdataset
= NULL
;
2043 dns_name_t
*soaname
= NULL
;
2045 debug("insert_soa()");
2047 soa
.serial
= lookup
->ixfr_serial
;
2052 soa
.common
.rdclass
= lookup
->rdclass
;
2053 soa
.common
.rdtype
= dns_rdatatype_soa
;
2055 dns_name_init(&soa
.origin
, NULL
);
2056 dns_name_init(&soa
.contact
, NULL
);
2058 dns_name_clone(dns_rootname
, &soa
.origin
);
2059 dns_name_clone(dns_rootname
, &soa
.contact
);
2061 isc_buffer_init(&lookup
->rdatabuf
, lookup
->rdatastore
,
2062 sizeof(lookup
->rdatastore
));
2064 result
= dns_message_gettemprdata(lookup
->sendmsg
, &rdata
);
2065 check_result(result
, "dns_message_gettemprdata");
2067 result
= dns_rdata_fromstruct(rdata
, lookup
->rdclass
,
2068 dns_rdatatype_soa
, &soa
,
2070 check_result(result
, "isc_rdata_fromstruct");
2072 result
= dns_message_gettemprdatalist(lookup
->sendmsg
, &rdatalist
);
2073 check_result(result
, "dns_message_gettemprdatalist");
2075 result
= dns_message_gettemprdataset(lookup
->sendmsg
, &rdataset
);
2076 check_result(result
, "dns_message_gettemprdataset");
2078 dns_rdatalist_init(rdatalist
);
2079 rdatalist
->type
= dns_rdatatype_soa
;
2080 rdatalist
->rdclass
= lookup
->rdclass
;
2081 rdatalist
->covers
= 0;
2083 ISC_LIST_INIT(rdatalist
->rdata
);
2084 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
2086 dns_rdatalist_tordataset(rdatalist
, rdataset
);
2088 result
= dns_message_gettempname(lookup
->sendmsg
, &soaname
);
2089 check_result(result
, "dns_message_gettempname");
2090 dns_name_init(soaname
, NULL
);
2091 dns_name_clone(lookup
->name
, soaname
);
2092 ISC_LIST_INIT(soaname
->list
);
2093 ISC_LIST_APPEND(soaname
->list
, rdataset
, link
);
2094 dns_message_addname(lookup
->sendmsg
, soaname
, DNS_SECTION_AUTHORITY
);
2097 #ifdef ISC_PLATFORM_USESIT
2099 compute_cookie(unsigned char *clientcookie
, size_t len
) {
2100 /* XXXMPA need to fix, should be per server. */
2102 memmove(clientcookie
, cookie_secret
, 8);
2107 * Setup the supplied lookup structure, making it ready to start sending
2108 * queries to servers. Create and initialize the message to be sent as
2109 * well as the query structures and buffer space for the replies. If the
2110 * server list is empty, clone it from the system default list.
2113 setup_lookup(dig_lookup_t
*lookup
) {
2114 isc_result_t result
;
2120 dns_compress_t cctx
;
2123 #ifdef ISC_PLATFORM_USESIT
2128 char utf8_textname
[MXNAME
], utf8_origin
[MXNAME
], idn_textname
[MXNAME
];
2132 result
= dns_name_settotextfilter(output_filter
);
2133 check_result(result
, "dns_name_settotextfilter");
2136 REQUIRE(lookup
!= NULL
);
2139 debug("setup_lookup(%p)", lookup
);
2141 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTRENDER
,
2143 check_result(result
, "dns_message_create");
2145 if (lookup
->new_search
) {
2146 debug("resetting lookup counter.");
2150 if (ISC_LIST_EMPTY(lookup
->my_server_list
)) {
2151 debug("cloning server list");
2152 clone_server_list(server_list
, &lookup
->my_server_list
);
2154 result
= dns_message_gettempname(lookup
->sendmsg
, &lookup
->name
);
2155 check_result(result
, "dns_message_gettempname");
2156 dns_name_init(lookup
->name
, NULL
);
2158 isc_buffer_init(&lookup
->namebuf
, lookup
->namespace,
2159 sizeof(lookup
->namespace));
2160 isc_buffer_init(&lookup
->onamebuf
, lookup
->onamespace
,
2161 sizeof(lookup
->onamespace
));
2165 * We cannot convert `textname' and `origin' separately.
2166 * `textname' doesn't contain TLD, but local mapping needs
2169 mr
= idn_encodename(IDN_LOCALCONV
| IDN_DELIMMAP
, lookup
->textname
,
2170 utf8_textname
, sizeof(utf8_textname
));
2171 idn_check_result(mr
, "convert textname to UTF-8");
2175 * If the name has too many dots, force the origin to be NULL
2176 * (which produces an absolute lookup). Otherwise, take the origin
2177 * we have if there's one in the struct already. If it's NULL,
2178 * take the first entry in the searchlist iff either usesearch
2179 * is TRUE or we got a domain line in the resolv.conf file.
2181 if (lookup
->new_search
) {
2183 if ((count_dots(utf8_textname
) >= ndots
) || !usesearch
) {
2184 lookup
->origin
= NULL
; /* Force abs lookup */
2185 lookup
->done_as_is
= ISC_TRUE
;
2186 lookup
->need_search
= usesearch
;
2187 } else if (lookup
->origin
== NULL
&& usesearch
) {
2188 lookup
->origin
= ISC_LIST_HEAD(search_list
);
2189 lookup
->need_search
= ISC_FALSE
;
2192 if ((count_dots(lookup
->textname
) >= ndots
) || !usesearch
) {
2193 lookup
->origin
= NULL
; /* Force abs lookup */
2194 lookup
->done_as_is
= ISC_TRUE
;
2195 lookup
->need_search
= usesearch
;
2196 } else if (lookup
->origin
== NULL
&& usesearch
) {
2197 lookup
->origin
= ISC_LIST_HEAD(search_list
);
2198 lookup
->need_search
= ISC_FALSE
;
2204 if (lookup
->origin
!= NULL
) {
2205 mr
= idn_encodename(IDN_LOCALCONV
| IDN_DELIMMAP
,
2206 lookup
->origin
->origin
, utf8_origin
,
2207 sizeof(utf8_origin
));
2208 idn_check_result(mr
, "convert origin to UTF-8");
2209 mr
= append_textname(utf8_textname
, utf8_origin
,
2210 sizeof(utf8_textname
));
2211 idn_check_result(mr
, "append origin to textname");
2213 mr
= idn_encodename(idnoptions
| IDN_LOCALMAP
| IDN_NAMEPREP
|
2214 IDN_IDNCONV
| IDN_LENCHECK
, utf8_textname
,
2215 idn_textname
, sizeof(idn_textname
));
2216 idn_check_result(mr
, "convert UTF-8 textname to IDN encoding");
2218 if (lookup
->origin
!= NULL
) {
2219 debug("trying origin %s", lookup
->origin
->origin
);
2220 result
= dns_message_gettempname(lookup
->sendmsg
,
2222 check_result(result
, "dns_message_gettempname");
2223 dns_name_init(lookup
->oname
, NULL
);
2224 /* XXX Helper funct to conv char* to name? */
2225 len
= strlen(lookup
->origin
->origin
);
2226 isc_buffer_init(&b
, lookup
->origin
->origin
, len
);
2227 isc_buffer_add(&b
, len
);
2228 result
= dns_name_fromtext(lookup
->oname
, &b
, dns_rootname
,
2229 0, &lookup
->onamebuf
);
2230 if (result
!= ISC_R_SUCCESS
) {
2231 dns_message_puttempname(lookup
->sendmsg
,
2233 dns_message_puttempname(lookup
->sendmsg
,
2235 fatal("'%s' is not in legal name syntax (%s)",
2236 lookup
->origin
->origin
,
2237 isc_result_totext(result
));
2239 if (lookup
->trace
&& lookup
->trace_root
) {
2240 dns_name_clone(dns_rootname
, lookup
->name
);
2242 dns_fixedname_t fixed
;
2245 dns_fixedname_init(&fixed
);
2246 name
= dns_fixedname_name(&fixed
);
2247 len
= strlen(lookup
->textname
);
2248 isc_buffer_init(&b
, lookup
->textname
, len
);
2249 isc_buffer_add(&b
, len
);
2250 result
= dns_name_fromtext(name
, &b
, NULL
, 0, NULL
);
2251 if (result
== ISC_R_SUCCESS
&&
2252 !dns_name_isabsolute(name
))
2253 result
= dns_name_concatenate(name
,
2257 else if (result
== ISC_R_SUCCESS
)
2258 result
= dns_name_copy(name
, lookup
->name
,
2260 if (result
!= ISC_R_SUCCESS
) {
2261 dns_message_puttempname(lookup
->sendmsg
,
2263 dns_message_puttempname(lookup
->sendmsg
,
2265 if (result
== DNS_R_NAMETOOLONG
)
2267 fatal("'%s' is not in legal name syntax (%s)",
2269 isc_result_totext(result
));
2272 dns_message_puttempname(lookup
->sendmsg
, &lookup
->oname
);
2276 debug("using root origin");
2277 if (lookup
->trace
&& lookup
->trace_root
)
2278 dns_name_clone(dns_rootname
, lookup
->name
);
2281 len
= strlen(idn_textname
);
2282 isc_buffer_init(&b
, idn_textname
, len
);
2283 isc_buffer_add(&b
, len
);
2284 result
= dns_name_fromtext(lookup
->name
, &b
,
2288 len
= strlen(lookup
->textname
);
2289 isc_buffer_init(&b
, lookup
->textname
, len
);
2290 isc_buffer_add(&b
, len
);
2291 result
= dns_name_fromtext(lookup
->name
, &b
,
2296 if (result
!= ISC_R_SUCCESS
) {
2297 dns_message_puttempname(lookup
->sendmsg
,
2299 fatal("'%s' is not a legal name "
2300 "(%s)", lookup
->textname
,
2301 isc_result_totext(result
));
2304 dns_name_format(lookup
->name
, store
, sizeof(store
));
2305 trying(store
, lookup
);
2306 INSIST(dns_name_isabsolute(lookup
->name
));
2308 isc_random_get(&id
);
2309 lookup
->sendmsg
->id
= (unsigned short)id
& 0xFFFF;
2310 lookup
->sendmsg
->opcode
= dns_opcode_query
;
2311 lookup
->msgcounter
= 0;
2313 * If this is a trace request, completely disallow recursion, since
2314 * it's meaningless for traces.
2316 if (lookup
->trace
|| (lookup
->ns_search_only
&& !lookup
->trace_root
))
2317 lookup
->recurse
= ISC_FALSE
;
2319 if (lookup
->recurse
&&
2320 lookup
->rdtype
!= dns_rdatatype_axfr
&&
2321 lookup
->rdtype
!= dns_rdatatype_ixfr
) {
2322 debug("recursive query");
2323 lookup
->sendmsg
->flags
|= DNS_MESSAGEFLAG_RD
;
2327 if (lookup
->aaonly
) {
2329 lookup
->sendmsg
->flags
|= DNS_MESSAGEFLAG_AA
;
2332 if (lookup
->adflag
) {
2334 lookup
->sendmsg
->flags
|= DNS_MESSAGEFLAG_AD
;
2337 if (lookup
->cdflag
) {
2339 lookup
->sendmsg
->flags
|= DNS_MESSAGEFLAG_CD
;
2342 dns_message_addname(lookup
->sendmsg
, lookup
->name
,
2343 DNS_SECTION_QUESTION
);
2345 if (lookup
->trace
&& lookup
->trace_root
) {
2346 lookup
->qrdtype
= lookup
->rdtype
;
2347 lookup
->rdtype
= dns_rdatatype_ns
;
2350 if ((lookup
->rdtype
== dns_rdatatype_axfr
) ||
2351 (lookup
->rdtype
== dns_rdatatype_ixfr
)) {
2353 * Force TCP mode if we're doing an axfr.
2355 if (lookup
->rdtype
== dns_rdatatype_axfr
) {
2356 lookup
->doing_xfr
= ISC_TRUE
;
2357 lookup
->tcp_mode
= ISC_TRUE
;
2358 } else if (lookup
->tcp_mode
) {
2359 lookup
->doing_xfr
= ISC_TRUE
;
2363 add_question(lookup
->sendmsg
, lookup
->name
, lookup
->rdclass
,
2367 if (lookup
->rdtype
== dns_rdatatype_ixfr
)
2370 /* XXX Insist this? */
2371 lookup
->tsigctx
= NULL
;
2372 lookup
->querysig
= NULL
;
2374 debug("initializing keys");
2375 result
= dns_message_settsigkey(lookup
->sendmsg
, key
);
2376 check_result(result
, "dns_message_settsigkey");
2379 lookup
->sendspace
= isc_mempool_get(commctx
);
2380 if (lookup
->sendspace
== NULL
)
2381 fatal("memory allocation failure");
2383 result
= dns_compress_init(&cctx
, -1, mctx
);
2384 check_result(result
, "dns_compress_init");
2386 debug("starting to render the message");
2387 isc_buffer_init(&lookup
->renderbuf
, lookup
->sendspace
, COMMSIZE
);
2388 result
= dns_message_renderbegin(lookup
->sendmsg
, &cctx
,
2389 &lookup
->renderbuf
);
2390 check_result(result
, "dns_message_renderbegin");
2391 if (lookup
->udpsize
> 0 || lookup
->dnssec
||
2392 lookup
->edns
> -1 || lookup
->ecs_addr
!= NULL
)
2394 dns_ednsopt_t opts
[DNS_EDNSOPTIONS
];
2397 if (lookup
->udpsize
== 0)
2398 lookup
->udpsize
= 4096;
2399 if (lookup
->edns
< 0)
2403 INSIST(i
< DNS_EDNSOPTIONS
);
2404 opts
[i
].code
= DNS_OPT_NSID
;
2406 opts
[i
].value
= NULL
;
2410 if (lookup
->ecs_addr
!= NULL
) {
2411 isc_uint32_t prefixlen
;
2412 struct sockaddr
*sa
;
2413 struct sockaddr_in
*sin
;
2414 struct sockaddr_in6
*sin6
;
2417 sa
= &lookup
->ecs_addr
->type
.sa
;
2418 prefixlen
= lookup
->ecs_addr
->length
;
2420 /* Round up prefix len to a multiple of 8 */
2421 addrl
= (prefixlen
+ 7) / 8;
2423 INSIST(i
< DNS_EDNSOPTIONS
);
2424 opts
[i
].code
= DNS_OPT_CLIENT_SUBNET
;
2425 opts
[i
].length
= (isc_uint16_t
) addrl
+ 4;
2426 check_result(result
, "isc_buffer_allocate");
2427 isc_buffer_init(&b
, ecsbuf
, sizeof(ecsbuf
));
2428 if (sa
->sa_family
== AF_INET
) {
2429 sin
= (struct sockaddr_in
*) sa
;
2430 isc_buffer_putuint16(&b
, 1);
2431 isc_buffer_putuint8(&b
, prefixlen
);
2432 isc_buffer_putuint8(&b
, 0);
2433 isc_buffer_putmem(&b
,
2434 (isc_uint8_t
*) &sin
->sin_addr
,
2435 (unsigned int) addrl
);
2437 sin6
= (struct sockaddr_in6
*) sa
;
2438 isc_buffer_putuint16(&b
, 2);
2439 isc_buffer_putuint8(&b
, prefixlen
);
2440 isc_buffer_putuint8(&b
, 0);
2441 isc_buffer_putmem(&b
,
2442 (isc_uint8_t
*) &sin6
->sin6_addr
,
2443 (unsigned int) addrl
);
2446 opts
[i
].value
= (isc_uint8_t
*) ecsbuf
;
2450 #ifdef ISC_PLATFORM_USESIT
2452 INSIST(i
< DNS_EDNSOPTIONS
);
2453 opts
[i
].code
= DNS_OPT_SIT
;
2454 if (lookup
->sitvalue
!= NULL
) {
2455 isc_buffer_init(&b
, sitbuf
, sizeof(sitbuf
));
2456 result
= isc_hex_decodestring(lookup
->sitvalue
,
2458 check_result(result
, "isc_hex_decodestring");
2459 opts
[i
].value
= isc_buffer_base(&b
);
2460 opts
[i
].length
= isc_buffer_usedlength(&b
);
2462 compute_cookie(cookie
, sizeof(cookie
));
2464 opts
[i
].value
= cookie
;
2470 if (lookup
->expire
) {
2471 INSIST(i
< DNS_EDNSOPTIONS
);
2472 opts
[i
].code
= DNS_OPT_EXPIRE
;
2474 opts
[i
].value
= NULL
;
2478 add_opt(lookup
->sendmsg
, lookup
->udpsize
,
2479 lookup
->edns
, lookup
->dnssec
, opts
, i
);
2482 result
= dns_message_rendersection(lookup
->sendmsg
,
2483 DNS_SECTION_QUESTION
, 0);
2484 check_result(result
, "dns_message_rendersection");
2485 result
= dns_message_rendersection(lookup
->sendmsg
,
2486 DNS_SECTION_AUTHORITY
, 0);
2487 check_result(result
, "dns_message_rendersection");
2488 result
= dns_message_renderend(lookup
->sendmsg
);
2489 check_result(result
, "dns_message_renderend");
2490 debug("done rendering");
2492 dns_compress_invalidate(&cctx
);
2495 * Force TCP mode if the request is larger than 512 bytes.
2497 if (isc_buffer_usedlength(&lookup
->renderbuf
) > 512)
2498 lookup
->tcp_mode
= ISC_TRUE
;
2500 lookup
->pending
= ISC_FALSE
;
2502 for (serv
= ISC_LIST_HEAD(lookup
->my_server_list
);
2504 serv
= ISC_LIST_NEXT(serv
, link
)) {
2505 query
= isc_mem_allocate(mctx
, sizeof(dig_query_t
));
2507 fatal("memory allocation failure in %s:%d",
2508 __FILE__
, __LINE__
);
2509 debug("create query %p linked to lookup %p",
2511 query
->lookup
= lookup
;
2512 query
->waiting_connect
= ISC_FALSE
;
2513 query
->waiting_senddone
= ISC_FALSE
;
2514 query
->pending_free
= ISC_FALSE
;
2515 query
->recv_made
= ISC_FALSE
;
2516 query
->first_pass
= ISC_TRUE
;
2517 query
->first_soa_rcvd
= ISC_FALSE
;
2518 query
->second_rr_rcvd
= ISC_FALSE
;
2519 query
->first_repeat_rcvd
= ISC_FALSE
;
2520 query
->warn_id
= ISC_TRUE
;
2521 query
->first_rr_serial
= 0;
2522 query
->second_rr_serial
= 0;
2523 query
->servname
= serv
->servername
;
2524 query
->userarg
= serv
->userarg
;
2525 query
->rr_count
= 0;
2526 query
->msg_count
= 0;
2527 query
->byte_count
= 0;
2528 query
->ixfr_axfr
= ISC_FALSE
;
2529 ISC_LIST_INIT(query
->recvlist
);
2530 ISC_LIST_INIT(query
->lengthlist
);
2532 query
->recvspace
= isc_mempool_get(commctx
);
2533 if (query
->recvspace
== NULL
)
2534 fatal("memory allocation failure");
2536 isc_buffer_init(&query
->recvbuf
, query
->recvspace
, COMMSIZE
);
2537 isc_buffer_init(&query
->lengthbuf
, query
->lengthspace
, 2);
2538 isc_buffer_init(&query
->slbuf
, query
->slspace
, 2);
2539 query
->sendbuf
= lookup
->renderbuf
;
2541 ISC_LINK_INIT(query
, clink
);
2542 ISC_LINK_INIT(query
, link
);
2543 ISC_LIST_ENQUEUE(lookup
->q
, query
, link
);
2546 /* XXX qrflag, print_query, etc... */
2547 if (!ISC_LIST_EMPTY(lookup
->q
) && qr
) {
2549 printmessage(ISC_LIST_HEAD(lookup
->q
), lookup
->sendmsg
,
2556 * Event handler for send completion. Track send counter, and clear out
2557 * the query if the send was canceled.
2560 send_done(isc_task_t
*_task
, isc_event_t
*event
) {
2561 isc_socketevent_t
*sevent
= (isc_socketevent_t
*)event
;
2562 isc_buffer_t
*b
= NULL
;
2563 dig_query_t
*query
, *next
;
2566 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
2572 debug("send_done()");
2574 debug("sendcount=%d", sendcount
);
2575 INSIST(sendcount
>= 0);
2577 for (b
= ISC_LIST_HEAD(sevent
->bufferlist
);
2579 b
= ISC_LIST_HEAD(sevent
->bufferlist
)) {
2580 ISC_LIST_DEQUEUE(sevent
->bufferlist
, b
, link
);
2581 isc_mem_free(mctx
, b
);
2584 query
= event
->ev_arg
;
2585 query
->waiting_senddone
= ISC_FALSE
;
2588 if (l
->ns_search_only
&& !l
->trace_root
&& !l
->tcp_mode
) {
2589 debug("sending next, since searching");
2590 next
= ISC_LIST_NEXT(query
, link
);
2595 isc_event_free(&event
);
2597 if (query
->pending_free
)
2598 isc_mem_free(mctx
, query
);
2605 * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
2606 * IO sockets. The cancel handlers should take care of cleaning up the
2607 * query and lookup structures
2610 cancel_lookup(dig_lookup_t
*lookup
) {
2611 dig_query_t
*query
, *next
;
2613 debug("cancel_lookup()");
2614 query
= ISC_LIST_HEAD(lookup
->q
);
2615 while (query
!= NULL
) {
2616 next
= ISC_LIST_NEXT(query
, link
);
2617 if (query
->sock
!= NULL
) {
2618 isc_socket_cancel(query
->sock
, global_task
,
2619 ISC_SOCKCANCEL_ALL
);
2626 if (lookup
->timer
!= NULL
)
2627 isc_timer_detach(&lookup
->timer
);
2628 lookup
->pending
= ISC_FALSE
;
2629 lookup
->retries
= 0;
2633 bringup_timer(dig_query_t
*query
, unsigned int default_timeout
) {
2635 unsigned int local_timeout
;
2636 isc_result_t result
;
2638 debug("bringup_timer()");
2640 * If the timer already exists, that means we're calling this
2641 * a second time (for a retry). Don't need to recreate it,
2645 if (ISC_LIST_NEXT(query
, link
) != NULL
)
2646 local_timeout
= SERVER_TIMEOUT
;
2649 local_timeout
= default_timeout
;
2651 local_timeout
= timeout
;
2653 debug("have local timeout of %d", local_timeout
);
2654 isc_interval_set(&l
->interval
, local_timeout
, 0);
2655 if (l
->timer
!= NULL
)
2656 isc_timer_detach(&l
->timer
);
2657 result
= isc_timer_create(timermgr
, isc_timertype_once
, NULL
,
2658 &l
->interval
, global_task
, connect_timeout
,
2660 check_result(result
, "isc_timer_create");
2664 force_timeout(dig_lookup_t
*l
, dig_query_t
*query
) {
2667 debug("force_timeout ()");
2668 event
= isc_event_allocate(mctx
, query
, ISC_TIMEREVENT_IDLE
,
2670 sizeof(isc_event_t
));
2671 if (event
== NULL
) {
2672 fatal("isc_event_allocate: %s",
2673 isc_result_totext(ISC_R_NOMEMORY
));
2675 isc_task_send(global_task
, &event
);
2678 * The timer may have expired if, for example, get_address() takes
2679 * long time and the timer was running on a different thread.
2680 * We need to cancel the possible timeout event not to confuse
2681 * ourselves due to the duplicate events.
2683 if (l
->timer
!= NULL
)
2684 isc_timer_detach(&l
->timer
);
2689 connect_done(isc_task_t
*task
, isc_event_t
*event
);
2692 * Unlike send_udp, this can't be called multiple times with the same
2693 * query. When we retry TCP, we requeue the whole lookup, which should
2697 send_tcp_connect(dig_query_t
*query
) {
2698 isc_result_t result
;
2702 debug("send_tcp_connect(%p)", query
);
2705 query
->waiting_connect
= ISC_TRUE
;
2706 query
->lookup
->current_query
= query
;
2707 result
= get_address(query
->servname
, port
, &query
->sockaddr
);
2708 if (result
!= ISC_R_SUCCESS
) {
2710 * This servname doesn't have an address. Try the next server
2711 * by triggering an immediate 'timeout' (we lie, but the effect
2714 force_timeout(l
, query
);
2718 if (specified_source
&&
2719 (isc_sockaddr_pf(&query
->sockaddr
) !=
2720 isc_sockaddr_pf(&bind_address
))) {
2721 printf(";; Skipping server %s, incompatible "
2722 "address family\n", query
->servname
);
2723 query
->waiting_connect
= ISC_FALSE
;
2724 next
= ISC_LIST_NEXT(query
, link
);
2728 printf(";; No acceptable nameservers\n");
2729 check_next_lookup(l
);
2732 send_tcp_connect(next
);
2736 INSIST(query
->sock
== NULL
);
2738 if (keep
!= NULL
&& isc_sockaddr_equal(&keepaddr
, &query
->sockaddr
)) {
2740 isc_socket_attach(keep
, &query
->sock
);
2741 query
->waiting_connect
= ISC_FALSE
;
2742 launch_next_query(query
, ISC_TRUE
);
2746 result
= isc_socket_create(socketmgr
,
2747 isc_sockaddr_pf(&query
->sockaddr
),
2748 isc_sockettype_tcp
, &query
->sock
);
2749 check_result(result
, "isc_socket_create");
2751 debug("sockcount=%d", sockcount
);
2752 if (specified_source
)
2753 result
= isc_socket_bind(query
->sock
, &bind_address
,
2754 ISC_SOCKET_REUSEADDRESS
);
2756 if ((isc_sockaddr_pf(&query
->sockaddr
) == AF_INET
) &&
2758 isc_sockaddr_any(&bind_any
);
2760 isc_sockaddr_any6(&bind_any
);
2761 result
= isc_socket_bind(query
->sock
, &bind_any
, 0);
2763 check_result(result
, "isc_socket_bind");
2764 bringup_timer(query
, TCP_TIMEOUT
);
2765 result
= isc_socket_connect(query
->sock
, &query
->sockaddr
,
2766 global_task
, connect_done
, query
);
2767 check_result(result
, "isc_socket_connect");
2770 * If we're at the endgame of a nameserver search, we need to
2771 * immediately bring up all the queries. Do it here.
2773 if (l
->ns_search_only
&& !l
->trace_root
) {
2774 debug("sending next, since searching");
2775 next
= ISC_LIST_NEXT(query
, link
);
2776 if (ISC_LINK_LINKED(query
, link
))
2777 ISC_LIST_DEQUEUE(l
->q
, query
, link
);
2778 ISC_LIST_ENQUEUE(l
->connecting
, query
, clink
);
2780 send_tcp_connect(next
);
2784 static isc_buffer_t
*
2785 clone_buffer(isc_buffer_t
*source
) {
2786 isc_buffer_t
*buffer
;
2787 buffer
= isc_mem_allocate(mctx
, sizeof(*buffer
));
2789 fatal("memory allocation failure in %s:%d",
2790 __FILE__
, __LINE__
);
2796 * Send a UDP packet to the remote nameserver, possible starting the
2797 * recv action as well. Also make sure that the timer is running and
2798 * is properly reset.
2801 send_udp(dig_query_t
*query
) {
2802 dig_lookup_t
*l
= NULL
;
2803 isc_result_t result
;
2804 isc_buffer_t
*sendbuf
;
2806 debug("send_udp(%p)", query
);
2809 bringup_timer(query
, UDP_TIMEOUT
);
2810 l
->current_query
= query
;
2811 debug("working on lookup %p, query %p", query
->lookup
, query
);
2812 if (!query
->recv_made
) {
2813 /* XXX Check the sense of this, need assertion? */
2814 query
->waiting_connect
= ISC_FALSE
;
2815 result
= get_address(query
->servname
, port
, &query
->sockaddr
);
2816 if (result
!= ISC_R_SUCCESS
) {
2817 /* This servname doesn't have an address. */
2818 force_timeout(l
, query
);
2822 result
= isc_socket_create(socketmgr
,
2823 isc_sockaddr_pf(&query
->sockaddr
),
2824 isc_sockettype_udp
, &query
->sock
);
2825 check_result(result
, "isc_socket_create");
2827 debug("sockcount=%d", sockcount
);
2828 if (specified_source
) {
2829 result
= isc_socket_bind(query
->sock
, &bind_address
,
2830 ISC_SOCKET_REUSEADDRESS
);
2832 isc_sockaddr_anyofpf(&bind_any
,
2833 isc_sockaddr_pf(&query
->sockaddr
));
2834 result
= isc_socket_bind(query
->sock
, &bind_any
, 0);
2836 check_result(result
, "isc_socket_bind");
2838 query
->recv_made
= ISC_TRUE
;
2839 ISC_LINK_INIT(&query
->recvbuf
, link
);
2840 ISC_LIST_ENQUEUE(query
->recvlist
, &query
->recvbuf
,
2842 debug("recving with lookup=%p, query=%p, sock=%p",
2843 query
->lookup
, query
, query
->sock
);
2844 result
= isc_socket_recvv(query
->sock
, &query
->recvlist
, 1,
2845 global_task
, recv_done
, query
);
2846 check_result(result
, "isc_socket_recvv");
2848 debug("recvcount=%d", recvcount
);
2850 ISC_LIST_INIT(query
->sendlist
);
2851 sendbuf
= clone_buffer(&query
->sendbuf
);
2852 ISC_LIST_ENQUEUE(query
->sendlist
, sendbuf
, link
);
2853 debug("sending a request");
2854 TIME_NOW(&query
->time_sent
);
2855 INSIST(query
->sock
!= NULL
);
2856 query
->waiting_senddone
= ISC_TRUE
;
2857 result
= isc_socket_sendtov2(query
->sock
, &query
->sendlist
,
2858 global_task
, send_done
, query
,
2859 &query
->sockaddr
, NULL
,
2860 ISC_SOCKFLAG_NORETRY
);
2861 check_result(result
, "isc_socket_sendtov");
2866 * IO timeout handler, used for both connect and recv timeouts. If
2867 * retries are still allowed, either resend the UDP packet or queue a
2868 * new TCP lookup. Otherwise, cancel the lookup.
2871 connect_timeout(isc_task_t
*task
, isc_event_t
*event
) {
2872 dig_lookup_t
*l
= NULL
;
2873 dig_query_t
*query
= NULL
, *next
, *cq
;
2876 REQUIRE(event
->ev_type
== ISC_TIMEREVENT_IDLE
);
2878 debug("connect_timeout()");
2882 query
= l
->current_query
;
2883 isc_event_free(&event
);
2887 if ((query
!= NULL
) && (query
->lookup
->current_query
!= NULL
) &&
2888 (ISC_LIST_NEXT(query
->lookup
->current_query
, link
) != NULL
)) {
2889 debug("trying next server...");
2890 cq
= query
->lookup
->current_query
;
2892 send_udp(ISC_LIST_NEXT(cq
, link
));
2894 if (query
->sock
!= NULL
)
2895 isc_socket_cancel(query
->sock
, NULL
,
2896 ISC_SOCKCANCEL_ALL
);
2897 next
= ISC_LIST_NEXT(cq
, link
);
2899 send_tcp_connect(next
);
2905 if (l
->retries
> 1) {
2908 debug("resending UDP request to first server");
2909 send_udp(ISC_LIST_HEAD(l
->q
));
2911 debug("making new TCP request, %d tries left",
2914 requeue_lookup(l
, ISC_TRUE
);
2916 check_next_lookup(l
);
2919 fputs(l
->cmdline
, stdout
);
2920 printf(";; connection timed out; no servers could be "
2923 check_next_lookup(l
);
2931 * Event handler for the TCP recv which gets the length header of TCP
2932 * packets. Start the next recv of length bytes.
2935 tcp_length_done(isc_task_t
*task
, isc_event_t
*event
) {
2936 isc_socketevent_t
*sevent
;
2937 isc_buffer_t
*b
= NULL
;
2938 isc_result_t result
;
2939 dig_query_t
*query
= NULL
;
2941 isc_uint16_t length
;
2943 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_RECVDONE
);
2948 debug("tcp_length_done()");
2951 sevent
= (isc_socketevent_t
*)event
;
2952 query
= event
->ev_arg
;
2955 INSIST(recvcount
>= 0);
2957 b
= ISC_LIST_HEAD(sevent
->bufferlist
);
2958 INSIST(b
== &query
->lengthbuf
);
2959 ISC_LIST_DEQUEUE(sevent
->bufferlist
, b
, link
);
2961 if (sevent
->result
== ISC_R_CANCELED
) {
2962 isc_event_free(&event
);
2965 check_next_lookup(l
);
2969 if (sevent
->result
!= ISC_R_SUCCESS
) {
2970 char sockstr
[ISC_SOCKADDR_FORMATSIZE
];
2971 isc_sockaddr_format(&query
->sockaddr
, sockstr
,
2973 printf(";; communications error to %s: %s\n",
2974 sockstr
, isc_result_totext(sevent
->result
));
2976 isc_socket_detach(&query
->sock
);
2978 debug("sockcount=%d", sockcount
);
2979 INSIST(sockcount
>= 0);
2980 isc_event_free(&event
);
2982 check_next_lookup(l
);
2986 length
= isc_buffer_getuint16(b
);
2988 isc_event_free(&event
);
2989 launch_next_query(query
, ISC_FALSE
);
2995 * Even though the buffer was already init'ed, we need
2996 * to redo it now, to force the length we want.
2998 isc_buffer_invalidate(&query
->recvbuf
);
2999 isc_buffer_init(&query
->recvbuf
, query
->recvspace
, length
);
3000 ENSURE(ISC_LIST_EMPTY(query
->recvlist
));
3001 ISC_LINK_INIT(&query
->recvbuf
, link
);
3002 ISC_LIST_ENQUEUE(query
->recvlist
, &query
->recvbuf
, link
);
3003 debug("recving with lookup=%p, query=%p", query
->lookup
, query
);
3004 result
= isc_socket_recvv(query
->sock
, &query
->recvlist
, length
, task
,
3006 check_result(result
, "isc_socket_recvv");
3008 debug("resubmitted recv request with length %d, recvcount=%d",
3010 isc_event_free(&event
);
3015 * For transfers that involve multiple recvs (XFR's in particular),
3016 * launch the next recv.
3019 launch_next_query(dig_query_t
*query
, isc_boolean_t include_question
) {
3020 isc_result_t result
;
3022 isc_buffer_t
*buffer
;
3026 debug("launch_next_query()");
3028 if (!query
->lookup
->pending
) {
3029 debug("ignoring launch_next_query because !pending");
3030 isc_socket_detach(&query
->sock
);
3032 debug("sockcount=%d", sockcount
);
3033 INSIST(sockcount
>= 0);
3034 query
->waiting_connect
= ISC_FALSE
;
3037 check_next_lookup(l
);
3041 isc_buffer_clear(&query
->slbuf
);
3042 isc_buffer_clear(&query
->lengthbuf
);
3043 isc_buffer_putuint16(&query
->slbuf
, (isc_uint16_t
) query
->sendbuf
.used
);
3044 ISC_LIST_INIT(query
->sendlist
);
3045 ISC_LINK_INIT(&query
->slbuf
, link
);
3046 if (!query
->first_soa_rcvd
) {
3047 buffer
= clone_buffer(&query
->slbuf
);
3048 ISC_LIST_ENQUEUE(query
->sendlist
, buffer
, link
);
3049 if (include_question
) {
3050 buffer
= clone_buffer(&query
->sendbuf
);
3051 ISC_LIST_ENQUEUE(query
->sendlist
, buffer
, link
);
3055 ISC_LINK_INIT(&query
->lengthbuf
, link
);
3056 ISC_LIST_ENQUEUE(query
->lengthlist
, &query
->lengthbuf
, link
);
3058 result
= isc_socket_recvv(query
->sock
, &query
->lengthlist
, 0,
3059 global_task
, tcp_length_done
, query
);
3060 check_result(result
, "isc_socket_recvv");
3062 debug("recvcount=%d", recvcount
);
3063 if (!query
->first_soa_rcvd
) {
3064 debug("sending a request in launch_next_query");
3065 TIME_NOW(&query
->time_sent
);
3066 query
->waiting_senddone
= ISC_TRUE
;
3067 result
= isc_socket_sendv(query
->sock
, &query
->sendlist
,
3068 global_task
, send_done
, query
);
3069 check_result(result
, "isc_socket_sendv");
3071 debug("sendcount=%d", sendcount
);
3073 query
->waiting_connect
= ISC_FALSE
;
3075 check_next_lookup(query
->lookup
);
3081 * Event handler for TCP connect complete. Make sure the connection was
3082 * successful, then pass into launch_next_query to actually send the
3086 connect_done(isc_task_t
*task
, isc_event_t
*event
) {
3087 isc_socketevent_t
*sevent
= NULL
;
3088 dig_query_t
*query
= NULL
, *next
;
3093 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_CONNECT
);
3096 debug("connect_done()");
3099 sevent
= (isc_socketevent_t
*)event
;
3100 query
= sevent
->ev_arg
;
3102 INSIST(query
->waiting_connect
);
3104 query
->waiting_connect
= ISC_FALSE
;
3106 if (sevent
->result
== ISC_R_CANCELED
) {
3107 debug("in cancel handler");
3108 isc_socket_detach(&query
->sock
);
3109 INSIST(sockcount
> 0);
3111 debug("sockcount=%d", sockcount
);
3112 query
->waiting_connect
= ISC_FALSE
;
3113 isc_event_free(&event
);
3116 check_next_lookup(l
);
3120 if (sevent
->result
!= ISC_R_SUCCESS
) {
3121 char sockstr
[ISC_SOCKADDR_FORMATSIZE
];
3123 debug("unsuccessful connection: %s",
3124 isc_result_totext(sevent
->result
));
3125 isc_sockaddr_format(&query
->sockaddr
, sockstr
, sizeof(sockstr
));
3126 if (sevent
->result
!= ISC_R_CANCELED
)
3127 printf(";; Connection to %s(%s) for %s failed: "
3129 query
->servname
, query
->lookup
->textname
,
3130 isc_result_totext(sevent
->result
));
3131 isc_socket_detach(&query
->sock
);
3133 INSIST(sockcount
>= 0);
3134 /* XXX Clean up exitcodes */
3137 debug("sockcount=%d", sockcount
);
3138 query
->waiting_connect
= ISC_FALSE
;
3139 isc_event_free(&event
);
3141 if ((l
->current_query
!= NULL
) &&
3142 (ISC_LINK_LINKED(l
->current_query
, link
)))
3143 next
= ISC_LIST_NEXT(l
->current_query
, link
);
3148 bringup_timer(next
, TCP_TIMEOUT
);
3149 send_tcp_connect(next
);
3151 check_next_lookup(l
);
3157 isc_socket_detach(&keep
);
3158 isc_socket_attach(query
->sock
, &keep
);
3159 keepaddr
= query
->sockaddr
;
3161 launch_next_query(query
, ISC_TRUE
);
3162 isc_event_free(&event
);
3167 * Check if the ongoing XFR needs more data before it's complete, using
3168 * the semantics of IXFR and AXFR protocols. Much of the complexity of
3169 * this routine comes from determining when an IXFR is complete.
3170 * ISC_FALSE means more data is on the way, and the recv has been issued.
3172 static isc_boolean_t
3173 check_for_more_data(dig_query_t
*query
, dns_message_t
*msg
,
3174 isc_socketevent_t
*sevent
)
3176 dns_rdataset_t
*rdataset
= NULL
;
3177 dns_rdata_t rdata
= DNS_RDATA_INIT
;
3178 dns_rdata_soa_t soa
;
3179 isc_uint32_t ixfr_serial
= query
->lookup
->ixfr_serial
, serial
;
3180 isc_result_t result
;
3181 isc_boolean_t ixfr
= query
->lookup
->rdtype
== dns_rdatatype_ixfr
;
3182 isc_boolean_t axfr
= query
->lookup
->rdtype
== dns_rdatatype_axfr
;
3185 axfr
= query
->ixfr_axfr
;
3187 debug("check_for_more_data()");
3190 * By the time we're in this routine, we know we're doing
3191 * either an AXFR or IXFR. If there's no second_rr_type,
3192 * then we don't yet know which kind of answer we got back
3193 * from the server. Here, we're going to walk through the
3194 * rr's in the message, acting as necessary whenever we hit
3199 query
->byte_count
+= sevent
->n
;
3200 result
= dns_message_firstname(msg
, DNS_SECTION_ANSWER
);
3201 if (result
!= ISC_R_SUCCESS
) {
3202 puts("; Transfer failed.");
3208 dns_message_currentname(msg
, DNS_SECTION_ANSWER
,
3210 for (rdataset
= ISC_LIST_HEAD(name
->list
);
3212 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3213 result
= dns_rdataset_first(rdataset
);
3214 if (result
!= ISC_R_SUCCESS
)
3218 dns_rdata_reset(&rdata
);
3219 dns_rdataset_current(rdataset
, &rdata
);
3221 * If this is the first rr, make sure
3224 if ((!query
->first_soa_rcvd
) &&
3225 (rdata
.type
!= dns_rdatatype_soa
)) {
3226 puts("; Transfer failed. "
3227 "Didn't start with SOA answer.");
3230 if ((!query
->second_rr_rcvd
) &&
3231 (rdata
.type
!= dns_rdatatype_soa
)) {
3232 query
->second_rr_rcvd
= ISC_TRUE
;
3233 query
->second_rr_serial
= 0;
3234 debug("got the second rr as nonsoa");
3235 axfr
= query
->ixfr_axfr
= ISC_TRUE
;
3240 * If the record is anything except an SOA
3241 * now, just continue on...
3243 if (rdata
.type
!= dns_rdatatype_soa
)
3246 /* Now we have an SOA. Work with it. */
3247 debug("got an SOA");
3248 result
= dns_rdata_tostruct(&rdata
, &soa
, NULL
);
3249 check_result(result
, "dns_rdata_tostruct");
3250 serial
= soa
.serial
;
3251 dns_rdata_freestruct(&soa
);
3252 if (!query
->first_soa_rcvd
) {
3253 query
->first_soa_rcvd
= ISC_TRUE
;
3254 query
->first_rr_serial
= serial
;
3255 debug("this is the first serial %u",
3257 if (ixfr
&& isc_serial_ge(ixfr_serial
,
3259 debug("got up to date "
3266 debug("doing axfr, got second SOA");
3269 if (!query
->second_rr_rcvd
) {
3270 if (query
->first_rr_serial
== serial
) {
3271 debug("doing ixfr, got "
3275 debug("this is the second serial %u",
3277 query
->second_rr_rcvd
= ISC_TRUE
;
3278 query
->second_rr_serial
= serial
;
3282 * If we get to this point, we're doing an
3283 * IXFR and have to start really looking
3284 * at serial numbers.
3286 if (query
->first_rr_serial
== serial
) {
3287 debug("got a match for ixfr");
3288 if (!query
->first_repeat_rcvd
) {
3289 query
->first_repeat_rcvd
=
3293 debug("done with ixfr");
3296 debug("meaningless soa %u", serial
);
3298 result
= dns_rdataset_next(rdataset
);
3299 } while (result
== ISC_R_SUCCESS
);
3301 result
= dns_message_nextname(msg
, DNS_SECTION_ANSWER
);
3302 } while (result
== ISC_R_SUCCESS
);
3303 launch_next_query(query
, ISC_FALSE
);
3306 received(sevent
->n
, &sevent
->address
, query
);
3310 #ifdef ISC_PLATFORM_USESIT
3312 process_sit(dig_lookup_t
*l
, dns_message_t
*msg
,
3313 isc_buffer_t
*optbuf
, size_t optlen
)
3316 isc_buffer_t hexbuf
;
3318 const unsigned char *sit
;
3319 isc_result_t result
;
3321 if (l
->sitvalue
!= NULL
) {
3322 isc_buffer_init(&hexbuf
, bb
, sizeof(bb
));
3323 result
= isc_hex_decodestring(l
->sitvalue
, &hexbuf
);
3324 check_result(result
, "isc_hex_decodestring");
3325 sit
= isc_buffer_base(&hexbuf
);
3326 len
= isc_buffer_usedlength(&hexbuf
);
3329 len
= sizeof(cookie
);
3332 INSIST(msg
->sitok
== 0 && msg
->sitbad
== 0);
3333 if (optlen
>= len
&& optlen
>= 8U) {
3334 if (memcmp(isc_buffer_current(optbuf
), sit
, 8) == 0) {
3337 printf(";; Warning: SIT client cookie mismatch\n");
3341 printf(";; Warning: SIT bad token (too short)\n");
3344 isc_buffer_forward(optbuf
, (unsigned int)optlen
);
3348 process_opt(dig_lookup_t
*l
, dns_message_t
*msg
) {
3350 isc_result_t result
;
3351 isc_buffer_t optbuf
;
3352 isc_uint16_t optcode
, optlen
;
3353 dns_rdataset_t
*opt
= msg
->opt
;
3355 result
= dns_rdataset_first(opt
);
3356 if (result
== ISC_R_SUCCESS
) {
3357 dns_rdata_init(&rdata
);
3358 dns_rdataset_current(opt
, &rdata
);
3359 isc_buffer_init(&optbuf
, rdata
.data
, rdata
.length
);
3360 isc_buffer_add(&optbuf
, rdata
.length
);
3361 while (isc_buffer_remaininglength(&optbuf
) >= 4) {
3362 optcode
= isc_buffer_getuint16(&optbuf
);
3363 optlen
= isc_buffer_getuint16(&optbuf
);
3366 process_sit(l
, msg
, &optbuf
, optlen
);
3369 isc_buffer_forward(&optbuf
, optlen
);
3379 * Event handler for recv complete. Perform whatever actions are necessary,
3380 * based on the specifics of the user's request.
3383 recv_done(isc_task_t
*task
, isc_event_t
*event
) {
3384 isc_socketevent_t
*sevent
= NULL
;
3385 dig_query_t
*query
= NULL
;
3386 isc_buffer_t
*b
= NULL
;
3387 dns_message_t
*msg
= NULL
;
3389 dig_message_t
*chase_msg
= NULL
;
3390 dig_message_t
*chase_msg2
= NULL
;
3392 isc_result_t result
;
3393 dig_lookup_t
*n
, *l
;
3394 isc_boolean_t docancel
= ISC_FALSE
;
3395 isc_boolean_t match
= ISC_TRUE
;
3396 unsigned int parseflags
;
3398 unsigned int msgflags
;
3400 isc_result_t do_sigchase
= ISC_FALSE
;
3402 dns_message_t
*msg_temp
= NULL
;
3404 isc_buffer_t
*buf
= NULL
;
3410 debug("recv_done()");
3414 debug("recvcount=%d", recvcount
);
3415 INSIST(recvcount
>= 0);
3417 query
= event
->ev_arg
;
3418 TIME_NOW(&query
->time_recv
);
3419 debug("lookup=%p, query=%p", query
->lookup
, query
);
3423 REQUIRE(event
->ev_type
== ISC_SOCKEVENT_RECVDONE
);
3424 sevent
= (isc_socketevent_t
*)event
;
3426 b
= ISC_LIST_HEAD(sevent
->bufferlist
);
3427 INSIST(b
== &query
->recvbuf
);
3428 ISC_LIST_DEQUEUE(sevent
->bufferlist
, &query
->recvbuf
, link
);
3430 if ((l
->tcp_mode
) && (l
->timer
!= NULL
))
3431 isc_timer_touch(l
->timer
);
3432 if ((!l
->pending
&& !l
->ns_search_only
) || cancel_now
) {
3433 debug("no longer pending. Got %s",
3434 isc_result_totext(sevent
->result
));
3435 query
->waiting_connect
= ISC_FALSE
;
3437 isc_event_free(&event
);
3439 check_next_lookup(l
);
3444 if (sevent
->result
!= ISC_R_SUCCESS
) {
3445 if (sevent
->result
== ISC_R_CANCELED
) {
3446 debug("in recv cancel handler");
3447 query
->waiting_connect
= ISC_FALSE
;
3449 printf(";; communications error: %s\n",
3450 isc_result_totext(sevent
->result
));
3451 isc_socket_detach(&query
->sock
);
3453 debug("sockcount=%d", sockcount
);
3454 INSIST(sockcount
>= 0);
3456 isc_event_free(&event
);
3458 check_next_lookup(l
);
3464 !isc_sockaddr_compare(&sevent
->address
, &query
->sockaddr
,
3465 ISC_SOCKADDR_CMPADDR
|
3466 ISC_SOCKADDR_CMPPORT
|
3467 ISC_SOCKADDR_CMPSCOPE
|
3468 ISC_SOCKADDR_CMPSCOPEZERO
)) {
3469 char buf1
[ISC_SOCKADDR_FORMATSIZE
];
3470 char buf2
[ISC_SOCKADDR_FORMATSIZE
];
3473 if (isc_sockaddr_pf(&query
->sockaddr
) == AF_INET
)
3474 isc_sockaddr_any(&any
);
3476 isc_sockaddr_any6(&any
);
3479 * We don't expect a match when the packet is
3480 * sent to 0.0.0.0, :: or to a multicast addresses.
3481 * XXXMPA broadcast needs to be handled here as well.
3483 if ((!isc_sockaddr_eqaddr(&query
->sockaddr
, &any
) &&
3484 !isc_sockaddr_ismulticast(&query
->sockaddr
)) ||
3485 isc_sockaddr_getport(&query
->sockaddr
) !=
3486 isc_sockaddr_getport(&sevent
->address
)) {
3487 isc_sockaddr_format(&sevent
->address
, buf1
,
3489 isc_sockaddr_format(&query
->sockaddr
, buf2
,
3491 printf(";; reply from unexpected source: %s,"
3492 " expected %s\n", buf1
, buf2
);
3497 result
= dns_message_peekheader(b
, &id
, &msgflags
);
3498 if (result
!= ISC_R_SUCCESS
|| l
->sendmsg
->id
!= id
) {
3501 isc_boolean_t fail
= ISC_TRUE
;
3502 if (result
== ISC_R_SUCCESS
) {
3503 if (!query
->first_soa_rcvd
||
3505 printf(";; %s: ID mismatch: "
3506 "expected ID %u, got %u\n",
3507 query
->first_soa_rcvd
?
3508 "WARNING" : "ERROR",
3509 l
->sendmsg
->id
, id
);
3510 if (query
->first_soa_rcvd
)
3512 query
->warn_id
= ISC_FALSE
;
3514 printf(";; ERROR: short "
3515 "(< header size) message\n");
3517 isc_event_free(&event
);
3519 check_next_lookup(l
);
3524 } else if (result
== ISC_R_SUCCESS
)
3525 printf(";; Warning: ID mismatch: "
3526 "expected ID %u, got %u\n", l
->sendmsg
->id
, id
);
3528 printf(";; Warning: short "
3529 "(< header size) message received\n");
3532 if (result
== ISC_R_SUCCESS
&& (msgflags
& DNS_MESSAGEFLAG_QR
) == 0)
3533 printf(";; Warning: query response not set\n");
3538 result
= dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
, &msg
);
3539 check_result(result
, "dns_message_create");
3542 if (l
->querysig
== NULL
) {
3543 debug("getting initial querysig");
3544 result
= dns_message_getquerytsig(l
->sendmsg
, mctx
,
3546 check_result(result
, "dns_message_getquerytsig");
3548 result
= dns_message_setquerytsig(msg
, l
->querysig
);
3549 check_result(result
, "dns_message_setquerytsig");
3550 result
= dns_message_settsigkey(msg
, key
);
3551 check_result(result
, "dns_message_settsigkey");
3552 msg
->tsigctx
= l
->tsigctx
;
3554 if (l
->msgcounter
!= 0)
3555 msg
->tcp_continuation
= 1;
3559 debug("before parse starts");
3560 parseflags
= DNS_MESSAGEPARSE_PRESERVEORDER
;
3563 do_sigchase
= ISC_FALSE
;
3566 do_sigchase
= ISC_TRUE
;
3569 if (l
->besteffort
) {
3570 parseflags
|= DNS_MESSAGEPARSE_BESTEFFORT
;
3571 parseflags
|= DNS_MESSAGEPARSE_IGNORETRUNCATION
;
3573 result
= dns_message_parse(msg
, b
, parseflags
);
3574 if (result
== DNS_R_RECOVERABLE
) {
3575 printf(";; Warning: Message parser reports malformed "
3576 "message packet.\n");
3577 result
= ISC_R_SUCCESS
;
3579 if (result
!= ISC_R_SUCCESS
) {
3580 printf(";; Got bad packet: %s\n", isc_result_totext(result
));
3582 query
->waiting_connect
= ISC_FALSE
;
3583 dns_message_destroy(&msg
);
3584 isc_event_free(&event
);
3587 check_next_lookup(l
);
3591 if (msg
->counts
[DNS_SECTION_QUESTION
] != 0) {
3593 for (result
= dns_message_firstname(msg
, DNS_SECTION_QUESTION
);
3594 result
== ISC_R_SUCCESS
&& match
;
3595 result
= dns_message_nextname(msg
, DNS_SECTION_QUESTION
)) {
3596 dns_name_t
*name
= NULL
;
3597 dns_rdataset_t
*rdataset
;
3599 dns_message_currentname(msg
, DNS_SECTION_QUESTION
,
3601 for (rdataset
= ISC_LIST_HEAD(name
->list
);
3603 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
3604 if (l
->rdtype
!= rdataset
->type
||
3605 l
->rdclass
!= rdataset
->rdclass
||
3606 !dns_name_equal(l
->name
, name
)) {
3607 char namestr
[DNS_NAME_FORMATSIZE
];
3608 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
3609 char classbuf
[DNS_RDATACLASS_FORMATSIZE
];
3610 dns_name_format(name
, namestr
,
3612 dns_rdatatype_format(rdataset
->type
,
3615 dns_rdataclass_format(rdataset
->rdclass
,
3618 printf(";; Question section mismatch: "
3620 namestr
, typebuf
, classbuf
);
3626 dns_message_destroy(&msg
);
3628 isc_event_free(&event
);
3630 check_next_lookup(l
);
3637 if ((msg
->flags
& DNS_MESSAGEFLAG_TC
) != 0 &&
3638 !l
->ignore
&& !l
->tcp_mode
) {
3640 printf(";; Truncated, retrying in TCP mode.\n");
3641 n
= requeue_lookup(l
, ISC_TRUE
);
3642 n
->tcp_mode
= ISC_TRUE
;
3643 n
->origin
= query
->lookup
->origin
;
3644 dns_message_destroy(&msg
);
3645 isc_event_free(&event
);
3648 check_next_lookup(l
);
3652 if ((msg
->rcode
== dns_rcode_servfail
&& !l
->servfail_stops
) ||
3653 (check_ra
&& (msg
->flags
& DNS_MESSAGEFLAG_RA
) == 0 && l
->recurse
))
3655 dig_query_t
*next
= ISC_LIST_NEXT(query
, link
);
3656 if (l
->current_query
== query
)
3657 l
->current_query
= NULL
;
3659 debug("sending query %p\n", next
);
3661 send_tcp_connect(next
);
3666 * If our query is at the head of the list and there
3667 * is no next, we're the only one left, so fall
3668 * through to print the message.
3670 if ((ISC_LIST_HEAD(l
->q
) != query
) ||
3671 (ISC_LIST_NEXT(query
, link
) != NULL
)) {
3673 printf(";; Got %s from %s, "
3674 "trying next server\n",
3675 msg
->rcode
== dns_rcode_servfail
?
3677 "recursion not available",
3680 check_next_lookup(l
);
3681 dns_message_destroy(&msg
);
3682 isc_event_free(&event
);
3689 result
= dns_tsig_verify(&query
->recvbuf
, msg
, NULL
, NULL
);
3690 if (result
!= ISC_R_SUCCESS
) {
3691 printf(";; Couldn't verify signature: %s\n",
3692 isc_result_totext(result
));
3693 validated
= ISC_FALSE
;
3695 l
->tsigctx
= msg
->tsigctx
;
3696 msg
->tsigctx
= NULL
;
3697 if (l
->querysig
!= NULL
) {
3698 debug("freeing querysig buffer %p", l
->querysig
);
3699 isc_buffer_free(&l
->querysig
);
3701 result
= dns_message_getquerytsig(msg
, mctx
, &l
->querysig
);
3702 check_result(result
,"dns_message_getquerytsig");
3705 extrabytes
= isc_buffer_remaininglength(b
);
3707 debug("after parse");
3708 if (l
->doing_xfr
&& l
->xfr_q
== NULL
) {
3711 * Once we are in the XFR message, increase
3712 * the timeout to much longer, so brief network
3713 * outages won't cause the XFR to abort
3715 if (timeout
!= INT_MAX
&& l
->timer
!= NULL
) {
3716 unsigned int local_timeout
;
3720 local_timeout
= TCP_TIMEOUT
* 4;
3722 local_timeout
= UDP_TIMEOUT
* 4;
3724 if (timeout
< (INT_MAX
/ 4))
3725 local_timeout
= timeout
* 4;
3727 local_timeout
= INT_MAX
;
3729 debug("have local timeout of %d", local_timeout
);
3730 isc_interval_set(&l
->interval
, local_timeout
, 0);
3731 result
= isc_timer_reset(l
->timer
,
3736 check_result(result
, "isc_timer_reset");
3740 #ifdef ISC_PLATFORM_USESIT
3741 if (l
->sitvalue
!= NULL
) {
3742 if (msg
->opt
== NULL
)
3743 printf(";; expected opt record in response\n");
3745 process_opt(l
, msg
);
3746 } else if (l
->sit
&& msg
->opt
!= NULL
)
3747 process_opt(l
, msg
);
3750 if (!l
->doing_xfr
|| l
->xfr_q
== query
) {
3751 if (msg
->rcode
== dns_rcode_nxdomain
&&
3752 (l
->origin
!= NULL
|| l
->need_search
)) {
3753 if (!next_origin(query
->lookup
) || showsearch
) {
3754 printmessage(query
, msg
, ISC_TRUE
);
3755 received(b
->used
, &sevent
->address
, query
);
3757 } else if (!l
->trace
&& !l
->ns_search_only
) {
3761 printmessage(query
, msg
, ISC_TRUE
);
3762 } else if (l
->trace
) {
3764 int count
= msg
->counts
[DNS_SECTION_ANSWER
];
3766 debug("in TRACE code");
3767 if (!l
->ns_search_only
)
3768 printmessage(query
, msg
, ISC_TRUE
);
3770 l
->rdtype
= l
->qrdtype
;
3771 if (l
->trace_root
|| (l
->ns_search_only
&& count
> 0)) {
3773 l
->rdtype
= dns_rdatatype_soa
;
3774 nl
= followup_lookup(msg
, query
,
3775 DNS_SECTION_ANSWER
);
3776 l
->trace_root
= ISC_FALSE
;
3777 } else if (count
== 0)
3778 nl
= followup_lookup(msg
, query
,
3779 DNS_SECTION_AUTHORITY
);
3781 docancel
= ISC_TRUE
;
3783 debug("in NSSEARCH code");
3785 if (l
->trace_root
) {
3787 * This is the initial NS query.
3791 l
->rdtype
= dns_rdatatype_soa
;
3792 nl
= followup_lookup(msg
, query
,
3793 DNS_SECTION_ANSWER
);
3795 docancel
= ISC_TRUE
;
3796 l
->trace_root
= ISC_FALSE
;
3797 usesearch
= ISC_FALSE
;
3802 printmessage(query
, msg
, ISC_TRUE
);
3806 chase_msg
= isc_mem_allocate(mctx
,
3807 sizeof(dig_message_t
));
3808 if (chase_msg
== NULL
) {
3809 fatal("Memory allocation failure in %s:%d",
3810 __FILE__
, __LINE__
);
3812 ISC_LIST_INITANDAPPEND(chase_message_list
, chase_msg
,
3814 if (dns_message_create(mctx
, DNS_MESSAGE_INTENTPARSE
,
3815 &msg_temp
) != ISC_R_SUCCESS
) {
3816 fatal("dns_message_create in %s:%d",
3817 __FILE__
, __LINE__
);
3820 isc_buffer_usedregion(b
, &r
);
3821 result
= isc_buffer_allocate(mctx
, &buf
, r
.length
);
3823 check_result(result
, "isc_buffer_allocate");
3824 result
= isc_buffer_copyregion(buf
, &r
);
3825 check_result(result
, "isc_buffer_copyregion");
3827 result
= dns_message_parse(msg_temp
, buf
, 0);
3829 isc_buffer_free(&buf
);
3830 chase_msg
->msg
= msg_temp
;
3832 chase_msg2
= isc_mem_allocate(mctx
,
3833 sizeof(dig_message_t
));
3834 if (chase_msg2
== NULL
) {
3835 fatal("Memory allocation failure in %s:%d",
3836 __FILE__
, __LINE__
);
3838 ISC_LIST_INITANDAPPEND(chase_message_list2
, chase_msg2
,
3840 chase_msg2
->msg
= msg
;
3846 if (l
->sigchase
&& ISC_LIST_EMPTY(lookup_list
)) {
3852 debug("still pending.");
3854 if (query
!= l
->xfr_q
) {
3855 dns_message_destroy(&msg
);
3856 isc_event_free(&event
);
3857 query
->waiting_connect
= ISC_FALSE
;
3862 docancel
= check_for_more_data(query
, msg
, sevent
);
3864 dns_message_destroy(&msg
);
3867 check_next_lookup(l
);
3871 if (msg
->rcode
== dns_rcode_noerror
|| l
->origin
== NULL
) {
3876 received(b
->used
, &sevent
->address
, query
);
3879 if (!query
->lookup
->ns_search_only
)
3880 query
->lookup
->pending
= ISC_FALSE
;
3881 if (!query
->lookup
->ns_search_only
||
3882 query
->lookup
->trace_root
|| docancel
) {
3886 dns_message_destroy(&msg
);
3891 check_next_lookup(l
);
3899 dns_message_destroy(&msg
);
3901 isc_event_free(&event
);
3906 isc_buffer_invalidate(&query
->recvbuf
);
3907 isc_buffer_init(&query
->recvbuf
, query
->recvspace
, COMMSIZE
);
3908 ISC_LIST_ENQUEUE(query
->recvlist
, &query
->recvbuf
, link
);
3909 result
= isc_socket_recvv(query
->sock
, &query
->recvlist
, 1,
3910 global_task
, recv_done
, query
);
3911 check_result(result
, "isc_socket_recvv");
3913 isc_event_free(&event
);
3919 * Turn a name into an address, using system-supplied routines. This is
3920 * used in looking up server names, etc... and needs to use system-supplied
3921 * routines, since they may be using a non-DNS system for these lookups.
3924 get_address(char *host
, in_port_t myport
, isc_sockaddr_t
*sockaddr
) {
3926 isc_result_t result
;
3929 result
= bind9_getaddresses(host
, myport
, sockaddr
, 1, &count
);
3931 if (result
!= ISC_R_SUCCESS
)
3936 return (ISC_R_SUCCESS
);
3940 getaddresses(dig_lookup_t
*lookup
, const char *host
, isc_result_t
*resultp
) {
3941 isc_result_t result
;
3942 isc_sockaddr_t sockaddrs
[DIG_MAX_ADDRESSES
];
3943 isc_netaddr_t netaddr
;
3946 char tmp
[ISC_NETADDR_FORMATSIZE
];
3948 result
= bind9_getaddresses(host
, 0, sockaddrs
,
3949 DIG_MAX_ADDRESSES
, &count
);
3950 if (resultp
!= NULL
)
3952 if (result
!= ISC_R_SUCCESS
) {
3953 if (resultp
== NULL
)
3954 fatal("couldn't get address for '%s': %s",
3955 host
, isc_result_totext(result
));
3959 for (i
= 0; i
< count
; i
++) {
3960 isc_netaddr_fromsockaddr(&netaddr
, &sockaddrs
[i
]);
3961 isc_netaddr_format(&netaddr
, tmp
, sizeof(tmp
));
3962 srv
= make_server(tmp
, host
);
3963 ISC_LIST_APPEND(lookup
->my_server_list
, srv
, link
);
3970 * Initiate either a TCP or UDP lookup
3973 do_lookup(dig_lookup_t
*lookup
) {
3976 REQUIRE(lookup
!= NULL
);
3978 debug("do_lookup()");
3979 lookup
->pending
= ISC_TRUE
;
3980 query
= ISC_LIST_HEAD(lookup
->q
);
3981 if (query
!= NULL
) {
3982 if (lookup
->tcp_mode
)
3983 send_tcp_connect(query
);
3990 * Start everything in action upon task startup.
3993 onrun_callback(isc_task_t
*task
, isc_event_t
*event
) {
3996 isc_event_free(&event
);
4003 * Make everything on the lookup queue go away. Mainly used by the
4008 dig_lookup_t
*l
, *n
;
4009 dig_query_t
*q
, *nq
;
4011 debug("cancel_all()");
4018 cancel_now
= ISC_TRUE
;
4019 if (current_lookup
!= NULL
) {
4020 if (current_lookup
->timer
!= NULL
)
4021 isc_timer_detach(¤t_lookup
->timer
);
4022 for (q
= ISC_LIST_HEAD(current_lookup
->q
);
4026 nq
= ISC_LIST_NEXT(q
, link
);
4027 debug("canceling pending query %p, belonging to %p",
4029 if (q
->sock
!= NULL
)
4030 isc_socket_cancel(q
->sock
, NULL
,
4031 ISC_SOCKCANCEL_ALL
);
4035 for (q
= ISC_LIST_HEAD(current_lookup
->connecting
);
4039 nq
= ISC_LIST_NEXT(q
, clink
);
4040 debug("canceling connecting query %p, belonging to %p",
4042 if (q
->sock
!= NULL
)
4043 isc_socket_cancel(q
->sock
, NULL
,
4044 ISC_SOCKCANCEL_ALL
);
4049 l
= ISC_LIST_HEAD(lookup_list
);
4051 n
= ISC_LIST_NEXT(l
, link
);
4052 ISC_LIST_DEQUEUE(lookup_list
, l
, link
);
4053 try_clear_lookup(l
);
4060 * Destroy all of the libs we are using, and get everything ready for a
4064 destroy_libs(void) {
4067 dig_message_t
*chase_msg
;
4070 isc_result_t result
;
4074 isc_socket_detach(&keep
);
4075 debug("destroy_libs()");
4076 if (global_task
!= NULL
) {
4077 debug("freeing task");
4078 isc_task_detach(&global_task
);
4081 * The taskmgr_destroy() call blocks until all events are cleared
4084 if (taskmgr
!= NULL
) {
4085 debug("freeing taskmgr");
4086 isc_taskmgr_destroy(&taskmgr
);
4089 REQUIRE(sockcount
== 0);
4090 REQUIRE(recvcount
== 0);
4091 REQUIRE(sendcount
== 0);
4093 INSIST(ISC_LIST_HEAD(lookup_list
) == NULL
);
4094 INSIST(current_lookup
== NULL
);
4097 free_now
= ISC_TRUE
;
4099 lwres_conf_clear(lwctx
);
4100 lwres_context_destroy(&lwctx
);
4102 flush_server_list();
4107 result
= dns_name_settotextfilter(NULL
);
4108 check_result(result
, "dns_name_settotextfilter");
4112 if (commctx
!= NULL
) {
4113 debug("freeing commctx");
4114 isc_mempool_destroy(&commctx
);
4116 if (socketmgr
!= NULL
) {
4117 debug("freeing socketmgr");
4118 isc_socketmgr_destroy(&socketmgr
);
4120 if (timermgr
!= NULL
) {
4121 debug("freeing timermgr");
4122 isc_timermgr_destroy(&timermgr
);
4125 debug("freeing key %p", key
);
4126 dns_tsigkey_detach(&key
);
4128 if (namebuf
!= NULL
)
4129 isc_buffer_free(&namebuf
);
4132 debug("destroy DST lib");
4134 is_dst_up
= ISC_FALSE
;
4137 debug("detach from entropy");
4138 isc_entropy_detach(&entp
);
4142 DESTROYLOCK(&lookup_lock
);
4145 debug("Destroy the messages kept for sigchase");
4146 /* Destroy the messages kept for sigchase */
4147 chase_msg
= ISC_LIST_HEAD(chase_message_list
);
4149 while (chase_msg
!= NULL
) {
4150 INSIST(chase_msg
->msg
!= NULL
);
4151 dns_message_destroy(&(chase_msg
->msg
));
4153 chase_msg
= ISC_LIST_NEXT(chase_msg
, link
);
4154 isc_mem_free(mctx
, ptr
);
4157 chase_msg
= ISC_LIST_HEAD(chase_message_list2
);
4159 while (chase_msg
!= NULL
) {
4160 INSIST(chase_msg
->msg
!= NULL
);
4161 dns_message_destroy(&(chase_msg
->msg
));
4163 chase_msg
= ISC_LIST_NEXT(chase_msg
, link
);
4164 isc_mem_free(mctx
, ptr
);
4166 if (dns_name_dynamic(&chase_name
))
4167 free_name(&chase_name
, mctx
);
4169 if (dns_name_dynamic(&chase_current_name
))
4170 free_name(&chase_current_name
, mctx
);
4171 if (dns_name_dynamic(&chase_authority_name
))
4172 free_name(&chase_authority_name
, mctx
);
4175 if (dns_name_dynamic(&chase_signame
))
4176 free_name(&chase_signame
, mctx
);
4180 debug("Removing log context");
4181 isc_log_destroy(&lctx
);
4183 debug("Destroy memory");
4184 if (memdebugging
!= 0)
4185 isc_mem_stats(mctx
, stderr
);
4187 isc_mem_destroy(&mctx
);
4192 initialize_idn(void) {
4194 isc_result_t result
;
4196 #ifdef HAVE_SETLOCALE
4198 (void)setlocale(LC_ALL
, "");
4200 /* Create configuration context. */
4201 r
= idn_nameinit(1);
4202 if (r
!= idn_success
)
4203 fatal("idn api initialization failed: %s",
4204 idn_result_tostring(r
));
4206 /* Set domain name -> text post-conversion filter. */
4207 result
= dns_name_settotextfilter(output_filter
);
4208 check_result(result
, "dns_name_settotextfilter");
4212 output_filter(isc_buffer_t
*buffer
, unsigned int used_org
,
4213 isc_boolean_t absolute
)
4215 char tmp1
[MAXDLEN
], tmp2
[MAXDLEN
];
4216 size_t fromlen
, tolen
;
4217 isc_boolean_t end_with_dot
;
4220 * Copy contents of 'buffer' to 'tmp1', supply trailing dot
4221 * if 'absolute' is true, and terminate with NUL.
4223 fromlen
= isc_buffer_usedlength(buffer
) - used_org
;
4224 if (fromlen
>= MAXDLEN
)
4225 return (ISC_R_SUCCESS
);
4226 memmove(tmp1
, (char *)isc_buffer_base(buffer
) + used_org
, fromlen
);
4227 end_with_dot
= (tmp1
[fromlen
- 1] == '.') ? ISC_TRUE
: ISC_FALSE
;
4228 if (absolute
&& !end_with_dot
) {
4230 if (fromlen
>= MAXDLEN
)
4231 return (ISC_R_SUCCESS
);
4232 tmp1
[fromlen
- 1] = '.';
4234 tmp1
[fromlen
] = '\0';
4237 * Convert contents of 'tmp1' to local encoding.
4239 if (idn_decodename(IDN_DECODE_APP
, tmp1
, tmp2
, MAXDLEN
) != idn_success
)
4240 return (ISC_R_SUCCESS
);
4244 * Copy the converted contents in 'tmp1' back to 'buffer'.
4245 * If we have appended trailing dot, remove it.
4247 tolen
= strlen(tmp1
);
4248 if (absolute
&& !end_with_dot
&& tmp1
[tolen
- 1] == '.')
4251 if (isc_buffer_length(buffer
) < used_org
+ tolen
)
4252 return (ISC_R_NOSPACE
);
4254 isc_buffer_subtract(buffer
, isc_buffer_usedlength(buffer
) - used_org
);
4255 memmove(isc_buffer_used(buffer
), tmp1
, tolen
);
4256 isc_buffer_add(buffer
, (unsigned int)tolen
);
4258 return (ISC_R_SUCCESS
);
4262 append_textname(char *name
, const char *origin
, size_t namesize
) {
4263 size_t namelen
= strlen(name
);
4264 size_t originlen
= strlen(origin
);
4266 /* Already absolute? */
4267 if (namelen
> 0 && name
[namelen
- 1] == '.')
4270 /* Append dot and origin */
4272 if (namelen
+ 1 + originlen
>= namesize
)
4273 return idn_buffer_overflow
;
4276 name
[namelen
++] = '.';
4277 (void)strcpy(name
+ namelen
, origin
);
4282 idn_check_result(idn_result_t r
, const char *msg
) {
4283 if (r
!= idn_success
) {
4285 fatal("%s: %s", msg
, idn_result_tostring(r
));
4288 #endif /* WITH_IDN */
4292 print_type(dns_rdatatype_t type
)
4294 isc_buffer_t
* b
= NULL
;
4295 isc_result_t result
;
4298 result
= isc_buffer_allocate(mctx
, &b
, 4000);
4299 check_result(result
, "isc_buffer_allocate");
4301 result
= dns_rdatatype_totext(type
, b
);
4302 check_result(result
, "print_type");
4304 isc_buffer_usedregion(b
, &r
);
4305 r
.base
[r
.length
] = '\0';
4307 printf("%s", r
.base
);
4309 isc_buffer_free(&b
);
4313 dump_database_section(dns_message_t
*msg
, int section
)
4315 dns_name_t
*msg_name
=NULL
;
4317 dns_rdataset_t
*rdataset
;
4320 dns_message_currentname(msg
, section
, &msg_name
);
4322 for (rdataset
= ISC_LIST_HEAD(msg_name
->list
); rdataset
!= NULL
;
4323 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
4324 dns_name_print(msg_name
, stdout
);
4326 print_rdataset(msg_name
, rdataset
, mctx
);
4330 } while (dns_message_nextname(msg
, section
) == ISC_R_SUCCESS
);
4334 dump_database(void) {
4335 dig_message_t
* msg
;
4337 for (msg
= ISC_LIST_HEAD(chase_message_list
); msg
!= NULL
;
4338 msg
= ISC_LIST_NEXT(msg
, link
)) {
4339 if (dns_message_firstname(msg
->msg
, DNS_SECTION_ANSWER
)
4341 dump_database_section(msg
->msg
, DNS_SECTION_ANSWER
);
4343 if (dns_message_firstname(msg
->msg
, DNS_SECTION_AUTHORITY
)
4345 dump_database_section(msg
->msg
, DNS_SECTION_AUTHORITY
);
4347 if (dns_message_firstname(msg
->msg
, DNS_SECTION_ADDITIONAL
)
4349 dump_database_section(msg
->msg
, DNS_SECTION_ADDITIONAL
);
4355 search_type(dns_name_t
*name
, dns_rdatatype_t type
, dns_rdatatype_t covers
) {
4356 dns_rdataset_t
*rdataset
;
4357 dns_rdata_sig_t siginfo
;
4358 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
4359 isc_result_t result
;
4361 for (rdataset
= ISC_LIST_HEAD(name
->list
); rdataset
!= NULL
;
4362 rdataset
= ISC_LIST_NEXT(rdataset
, link
)) {
4363 if (type
== dns_rdatatype_any
) {
4364 if (rdataset
->type
!= dns_rdatatype_rrsig
)
4366 } else if ((type
== dns_rdatatype_rrsig
) &&
4367 (rdataset
->type
== dns_rdatatype_rrsig
)) {
4368 result
= dns_rdataset_first(rdataset
);
4369 check_result(result
, "empty rdataset");
4370 dns_rdataset_current(rdataset
, &sigrdata
);
4371 result
= dns_rdata_tostruct(&sigrdata
, &siginfo
, NULL
);
4372 check_result(result
, "sigrdata tostruct siginfo");
4374 if ((siginfo
.covered
== covers
) ||
4375 (covers
== dns_rdatatype_any
)) {
4376 dns_rdata_reset(&sigrdata
);
4377 dns_rdata_freestruct(&siginfo
);
4380 dns_rdata_reset(&sigrdata
);
4381 dns_rdata_freestruct(&siginfo
);
4382 } else if (rdataset
->type
== type
)
4389 chase_scanname_section(dns_message_t
*msg
, dns_name_t
*name
,
4390 dns_rdatatype_t type
, dns_rdatatype_t covers
,
4393 dns_rdataset_t
*rdataset
;
4394 dns_name_t
*msg_name
= NULL
;
4396 if (msg
->counts
[section
] == 0)
4400 dns_message_currentname(msg
, section
, &msg_name
);
4401 if (dns_name_compare(msg_name
, name
) == 0) {
4402 rdataset
= search_type(msg_name
, type
, covers
);
4403 if (rdataset
!= NULL
)
4407 } while (dns_message_nextname(msg
, section
) == ISC_R_SUCCESS
);
4414 chase_scanname(dns_name_t
*name
, dns_rdatatype_t type
, dns_rdatatype_t covers
)
4416 dns_rdataset_t
*rdataset
= NULL
;
4417 dig_message_t
* msg
;
4419 for (msg
= ISC_LIST_HEAD(chase_message_list2
); msg
!= NULL
;
4420 msg
= ISC_LIST_NEXT(msg
, link
)) {
4421 if (dns_message_firstname(msg
->msg
, DNS_SECTION_ANSWER
)
4423 rdataset
= chase_scanname_section(msg
->msg
, name
,
4425 DNS_SECTION_ANSWER
);
4426 if (rdataset
!= NULL
)
4428 if (dns_message_firstname(msg
->msg
, DNS_SECTION_AUTHORITY
)
4431 chase_scanname_section(msg
->msg
, name
,
4433 DNS_SECTION_AUTHORITY
);
4434 if (rdataset
!= NULL
)
4436 if (dns_message_firstname(msg
->msg
, DNS_SECTION_ADDITIONAL
)
4439 chase_scanname_section(msg
->msg
, name
, type
,
4441 DNS_SECTION_ADDITIONAL
);
4442 if (rdataset
!= NULL
)
4450 sigchase_scanname(dns_rdatatype_t type
, dns_rdatatype_t covers
,
4451 isc_boolean_t
* lookedup
, dns_name_t
*rdata_name
)
4453 dig_lookup_t
*lookup
;
4454 isc_buffer_t
*b
= NULL
;
4456 isc_result_t result
;
4457 dns_rdataset_t
* temp
;
4458 dns_rdatatype_t querytype
;
4460 temp
= chase_scanname(rdata_name
, type
, covers
);
4464 if (*lookedup
== ISC_TRUE
)
4467 lookup
= clone_lookup(current_lookup
, ISC_TRUE
);
4468 lookup
->trace_root
= ISC_FALSE
;
4469 lookup
->new_search
= ISC_TRUE
;
4471 result
= isc_buffer_allocate(mctx
, &b
, BUFSIZE
);
4472 check_result(result
, "isc_buffer_allocate");
4473 result
= dns_name_totext(rdata_name
, ISC_FALSE
, b
);
4474 check_result(result
, "dns_name_totext");
4475 isc_buffer_usedregion(b
, &r
);
4476 r
.base
[r
.length
] = '\0';
4477 strlcpy(lookup
->textname
, (char*)r
.base
, sizeof(lookup
->textname
));
4478 isc_buffer_free(&b
);
4480 if (type
== dns_rdatatype_rrsig
)
4485 if (querytype
== 0 || querytype
== 255) {
4486 printf("Error in the queried type: %d\n", querytype
);
4490 lookup
->rdtype
= querytype
;
4491 lookup
->rdtypeset
= ISC_TRUE
;
4492 lookup
->qrdtype
= querytype
;
4493 *lookedup
= ISC_TRUE
;
4495 ISC_LIST_APPEND(lookup_list
, lookup
, link
);
4496 printf("\n\nLaunch a query to find a RRset of type ");
4498 printf(" for zone: %s\n", lookup
->textname
);
4503 insert_trustedkey(void *arg
, dns_name_t
*name
, dns_rdataset_t
*rdataset
)
4505 isc_result_t result
;
4510 if (rdataset
== NULL
|| rdataset
->type
!= dns_rdatatype_dnskey
)
4511 return (ISC_R_SUCCESS
);
4513 for (result
= dns_rdataset_first(rdataset
);
4514 result
== ISC_R_SUCCESS
;
4515 result
= dns_rdataset_next(rdataset
)) {
4516 dns_rdata_t rdata
= DNS_RDATA_INIT
;
4519 dns_rdataset_current(rdataset
, &rdata
);
4520 isc_buffer_init(&b
, rdata
.data
, rdata
.length
);
4521 isc_buffer_add(&b
, rdata
.length
);
4522 if (tk_list
.nb_tk
>= MAX_TRUSTED_KEY
)
4523 return (ISC_R_SUCCESS
);
4525 result
= dst_key_fromdns(name
, rdata
.rdclass
, &b
, mctx
, &key
);
4526 if (result
!= ISC_R_SUCCESS
)
4528 tk_list
.key
[tk_list
.nb_tk
++] = key
;
4530 return (ISC_R_SUCCESS
);
4538 for (i
= 0; i
< MAX_TRUSTED_KEY
; i
++) {
4539 if (tk_list
.key
[i
] != NULL
) {
4540 dst_key_free(&tk_list
.key
[i
]);
4541 tk_list
.key
[i
] = NULL
;
4550 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
4553 removetmpkey(isc_mem_t
*mctx
, const char *file
)
4555 char *tempnamekey
= NULL
;
4557 isc_result_t result
;
4559 tempnamekeylen
= strlen(file
)+10;
4561 tempnamekey
= isc_mem_allocate(mctx
, tempnamekeylen
);
4562 if (tempnamekey
== NULL
)
4563 return (ISC_R_NOMEMORY
);
4565 memset(tempnamekey
, 0, tempnamekeylen
);
4567 strcat(tempnamekey
, file
);
4568 strcat(tempnamekey
,".key");
4569 isc_file_remove(tempnamekey
);
4571 result
= isc_file_remove(tempnamekey
);
4572 isc_mem_free(mctx
, tempnamekey
);
4577 get_trusted_key(isc_mem_t
*mctx
)
4579 isc_result_t result
;
4580 const char *filename
= NULL
;
4581 dns_rdatacallbacks_t callbacks
;
4583 result
= isc_file_exists(trustedkey
);
4584 if (result
!= ISC_TRUE
) {
4585 result
= isc_file_exists("/etc/trusted-key.key");
4586 if (result
!= ISC_TRUE
) {
4587 result
= isc_file_exists("./trusted-key.key");
4588 if (result
!= ISC_TRUE
)
4589 return (ISC_R_FAILURE
);
4591 filename
= "./trusted-key.key";
4593 filename
= "/etc/trusted-key.key";
4595 filename
= trustedkey
;
4597 if (filename
== NULL
) {
4598 printf("No trusted key\n");
4599 return (ISC_R_FAILURE
);
4602 dns_rdatacallbacks_init_stdio(&callbacks
);
4603 callbacks
.add
= insert_trustedkey
;
4604 return (dns_master_loadfile(filename
, dns_rootname
, dns_rootname
,
4605 current_lookup
->rdclass
, DNS_MASTER_NOTTL
,
4611 nameFromString(const char *str
, dns_name_t
*p_ret
) {
4612 size_t len
= strlen(str
);
4613 isc_result_t result
;
4614 isc_buffer_t buffer
;
4615 dns_fixedname_t fixedname
;
4617 REQUIRE(p_ret
!= NULL
);
4618 REQUIRE(str
!= NULL
);
4620 isc_buffer_constinit(&buffer
, str
, len
);
4621 isc_buffer_add(&buffer
, len
);
4623 dns_fixedname_init(&fixedname
);
4624 result
= dns_name_fromtext(dns_fixedname_name(&fixedname
), &buffer
,
4625 dns_rootname
, DNS_NAME_DOWNCASE
, NULL
);
4626 check_result(result
, "nameFromString");
4628 if (dns_name_dynamic(p_ret
))
4629 free_name(p_ret
, mctx
);
4631 result
= dns_name_dup(dns_fixedname_name(&fixedname
), mctx
, p_ret
);
4632 check_result(result
, "nameFromString");
4638 prepare_lookup(dns_name_t
*name
)
4640 isc_result_t result
;
4641 dig_lookup_t
*lookup
= NULL
;
4645 lookup
= clone_lookup(current_lookup
, ISC_TRUE
);
4646 lookup
->trace_root
= ISC_FALSE
;
4647 lookup
->new_search
= ISC_TRUE
;
4648 lookup
->trace_root_sigchase
= ISC_FALSE
;
4650 strlcpy(lookup
->textname
, lookup
->textnamesigchase
, MXNAME
);
4652 lookup
->rdtype
= lookup
->rdtype_sigchase
;
4653 lookup
->rdtypeset
= ISC_TRUE
;
4654 lookup
->qrdtype
= lookup
->qrdtype_sigchase
;
4656 s
= ISC_LIST_HEAD(lookup
->my_server_list
);
4658 debug("freeing server %p belonging to %p",
4661 s
= ISC_LIST_NEXT(s
, link
);
4662 ISC_LIST_DEQUEUE(lookup
->my_server_list
,
4663 (dig_server_t
*)ptr
, link
);
4664 isc_mem_free(mctx
, ptr
);
4668 for (result
= dns_rdataset_first(chase_nsrdataset
);
4669 result
== ISC_R_SUCCESS
;
4670 result
= dns_rdataset_next(chase_nsrdataset
)) {
4671 char namestr
[DNS_NAME_FORMATSIZE
];
4673 dns_rdata_t rdata
= DNS_RDATA_INIT
;
4674 dig_server_t
* srv
= NULL
;
4675 #define __FOLLOW_GLUE__
4676 #ifdef __FOLLOW_GLUE__
4677 isc_buffer_t
*b
= NULL
;
4678 isc_result_t result
;
4680 dns_rdataset_t
*rdataset
= NULL
;
4681 isc_boolean_t
true = ISC_TRUE
;
4684 memset(namestr
, 0, DNS_NAME_FORMATSIZE
);
4686 dns_rdataset_current(chase_nsrdataset
, &rdata
);
4688 result
= dns_rdata_tostruct(&rdata
, &ns
, NULL
);
4689 check_result(result
, "dns_rdata_tostruct");
4691 #ifdef __FOLLOW_GLUE__
4693 result
= advanced_rrsearch(&rdataset
, &ns
.name
,
4695 dns_rdatatype_any
, &true);
4696 if (result
== ISC_R_SUCCESS
) {
4697 for (result
= dns_rdataset_first(rdataset
);
4698 result
== ISC_R_SUCCESS
;
4699 result
= dns_rdataset_next(rdataset
)) {
4700 dns_rdata_t aaaa
= DNS_RDATA_INIT
;
4701 dns_rdataset_current(rdataset
, &aaaa
);
4703 result
= isc_buffer_allocate(mctx
, &b
, 80);
4704 check_result(result
, "isc_buffer_allocate");
4706 dns_rdata_totext(&aaaa
, &ns
.name
, b
);
4707 isc_buffer_usedregion(b
, &r
);
4708 r
.base
[r
.length
] = '\0';
4709 strlcpy(namestr
, (char*)r
.base
,
4710 DNS_NAME_FORMATSIZE
);
4711 isc_buffer_free(&b
);
4712 dns_rdata_reset(&aaaa
);
4715 srv
= make_server(namestr
, namestr
);
4717 ISC_LIST_APPEND(lookup
->my_server_list
,
4723 result
= advanced_rrsearch(&rdataset
, &ns
.name
, dns_rdatatype_a
,
4724 dns_rdatatype_any
, &true);
4725 if (result
== ISC_R_SUCCESS
) {
4726 for (result
= dns_rdataset_first(rdataset
);
4727 result
== ISC_R_SUCCESS
;
4728 result
= dns_rdataset_next(rdataset
)) {
4729 dns_rdata_t a
= DNS_RDATA_INIT
;
4730 dns_rdataset_current(rdataset
, &a
);
4732 result
= isc_buffer_allocate(mctx
, &b
, 80);
4733 check_result(result
, "isc_buffer_allocate");
4735 dns_rdata_totext(&a
, &ns
.name
, b
);
4736 isc_buffer_usedregion(b
, &r
);
4737 r
.base
[r
.length
] = '\0';
4738 strlcpy(namestr
, (char*)r
.base
,
4739 DNS_NAME_FORMATSIZE
);
4740 isc_buffer_free(&b
);
4741 dns_rdata_reset(&a
);
4742 printf("ns name: %s\n", namestr
);
4745 srv
= make_server(namestr
, namestr
);
4747 ISC_LIST_APPEND(lookup
->my_server_list
,
4753 dns_name_format(&ns
.name
, namestr
, sizeof(namestr
));
4754 printf("ns name: ");
4755 dns_name_print(&ns
.name
, stdout
);
4757 srv
= make_server(namestr
, namestr
);
4759 ISC_LIST_APPEND(lookup
->my_server_list
, srv
, link
);
4762 dns_rdata_freestruct(&ns
);
4763 dns_rdata_reset(&rdata
);
4767 ISC_LIST_APPEND(lookup_list
, lookup
, link
);
4768 printf("\nLaunch a query to find a RRset of type ");
4769 print_type(lookup
->rdtype
);
4770 printf(" for zone: %s", lookup
->textname
);
4771 printf(" with nameservers:");
4773 print_rdataset(name
, chase_nsrdataset
, mctx
);
4774 return (ISC_R_SUCCESS
);
4779 child_of_zone(dns_name_t
* name
, dns_name_t
* zone_name
,
4780 dns_name_t
* child_name
)
4782 dns_namereln_t name_reln
;
4784 unsigned int nlabelsp
;
4786 name_reln
= dns_name_fullcompare(name
, zone_name
, &orderp
, &nlabelsp
);
4787 if (name_reln
!= dns_namereln_subdomain
||
4788 dns_name_countlabels(name
) <= dns_name_countlabels(zone_name
) + 1) {
4789 printf("\n;; ERROR : ");
4790 dns_name_print(name
, stdout
);
4791 printf(" is not a subdomain of: ");
4792 dns_name_print(zone_name
, stdout
);
4793 printf(" FAILED\n\n");
4794 return (ISC_R_FAILURE
);
4797 dns_name_getlabelsequence(name
,
4798 dns_name_countlabels(name
) -
4799 dns_name_countlabels(zone_name
) -1,
4800 dns_name_countlabels(zone_name
) +1,
4802 return (ISC_R_SUCCESS
);
4806 grandfather_pb_test(dns_name_t
*zone_name
, dns_rdataset_t
*sigrdataset
) {
4807 dns_rdata_sig_t siginfo
;
4808 dns_rdataset_t mysigrdataset
;
4809 isc_result_t result
;
4811 dns_rdataset_init(&mysigrdataset
);
4812 dns_rdataset_clone(sigrdataset
, &mysigrdataset
);
4814 result
= dns_rdataset_first(&mysigrdataset
);
4815 check_result(result
, "empty RRSIG dataset");
4818 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
4820 dns_rdataset_current(&mysigrdataset
, &sigrdata
);
4822 result
= dns_rdata_tostruct(&sigrdata
, &siginfo
, NULL
);
4823 check_result(result
, "sigrdata tostruct siginfo");
4825 if (dns_name_compare(&siginfo
.signer
, zone_name
) == 0) {
4826 result
= ISC_R_SUCCESS
;
4829 } while (dns_rdataset_next(&mysigrdataset
) == ISC_R_SUCCESS
);
4831 result
= ISC_R_FAILURE
;
4833 dns_rdataset_disassociate(&mysigrdataset
);
4840 initialization(dns_name_t
*name
)
4842 isc_result_t result
;
4843 isc_boolean_t
true = ISC_TRUE
;
4845 chase_nsrdataset
= NULL
;
4846 result
= advanced_rrsearch(&chase_nsrdataset
, name
, dns_rdatatype_ns
,
4847 dns_rdatatype_any
, &true);
4848 if (result
!= ISC_R_SUCCESS
) {
4849 printf("\n;; NS RRset is missing to continue validation:"
4851 return (ISC_R_FAILURE
);
4853 INSIST(chase_nsrdataset
!= NULL
);
4854 prepare_lookup(name
);
4856 dup_name(name
, &chase_current_name
, mctx
);
4858 return (ISC_R_SUCCESS
);
4863 print_rdataset(dns_name_t
*name
, dns_rdataset_t
*rdataset
, isc_mem_t
*mctx
)
4865 isc_buffer_t
*b
= NULL
;
4866 isc_result_t result
;
4869 result
= isc_buffer_allocate(mctx
, &b
, 9000);
4870 check_result(result
, "isc_buffer_allocate");
4872 printrdataset(name
, rdataset
, b
);
4874 isc_buffer_usedregion(b
, &r
);
4875 r
.base
[r
.length
] = '\0';
4878 printf("%s\n", r
.base
);
4880 isc_buffer_free(&b
);
4885 dup_name(dns_name_t
*source
, dns_name_t
*target
, isc_mem_t
*mctx
) {
4886 isc_result_t result
;
4888 if (dns_name_dynamic(target
))
4889 free_name(target
, mctx
);
4890 result
= dns_name_dup(source
, mctx
, target
);
4891 check_result(result
, "dns_name_dup");
4895 free_name(dns_name_t
*name
, isc_mem_t
*mctx
) {
4896 dns_name_free(name
, mctx
);
4897 dns_name_init(name
, NULL
);
4902 * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter
4903 * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key
4904 * and the RRset is valid
4905 * return ISC_R_NOTFOUND if not contains trusted key
4906 or if the RRset isn't valid
4907 * return ISC_R_FAILURE if problem
4911 contains_trusted_key(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
4912 dns_rdataset_t
*sigrdataset
,
4915 dns_rdataset_t myrdataset
;
4916 dst_key_t
*dnsseckey
= NULL
;
4918 isc_result_t result
;
4920 if (name
== NULL
|| rdataset
== NULL
)
4921 return (ISC_R_FAILURE
);
4923 dns_rdataset_init(&myrdataset
);
4924 dns_rdataset_clone(rdataset
, &myrdataset
);
4926 result
= dns_rdataset_first(&myrdataset
);
4927 check_result(result
, "empty rdataset");
4930 dns_rdata_t rdata
= DNS_RDATA_INIT
;
4932 dns_rdataset_current(&myrdataset
, &rdata
);
4933 INSIST(rdata
.type
== dns_rdatatype_dnskey
);
4935 result
= dns_dnssec_keyfromrdata(name
, &rdata
,
4937 check_result(result
, "dns_dnssec_keyfromrdata");
4939 for (i
= 0; i
< tk_list
.nb_tk
; i
++) {
4940 if (dst_key_compare(tk_list
.key
[i
], dnsseckey
)
4942 dns_rdata_reset(&rdata
);
4944 printf(";; Ok, find a Trusted Key in the "
4945 "DNSKEY RRset: %d\n",
4946 dst_key_id(dnsseckey
));
4947 result
= sigchase_verify_sig_key(name
, rdataset
,
4951 if (result
== ISC_R_SUCCESS
)
4955 dst_key_free(&dnsseckey
);
4956 } while (dns_rdataset_next(&myrdataset
) == ISC_R_SUCCESS
);
4959 if (dnsseckey
!= NULL
)
4960 dst_key_free(&dnsseckey
);
4961 dns_rdataset_disassociate(&myrdataset
);
4963 return (ISC_R_NOTFOUND
);
4967 sigchase_verify_sig(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
4968 dns_rdataset_t
*keyrdataset
,
4969 dns_rdataset_t
*sigrdataset
,
4972 dns_rdataset_t mykeyrdataset
;
4973 dst_key_t
*dnsseckey
= NULL
;
4974 isc_result_t result
;
4976 dns_rdataset_init(&mykeyrdataset
);
4977 dns_rdataset_clone(keyrdataset
, &mykeyrdataset
);
4979 result
= dns_rdataset_first(&mykeyrdataset
);
4980 check_result(result
, "empty DNSKEY dataset");
4983 dns_rdata_t keyrdata
= DNS_RDATA_INIT
;
4985 dns_rdataset_current(&mykeyrdataset
, &keyrdata
);
4986 INSIST(keyrdata
.type
== dns_rdatatype_dnskey
);
4988 result
= dns_dnssec_keyfromrdata(name
, &keyrdata
,
4990 check_result(result
, "dns_dnssec_keyfromrdata");
4992 result
= sigchase_verify_sig_key(name
, rdataset
, dnsseckey
,
4994 if (result
== ISC_R_SUCCESS
)
4996 dst_key_free(&dnsseckey
);
4997 } while (dns_rdataset_next(&mykeyrdataset
) == ISC_R_SUCCESS
);
4999 result
= ISC_R_NOTFOUND
;
5002 if (dnsseckey
!= NULL
)
5003 dst_key_free(&dnsseckey
);
5004 dns_rdataset_disassociate(&mykeyrdataset
);
5010 sigchase_verify_sig_key(dns_name_t
*name
, dns_rdataset_t
*rdataset
,
5011 dst_key_t
*dnsseckey
, dns_rdataset_t
*sigrdataset
,
5014 dns_rdata_sig_t siginfo
;
5015 dns_rdataset_t myrdataset
;
5016 dns_rdataset_t mysigrdataset
;
5017 isc_result_t result
;
5019 dns_rdataset_init(&myrdataset
);
5020 dns_rdataset_clone(rdataset
, &myrdataset
);
5021 dns_rdataset_init(&mysigrdataset
);
5022 dns_rdataset_clone(sigrdataset
, &mysigrdataset
);
5024 result
= dns_rdataset_first(&mysigrdataset
);
5025 check_result(result
, "empty RRSIG dataset");
5028 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
5030 dns_rdataset_current(&mysigrdataset
, &sigrdata
);
5032 result
= dns_rdata_tostruct(&sigrdata
, &siginfo
, NULL
);
5033 check_result(result
, "sigrdata tostruct siginfo");
5036 * Test if the id of the DNSKEY is
5037 * the id of the DNSKEY signer's
5039 if (siginfo
.keyid
== dst_key_id(dnsseckey
)) {
5041 result
= dns_rdataset_first(&myrdataset
);
5042 check_result(result
, "empty DS dataset");
5044 result
= dns_dnssec_verify(name
, &myrdataset
, dnsseckey
,
5045 ISC_FALSE
, mctx
, &sigrdata
);
5047 printf(";; VERIFYING ");
5048 print_type(rdataset
->type
);
5049 printf(" RRset for ");
5050 dns_name_print(name
, stdout
);
5051 printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey
),
5052 isc_result_totext(result
));
5054 if (result
== ISC_R_SUCCESS
)
5057 } while (dns_rdataset_next(&mysigrdataset
) == ISC_R_SUCCESS
);
5059 result
= ISC_R_NOTFOUND
;
5062 dns_rdataset_disassociate(&myrdataset
);
5063 dns_rdataset_disassociate(&mysigrdataset
);
5070 sigchase_verify_ds(dns_name_t
*name
, dns_rdataset_t
*keyrdataset
,
5071 dns_rdataset_t
*dsrdataset
, isc_mem_t
*mctx
)
5073 dns_rdata_ds_t dsinfo
;
5074 dns_rdataset_t mydsrdataset
;
5075 dns_rdataset_t mykeyrdataset
;
5076 dst_key_t
*dnsseckey
= NULL
;
5077 isc_result_t result
;
5078 unsigned char dsbuf
[DNS_DS_BUFFERSIZE
];
5080 dns_rdataset_init(&mydsrdataset
);
5081 dns_rdataset_clone(dsrdataset
, &mydsrdataset
);
5082 dns_rdataset_init(&mykeyrdataset
);
5083 dns_rdataset_clone(keyrdataset
, &mykeyrdataset
);
5085 result
= dns_rdataset_first(&mydsrdataset
);
5086 check_result(result
, "empty DSset dataset");
5088 dns_rdata_t dsrdata
= DNS_RDATA_INIT
;
5090 dns_rdataset_current(&mydsrdataset
, &dsrdata
);
5092 result
= dns_rdata_tostruct(&dsrdata
, &dsinfo
, NULL
);
5093 check_result(result
, "dns_rdata_tostruct for DS");
5095 result
= dns_rdataset_first(&mykeyrdataset
);
5096 check_result(result
, "empty KEY dataset");
5099 dns_rdata_t keyrdata
= DNS_RDATA_INIT
;
5101 dns_rdataset_current(&mykeyrdataset
, &keyrdata
);
5102 INSIST(keyrdata
.type
== dns_rdatatype_dnskey
);
5104 result
= dns_dnssec_keyfromrdata(name
, &keyrdata
,
5106 check_result(result
, "dns_dnssec_keyfromrdata");
5109 * Test if the id of the DNSKEY is the
5110 * id of DNSKEY referenced by the DS
5112 if (dsinfo
.key_tag
== dst_key_id(dnsseckey
)) {
5113 dns_rdata_t newdsrdata
= DNS_RDATA_INIT
;
5115 result
= dns_ds_buildrdata(name
, &keyrdata
,
5117 dsbuf
, &newdsrdata
);
5118 dns_rdata_freestruct(&dsinfo
);
5120 if (result
!= ISC_R_SUCCESS
) {
5121 printf("Oops: impossible to build"
5127 if (dns_rdata_compare(&dsrdata
,
5128 &newdsrdata
) == 0) {
5129 printf(";; OK a DS valids a DNSKEY"
5131 printf(";; Now verify that this"
5132 " DNSKEY validates the "
5135 result
= sigchase_verify_sig_key(name
,
5138 chase_sigkeyrdataset
,
5140 if (result
== ISC_R_SUCCESS
)
5143 printf(";; This DS is NOT the DS for"
5144 " the chasing KEY: FAILED\n");
5147 dst_key_free(&dnsseckey
);
5148 } while (dns_rdataset_next(&mykeyrdataset
) == ISC_R_SUCCESS
);
5149 } while (dns_rdataset_next(&mydsrdataset
) == ISC_R_SUCCESS
);
5151 result
= ISC_R_NOTFOUND
;
5154 if (dnsseckey
!= NULL
)
5155 dst_key_free(&dnsseckey
);
5156 dns_rdataset_disassociate(&mydsrdataset
);
5157 dns_rdataset_disassociate(&mykeyrdataset
);
5164 * take a pointer on a rdataset in parameter and try to resolv it.
5165 * the searched rrset is a rrset on 'name' with type 'type'
5166 * (and if the type is a rrsig the signature cover 'covers').
5167 * the lookedup is to known if you have already done the query on the net.
5168 * ISC_R_SUCCESS: if we found the rrset
5169 * ISC_R_NOTFOUND: we do not found the rrset in cache
5170 * and we do a query on the net
5171 * ISC_R_FAILURE: rrset not found
5174 advanced_rrsearch(dns_rdataset_t
**rdataset
, dns_name_t
*name
,
5175 dns_rdatatype_t type
, dns_rdatatype_t covers
,
5176 isc_boolean_t
*lookedup
)
5178 isc_boolean_t tmplookedup
;
5180 INSIST(rdataset
!= NULL
);
5182 if (*rdataset
!= NULL
)
5183 return (ISC_R_SUCCESS
);
5185 tmplookedup
= *lookedup
;
5186 if ((*rdataset
= sigchase_scanname(type
, covers
,
5187 lookedup
, name
)) == NULL
) {
5189 return (ISC_R_FAILURE
);
5190 return (ISC_R_NOTFOUND
);
5192 *lookedup
= ISC_FALSE
;
5193 return (ISC_R_SUCCESS
);
5200 sigchase_td(dns_message_t
*msg
)
5202 isc_result_t result
;
5203 dns_name_t
*name
= NULL
;
5204 isc_boolean_t have_answer
= ISC_FALSE
;
5205 isc_boolean_t
true = ISC_TRUE
;
5207 if (msg
->rcode
!= dns_rcode_noerror
&&
5208 msg
->rcode
!= dns_rcode_nxdomain
) {
5212 isc_buffer_init(&b
, buf
, sizeof(buf
));
5213 result
= dns_rcode_totext(msg
->rcode
, &b
);
5214 check_result(result
, "dns_rcode_totext failed");
5215 printf("error response code %.*s\n",
5216 (int)isc_buffer_usedlength(&b
), buf
);
5217 error_message
= msg
;
5221 if ((result
= dns_message_firstname(msg
, DNS_SECTION_ANSWER
))
5223 dns_message_currentname(msg
, DNS_SECTION_ANSWER
, &name
);
5224 if (current_lookup
->trace_root_sigchase
) {
5225 initialization(name
);
5230 if (!current_lookup
->trace_root_sigchase
) {
5231 result
= dns_message_firstname(msg
,
5232 DNS_SECTION_AUTHORITY
);
5233 if (result
!= ISC_R_SUCCESS
) {
5234 printf("no answer or authority section\n");
5235 error_message
= msg
;
5238 dns_message_currentname(msg
, DNS_SECTION_AUTHORITY
,
5241 = chase_scanname_section(msg
, name
,
5244 DNS_SECTION_AUTHORITY
);
5245 dup_name(name
, &chase_authority_name
, mctx
);
5246 if (chase_nsrdataset
!= NULL
) {
5247 have_delegation_ns
= ISC_TRUE
;
5248 printf("no response but there is a delegation"
5249 " in authority section: ");
5250 dns_name_print(name
, stdout
);
5253 printf("no response and no delegation in "
5254 "authority section but a reference"
5256 dns_name_print(name
, stdout
);
5258 error_message
= msg
;
5261 printf(";; NO ANSWERS: %s\n",
5262 isc_result_totext(result
));
5263 free_name(&chase_name
, mctx
);
5272 = chase_scanname_section(msg
, &chase_name
,
5276 DNS_SECTION_ANSWER
);
5277 if (chase_rdataset
!= NULL
)
5278 have_response
= ISC_TRUE
;
5281 result
= advanced_rrsearch(&chase_keyrdataset
,
5282 &chase_current_name
,
5283 dns_rdatatype_dnskey
,
5285 &chase_keylookedup
);
5286 if (result
== ISC_R_FAILURE
) {
5287 printf("\n;; DNSKEY is missing to continue validation:"
5291 if (result
== ISC_R_NOTFOUND
)
5293 INSIST(chase_keyrdataset
!= NULL
);
5294 printf("\n;; DNSKEYset:\n");
5295 print_rdataset(&chase_current_name
, chase_keyrdataset
, mctx
);
5298 result
= advanced_rrsearch(&chase_sigkeyrdataset
,
5299 &chase_current_name
,
5300 dns_rdatatype_rrsig
,
5301 dns_rdatatype_dnskey
,
5302 &chase_sigkeylookedup
);
5303 if (result
== ISC_R_FAILURE
) {
5304 printf("\n;; RRSIG of DNSKEY is missing to continue validation:"
5308 if (result
== ISC_R_NOTFOUND
)
5310 INSIST(chase_sigkeyrdataset
!= NULL
);
5311 printf("\n;; RRSIG of the DNSKEYset:\n");
5312 print_rdataset(&chase_current_name
, chase_sigkeyrdataset
, mctx
);
5315 if (!chase_dslookedup
&& !chase_nslookedup
) {
5316 if (!delegation_follow
) {
5317 result
= contains_trusted_key(&chase_current_name
,
5319 chase_sigkeyrdataset
,
5322 INSIST(chase_dsrdataset
!= NULL
);
5323 INSIST(chase_sigdsrdataset
!= NULL
);
5324 result
= sigchase_verify_ds(&chase_current_name
,
5330 if (result
!= ISC_R_SUCCESS
) {
5331 printf("\n;; chain of trust can't be validated:"
5335 chase_dsrdataset
= NULL
;
5336 chase_sigdsrdataset
= NULL
;
5340 if (have_response
|| (!have_delegation_ns
&& !have_response
)) {
5341 /* test if it's a grand father case */
5343 if (have_response
) {
5344 result
= advanced_rrsearch(&chase_sigrdataset
,
5346 dns_rdatatype_rrsig
,
5350 if (result
== ISC_R_FAILURE
) {
5351 printf("\n;; RRset is missing to continue"
5352 " validation SHOULD NOT APPEND:"
5358 result
= advanced_rrsearch(&chase_sigrdataset
,
5359 &chase_authority_name
,
5360 dns_rdatatype_rrsig
,
5363 if (result
== ISC_R_FAILURE
) {
5364 printf("\n;; RRSIG is missing to continue"
5365 " validation SHOULD NOT APPEND:"
5370 result
= grandfather_pb_test(&chase_current_name
,
5372 if (result
!= ISC_R_SUCCESS
) {
5373 dns_name_t tmp_name
;
5375 printf("\n;; We are in a Grand Father Problem:"
5376 " See 2.2.1 in RFC 3658\n");
5377 chase_rdataset
= NULL
;
5378 chase_sigrdataset
= NULL
;
5379 have_response
= ISC_FALSE
;
5380 have_delegation_ns
= ISC_FALSE
;
5382 dns_name_init(&tmp_name
, NULL
);
5383 result
= child_of_zone(&chase_name
, &chase_current_name
,
5385 if (dns_name_dynamic(&chase_authority_name
))
5386 free_name(&chase_authority_name
, mctx
);
5387 dup_name(&tmp_name
, &chase_authority_name
, mctx
);
5388 printf(";; and we try to continue chain of trust"
5389 " validation of the zone: ");
5390 dns_name_print(&chase_authority_name
, stdout
);
5392 have_delegation_ns
= ISC_TRUE
;
5397 chase_sigrdataset
= NULL
;
5401 if (have_delegation_ns
) {
5402 chase_nsrdataset
= NULL
;
5403 result
= advanced_rrsearch(&chase_nsrdataset
,
5404 &chase_authority_name
,
5408 if (result
== ISC_R_FAILURE
) {
5409 printf("\n;;NSset is missing to continue validation:"
5413 if (result
== ISC_R_NOTFOUND
) {
5416 INSIST(chase_nsrdataset
!= NULL
);
5418 result
= advanced_rrsearch(&chase_dsrdataset
,
5419 &chase_authority_name
,
5423 if (result
== ISC_R_FAILURE
) {
5424 printf("\n;; DSset is missing to continue validation:"
5428 if (result
== ISC_R_NOTFOUND
)
5430 INSIST(chase_dsrdataset
!= NULL
);
5431 printf("\n;; DSset:\n");
5432 print_rdataset(&chase_authority_name
, chase_dsrdataset
, mctx
);
5434 result
= advanced_rrsearch(&chase_sigdsrdataset
,
5435 &chase_authority_name
,
5436 dns_rdatatype_rrsig
,
5439 if (result
!= ISC_R_SUCCESS
) {
5440 printf("\n;; DSset is missing to continue validation:"
5444 printf("\n;; RRSIGset of DSset\n");
5445 print_rdataset(&chase_authority_name
,
5446 chase_sigdsrdataset
, mctx
);
5447 INSIST(chase_sigdsrdataset
!= NULL
);
5449 result
= sigchase_verify_sig(&chase_authority_name
,
5452 chase_sigdsrdataset
, mctx
);
5453 if (result
!= ISC_R_SUCCESS
) {
5454 printf("\n;; Impossible to verify the DSset:"
5458 chase_keyrdataset
= NULL
;
5459 chase_sigkeyrdataset
= NULL
;
5462 prepare_lookup(&chase_authority_name
);
5464 have_response
= ISC_FALSE
;
5465 have_delegation_ns
= ISC_FALSE
;
5466 delegation_follow
= ISC_TRUE
;
5467 error_message
= NULL
;
5468 dup_name(&chase_authority_name
, &chase_current_name
, mctx
);
5469 free_name(&chase_authority_name
, mctx
);
5474 if (error_message
!= NULL
) {
5475 dns_rdataset_t
*rdataset
;
5476 dns_rdataset_t
*sigrdataset
;
5477 dns_name_t rdata_name
;
5478 isc_result_t ret
= ISC_R_FAILURE
;
5480 dns_name_init(&rdata_name
, NULL
);
5481 result
= prove_nx(error_message
, &chase_name
,
5482 current_lookup
->rdclass_sigchase
,
5483 current_lookup
->rdtype_sigchase
, &rdata_name
,
5484 &rdataset
, &sigrdataset
);
5485 if (rdataset
== NULL
|| sigrdataset
== NULL
||
5486 dns_name_countlabels(&rdata_name
) == 0) {
5487 printf("\n;; Impossible to verify the non-existence,"
5488 " the NSEC RRset can't be validated:"
5492 ret
= sigchase_verify_sig(&rdata_name
, rdataset
,
5495 if (ret
!= ISC_R_SUCCESS
) {
5496 free_name(&rdata_name
, mctx
);
5497 printf("\n;; Impossible to verify the NSEC RR to prove"
5498 " the non-existence : FAILED\n\n");
5501 free_name(&rdata_name
, mctx
);
5502 if (result
!= ISC_R_SUCCESS
) {
5503 printf("\n;; Impossible to verify the non-existence:"
5507 printf("\n;; OK the query doesn't have response but"
5508 " we have validate this fact : SUCCESS\n\n");
5514 printf(";; cleanandgo \n");
5515 if (dns_name_dynamic(&chase_current_name
))
5516 free_name(&chase_current_name
, mctx
);
5517 if (dns_name_dynamic(&chase_authority_name
))
5518 free_name(&chase_authority_name
, mctx
);
5523 result
= advanced_rrsearch(&chase_rdataset
, &chase_name
,
5524 current_lookup
->rdtype_sigchase
,
5527 if (result
== ISC_R_FAILURE
) {
5528 printf("\n;; RRsig of RRset is missing to continue validation"
5529 " SHOULD NOT APPEND: FAILED\n\n");
5532 result
= sigchase_verify_sig(&chase_name
, chase_rdataset
,
5534 chase_sigrdataset
, mctx
);
5535 if (result
!= ISC_R_SUCCESS
) {
5536 printf("\n;; Impossible to verify the RRset : FAILED\n\n");
5539 print_rdataset(&chase_name , chase_rdataset, mctx);
5540 printf("DNSKEYset:\n");
5541 print_rdataset(&chase_name , chase_keyrdataset, mctx);
5542 printf("RRSIG of RRset:\n");
5543 print_rdataset(&chase_name , chase_sigrdataset, mctx);
5548 printf("\n;; The Answer:\n");
5549 print_rdataset(&chase_name
, chase_rdataset
, mctx
);
5551 printf("\n;; FINISH : we have validate the DNSSEC chain"
5552 " of trust: SUCCESS\n\n");
5563 getneededrr(dns_message_t
*msg
)
5565 isc_result_t result
;
5566 dns_name_t
*name
= NULL
;
5567 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
5568 dns_rdata_sig_t siginfo
;
5569 isc_boolean_t
true = ISC_TRUE
;
5571 if ((result
= dns_message_firstname(msg
, DNS_SECTION_ANSWER
))
5573 printf(";; NO ANSWERS: %s\n", isc_result_totext(result
));
5575 if (chase_name
.ndata
== NULL
)
5576 return (ISC_R_ADDRNOTAVAIL
);
5578 dns_message_currentname(msg
, DNS_SECTION_ANSWER
, &name
);
5581 /* What do we chase? */
5582 if (chase_rdataset
== NULL
) {
5583 result
= advanced_rrsearch(&chase_rdataset
, name
,
5585 dns_rdatatype_any
, &true);
5586 if (result
!= ISC_R_SUCCESS
) {
5587 printf("\n;; No Answers: Validation FAILED\n\n");
5588 return (ISC_R_NOTFOUND
);
5590 dup_name(name
, &chase_name
, mctx
);
5591 printf(";; RRset to chase:\n");
5592 print_rdataset(&chase_name
, chase_rdataset
, mctx
);
5594 INSIST(chase_rdataset
!= NULL
);
5597 if (chase_sigrdataset
== NULL
) {
5598 result
= advanced_rrsearch(&chase_sigrdataset
, name
,
5599 dns_rdatatype_rrsig
,
5600 chase_rdataset
->type
,
5601 &chase_siglookedup
);
5602 if (result
== ISC_R_FAILURE
) {
5603 printf("\n;; RRSIG is missing for continue validation:"
5605 if (dns_name_dynamic(&chase_name
))
5606 free_name(&chase_name
, mctx
);
5607 return (ISC_R_NOTFOUND
);
5609 if (result
== ISC_R_NOTFOUND
) {
5610 return (ISC_R_NOTFOUND
);
5612 printf("\n;; RRSIG of the RRset to chase:\n");
5613 print_rdataset(&chase_name
, chase_sigrdataset
, mctx
);
5615 INSIST(chase_sigrdataset
!= NULL
);
5618 /* first find the DNSKEY name */
5619 result
= dns_rdataset_first(chase_sigrdataset
);
5620 check_result(result
, "empty RRSIG dataset");
5621 dns_rdataset_current(chase_sigrdataset
, &sigrdata
);
5622 result
= dns_rdata_tostruct(&sigrdata
, &siginfo
, NULL
);
5623 check_result(result
, "sigrdata tostruct siginfo");
5624 dup_name(&siginfo
.signer
, &chase_signame
, mctx
);
5625 dns_rdata_freestruct(&siginfo
);
5626 dns_rdata_reset(&sigrdata
);
5628 /* Do we have a key? */
5629 if (chase_keyrdataset
== NULL
) {
5630 result
= advanced_rrsearch(&chase_keyrdataset
,
5632 dns_rdatatype_dnskey
,
5634 &chase_keylookedup
);
5635 if (result
== ISC_R_FAILURE
) {
5636 printf("\n;; DNSKEY is missing to continue validation:"
5638 free_name(&chase_signame
, mctx
);
5639 if (dns_name_dynamic(&chase_name
))
5640 free_name(&chase_name
, mctx
);
5641 return (ISC_R_NOTFOUND
);
5643 if (result
== ISC_R_NOTFOUND
) {
5644 free_name(&chase_signame
, mctx
);
5645 return (ISC_R_NOTFOUND
);
5647 printf("\n;; DNSKEYset that signs the RRset to chase:\n");
5648 print_rdataset(&chase_signame
, chase_keyrdataset
, mctx
);
5650 INSIST(chase_keyrdataset
!= NULL
);
5652 if (chase_sigkeyrdataset
== NULL
) {
5653 result
= advanced_rrsearch(&chase_sigkeyrdataset
,
5655 dns_rdatatype_rrsig
,
5656 dns_rdatatype_dnskey
,
5657 &chase_sigkeylookedup
);
5658 if (result
== ISC_R_FAILURE
) {
5659 printf("\n;; RRSIG for DNSKEY is missing to continue"
5660 " validation : FAILED\n\n");
5661 free_name(&chase_signame
, mctx
);
5662 if (dns_name_dynamic(&chase_name
))
5663 free_name(&chase_name
, mctx
);
5664 return (ISC_R_NOTFOUND
);
5666 if (result
== ISC_R_NOTFOUND
) {
5667 free_name(&chase_signame
, mctx
);
5668 return (ISC_R_NOTFOUND
);
5670 printf("\n;; RRSIG of the DNSKEYset that signs the "
5671 "RRset to chase:\n");
5672 print_rdataset(&chase_signame
, chase_sigkeyrdataset
, mctx
);
5674 INSIST(chase_sigkeyrdataset
!= NULL
);
5677 if (chase_dsrdataset
== NULL
) {
5678 result
= advanced_rrsearch(&chase_dsrdataset
, &chase_signame
,
5679 dns_rdatatype_ds
, dns_rdatatype_any
,
5681 if (result
== ISC_R_FAILURE
) {
5682 printf("\n;; WARNING There is no DS for the zone: ");
5683 dns_name_print(&chase_signame
, stdout
);
5686 if (result
== ISC_R_NOTFOUND
) {
5687 free_name(&chase_signame
, mctx
);
5688 return (ISC_R_NOTFOUND
);
5690 if (chase_dsrdataset
!= NULL
) {
5691 printf("\n;; DSset of the DNSKEYset\n");
5692 print_rdataset(&chase_signame
, chase_dsrdataset
, mctx
);
5696 if (chase_dsrdataset
!= NULL
) {
5698 * if there is no RRSIG of DS,
5699 * we don't want to search on the network
5701 result
= advanced_rrsearch(&chase_sigdsrdataset
,
5703 dns_rdatatype_rrsig
,
5704 dns_rdatatype_ds
, &true);
5705 if (result
== ISC_R_FAILURE
) {
5706 printf(";; WARNING : NO RRSIG DS : RRSIG DS"
5707 " should come with DS\n");
5709 * We continue even the DS couldn't be validated,
5710 * because the DNSKEY could be a Trusted Key.
5712 chase_dsrdataset
= NULL
;
5714 printf("\n;; RRSIG of the DSset of the DNSKEYset\n");
5715 print_rdataset(&chase_signame
, chase_sigdsrdataset
,
5725 sigchase_bu(dns_message_t
*msg
)
5727 isc_result_t result
;
5730 if (tk_list
.nb_tk
== 0) {
5731 result
= get_trusted_key(mctx
);
5732 if (result
!= ISC_R_SUCCESS
) {
5733 printf("No trusted keys present\n");
5739 ret
= getneededrr(msg
);
5740 if (ret
== ISC_R_NOTFOUND
)
5743 if (ret
== ISC_R_ADDRNOTAVAIL
) {
5744 /* We have no response */
5745 dns_rdataset_t
*rdataset
;
5746 dns_rdataset_t
*sigrdataset
;
5747 dns_name_t rdata_name
;
5748 dns_name_t query_name
;
5751 dns_name_init(&query_name
, NULL
);
5752 dns_name_init(&rdata_name
, NULL
);
5753 nameFromString(current_lookup
->textname
, &query_name
);
5755 result
= prove_nx(msg
, &query_name
, current_lookup
->rdclass
,
5756 current_lookup
->rdtype
, &rdata_name
,
5757 &rdataset
, &sigrdataset
);
5758 free_name(&query_name
, mctx
);
5759 if (rdataset
== NULL
|| sigrdataset
== NULL
||
5760 dns_name_countlabels(&rdata_name
) == 0) {
5761 printf("\n;; Impossible to verify the Non-existence,"
5762 " the NSEC RRset can't be validated: "
5768 if (result
!= ISC_R_SUCCESS
) {
5769 printf("\n No Answers and impossible to prove the"
5770 " unsecurity : Validation FAILED\n\n");
5774 printf(";; An NSEC prove the non-existence of a answers,"
5775 " Now we want validate this NSEC\n");
5777 dup_name(&rdata_name
, &chase_name
, mctx
);
5778 free_name(&rdata_name
, mctx
);
5779 chase_rdataset
= rdataset
;
5780 chase_sigrdataset
= sigrdataset
;
5781 chase_keyrdataset
= NULL
;
5782 chase_sigkeyrdataset
= NULL
;
5783 chase_dsrdataset
= NULL
;
5784 chase_sigdsrdataset
= NULL
;
5785 chase_siglookedup
= ISC_FALSE
;
5786 chase_keylookedup
= ISC_FALSE
;
5787 chase_dslookedup
= ISC_FALSE
;
5788 chase_sigdslookedup
= ISC_FALSE
;
5795 printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n");
5797 result
= sigchase_verify_sig(&chase_name
, chase_rdataset
,
5799 chase_sigrdataset
, mctx
);
5800 if (result
!= ISC_R_SUCCESS
) {
5801 free_name(&chase_name
, mctx
);
5802 free_name(&chase_signame
, mctx
);
5803 printf(";; No DNSKEY is valid to check the RRSIG"
5804 " of the RRset: FAILED\n");
5808 printf(";; OK We found DNSKEY (or more) to validate the RRset\n");
5810 result
= contains_trusted_key(&chase_signame
, chase_keyrdataset
,
5811 chase_sigkeyrdataset
, mctx
);
5812 if (result
== ISC_R_SUCCESS
) {
5813 free_name(&chase_name
, mctx
);
5814 free_name(&chase_signame
, mctx
);
5815 printf("\n;; Ok this DNSKEY is a Trusted Key,"
5816 " DNSSEC validation is ok: SUCCESS\n\n");
5821 printf(";; Now, we are going to validate this DNSKEY by the DS\n");
5823 if (chase_dsrdataset
== NULL
) {
5824 free_name(&chase_name
, mctx
);
5825 free_name(&chase_signame
, mctx
);
5826 printf(";; the DNSKEY isn't trusted-key and there isn't"
5827 " DS to validate the DNSKEY: FAILED\n");
5832 result
= sigchase_verify_ds(&chase_signame
, chase_keyrdataset
,
5833 chase_dsrdataset
, mctx
);
5834 if (result
!= ISC_R_SUCCESS
) {
5835 free_name(&chase_signame
, mctx
);
5836 free_name(&chase_name
, mctx
);
5837 printf(";; ERROR no DS validates a DNSKEY in the"
5838 " DNSKEY RRset: FAILED\n");
5842 printf(";; OK this DNSKEY (validated by the DS) validates"
5843 " the RRset of the DNSKEYs, thus the DNSKEY validates"
5845 INSIST(chase_sigdsrdataset
!= NULL
);
5847 dup_name(&chase_signame
, &chase_name
, mctx
);
5848 free_name(&chase_signame
, mctx
);
5849 chase_rdataset
= chase_dsrdataset
;
5850 chase_sigrdataset
= chase_sigdsrdataset
;
5851 chase_keyrdataset
= NULL
;
5852 chase_sigkeyrdataset
= NULL
;
5853 chase_dsrdataset
= NULL
;
5854 chase_sigdsrdataset
= NULL
;
5855 chase_siglookedup
= chase_keylookedup
= ISC_FALSE
;
5856 chase_dslookedup
= chase_sigdslookedup
= ISC_FALSE
;
5858 printf(";; Now, we want to validate the DS : recursive call\n");
5865 sigchase(dns_message_t
*msg
) {
5867 if (current_lookup
->do_topdown
) {
5880 * return 1 if name1 < name2
5881 * 0 if name1 == name2
5882 * -1 if name1 > name2
5886 inf_name(dns_name_t
*name1
, dns_name_t
*name2
)
5890 unsigned int nblabel1
;
5891 unsigned int nblabel2
;
5896 nblabel1
= dns_name_countlabels(name1
);
5897 nblabel2
= dns_name_countlabels(name2
);
5899 if (nblabel1
>= nblabel2
)
5900 min_lum_label
= nblabel2
;
5902 min_lum_label
= nblabel1
;
5905 for (i
=1 ; i
< min_lum_label
; i
++) {
5906 dns_name_getlabel(name1
, nblabel1
-1 - i
, &label1
);
5907 dns_name_getlabel(name2
, nblabel2
-1 - i
, &label2
);
5908 if ((ret
= isc_region_compare(&label1
, &label2
)) != 0) {
5915 if (nblabel1
== nblabel2
)
5918 if (nblabel1
< nblabel2
)
5930 prove_nx_domain(dns_message_t
*msg
,
5932 dns_name_t
*rdata_name
,
5933 dns_rdataset_t
**rdataset
,
5934 dns_rdataset_t
**sigrdataset
)
5936 isc_result_t ret
= ISC_R_FAILURE
;
5937 isc_result_t result
= ISC_R_NOTFOUND
;
5938 dns_rdataset_t
*nsecset
= NULL
;
5939 dns_rdataset_t
*signsecset
= NULL
;
5940 dns_rdata_t nsec
= DNS_RDATA_INIT
;
5941 dns_name_t
*nsecname
;
5942 dns_rdata_nsec_t nsecstruct
;
5944 if ((result
= dns_message_firstname(msg
, DNS_SECTION_AUTHORITY
))
5946 printf(";; nothing in authority section : impossible to"
5947 " validate the non-existence : FAILED\n");
5948 return (ISC_R_FAILURE
);
5953 dns_message_currentname(msg
, DNS_SECTION_AUTHORITY
, &nsecname
);
5954 nsecset
= search_type(nsecname
, dns_rdatatype_nsec
,
5956 if (nsecset
== NULL
)
5959 printf("There is a NSEC for this zone in the"
5960 " AUTHORITY section:\n");
5961 print_rdataset(nsecname
, nsecset
, mctx
);
5963 for (result
= dns_rdataset_first(nsecset
);
5964 result
== ISC_R_SUCCESS
;
5965 result
= dns_rdataset_next(nsecset
)) {
5966 dns_rdataset_current(nsecset
, &nsec
);
5969 = chase_scanname_section(msg
, nsecname
,
5970 dns_rdatatype_rrsig
,
5972 DNS_SECTION_AUTHORITY
);
5973 if (signsecset
== NULL
) {
5974 printf(";; no RRSIG NSEC in authority section:"
5975 " impossible to validate the "
5976 "non-existence: FAILED\n");
5977 return (ISC_R_FAILURE
);
5980 ret
= dns_rdata_tostruct(&nsec
, &nsecstruct
, NULL
);
5981 check_result(ret
,"dns_rdata_tostruct");
5983 if ((inf_name(nsecname
, &nsecstruct
.next
) == 1 &&
5984 inf_name(name
, &nsecstruct
.next
) == 1) ||
5985 (inf_name(name
, nsecname
) == 1 &&
5986 inf_name(&nsecstruct
.next
, name
) == 1)) {
5987 dns_rdata_freestruct(&nsecstruct
);
5988 *rdataset
= nsecset
;
5989 *sigrdataset
= signsecset
;
5990 dup_name(nsecname
, rdata_name
, mctx
);
5992 return (ISC_R_SUCCESS
);
5995 dns_rdata_freestruct(&nsecstruct
);
5996 dns_rdata_reset(&nsec
);
5998 } while (dns_message_nextname(msg
, DNS_SECTION_AUTHORITY
)
6002 *sigrdataset
= NULL
;
6004 return (ISC_R_FAILURE
);
6015 prove_nx_type(dns_message_t
*msg
, dns_name_t
*name
, dns_rdataset_t
*nsecset
,
6016 dns_rdataclass_t
class, dns_rdatatype_t type
,
6017 dns_name_t
*rdata_name
, dns_rdataset_t
**rdataset
,
6018 dns_rdataset_t
**sigrdataset
)
6021 dns_rdataset_t
*signsecset
;
6022 dns_rdata_t nsec
= DNS_RDATA_INIT
;
6026 ret
= dns_rdataset_first(nsecset
);
6027 check_result(ret
,"dns_rdataset_first");
6029 dns_rdataset_current(nsecset
, &nsec
);
6031 ret
= dns_nsec_typepresent(&nsec
, type
);
6032 if (ret
== ISC_R_SUCCESS
)
6033 printf("OK the NSEC said that the type doesn't exist \n");
6035 signsecset
= chase_scanname_section(msg
, name
,
6036 dns_rdatatype_rrsig
,
6038 DNS_SECTION_AUTHORITY
);
6039 if (signsecset
== NULL
) {
6040 printf("There isn't RRSIG NSEC for the zone \n");
6041 return (ISC_R_FAILURE
);
6043 dup_name(name
, rdata_name
, mctx
);
6044 *rdataset
= nsecset
;
6045 *sigrdataset
= signsecset
;
6057 prove_nx(dns_message_t
*msg
, dns_name_t
*name
, dns_rdataclass_t
class,
6058 dns_rdatatype_t type
, dns_name_t
*rdata_name
,
6059 dns_rdataset_t
**rdataset
, dns_rdataset_t
**sigrdataset
)
6062 dns_rdataset_t
*nsecset
= NULL
;
6064 printf("We want to prove the non-existence of a type of rdata %d"
6065 " or of the zone: \n", type
);
6067 if ((ret
= dns_message_firstname(msg
, DNS_SECTION_AUTHORITY
))
6069 printf(";; nothing in authority section : impossible to"
6070 " validate the non-existence : FAILED\n");
6071 return (ISC_R_FAILURE
);
6074 nsecset
= chase_scanname_section(msg
, name
, dns_rdatatype_nsec
,
6076 DNS_SECTION_AUTHORITY
);
6077 if (nsecset
!= NULL
) {
6078 printf("We have a NSEC for this zone :OK\n");
6079 ret
= prove_nx_type(msg
, name
, nsecset
, class,
6080 type
, rdata_name
, rdataset
,
6082 if (ret
!= ISC_R_SUCCESS
) {
6083 printf("prove_nx: ERROR type exist\n");
6086 printf("prove_nx: OK type does not exist\n");
6087 return (ISC_R_SUCCESS
);
6090 printf("there is no NSEC for this zone: validating "
6091 "that the zone doesn't exist\n");
6092 ret
= prove_nx_domain(msg
, name
, rdata_name
,
6093 rdataset
, sigrdataset
);
6096 /* Never get here */