Merge from vendor branch OPENSSL:
[dragonfly.git] / contrib / bind-9.3 / bin / dig / dighost.c
1 /*
2  * Copyright (C) 2004-2006  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2000-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id: dighost.c,v 1.221.2.19.2.36 2006/12/07 01:26:33 marka Exp $ */
19
20 /*
21  * Notice to programmers:  Do not use this code as an example of how to
22  * use the ISC library to perform DNS lookups.  Dig and Host both operate
23  * on the request level, since they allow fine-tuning of output and are
24  * intended as debugging tools.  As a result, they perform many of the
25  * functions which could be better handled using the dns_resolver
26  * functions in most applications.
27  */
28
29 #include <config.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <limits.h>
34
35 #include <dns/byaddr.h>
36 #ifdef DIG_SIGCHASE
37 #include <dns/dnssec.h>
38 #include <dns/ds.h>
39 #include <dns/nsec.h>
40 #include <isc/random.h>
41 #include <ctype.h>
42 #endif
43 #include <dns/fixedname.h>
44 #include <dns/message.h>
45 #include <dns/name.h>
46 #include <dns/rdata.h>
47 #include <dns/rdataclass.h>
48 #include <dns/rdatalist.h>
49 #include <dns/rdataset.h>
50 #include <dns/rdatastruct.h>
51 #include <dns/rdatatype.h>
52 #include <dns/result.h>
53 #include <dns/tsig.h>
54
55 #include <dst/dst.h>
56
57 #include <isc/app.h>
58 #include <isc/base64.h>
59 #include <isc/entropy.h>
60 #include <isc/file.h>
61 #include <isc/lang.h>
62 #include <isc/netaddr.h>
63 #ifdef DIG_SIGCHASE
64 #include <isc/netdb.h>
65 #endif
66 #include <isc/print.h>
67 #include <isc/random.h>
68 #include <isc/result.h>
69 #include <isc/string.h>
70 #include <isc/task.h>
71 #include <isc/timer.h>
72 #include <isc/types.h>
73 #include <isc/util.h>
74
75 #include <lwres/lwres.h>
76 #include <lwres/net.h>
77
78 #include <bind9/getaddresses.h>
79
80 #include <dig/dig.h>
81
82 #if ! defined(NS_INADDRSZ)
83 #define NS_INADDRSZ      4
84 #endif
85
86 #if ! defined(NS_IN6ADDRSZ)
87 #define NS_IN6ADDRSZ    16
88 #endif
89
90 static lwres_context_t *lwctx = NULL;
91 static lwres_conf_t *lwconf;
92
93 dig_lookuplist_t lookup_list;
94 dig_serverlist_t server_list;
95 dig_searchlistlist_t search_list;
96
97 isc_boolean_t
98         have_ipv4 = ISC_FALSE,
99         have_ipv6 = ISC_FALSE,
100         specified_source = ISC_FALSE,
101         free_now = ISC_FALSE,
102         cancel_now = ISC_FALSE,
103         usesearch = ISC_FALSE,
104         qr = ISC_FALSE,
105         is_dst_up = ISC_FALSE;
106 in_port_t port = 53;
107 unsigned int timeout = 0;
108 isc_mem_t *mctx = NULL;
109 isc_taskmgr_t *taskmgr = NULL;
110 isc_task_t *global_task = NULL;
111 isc_timermgr_t *timermgr = NULL;
112 isc_socketmgr_t *socketmgr = NULL;
113 isc_sockaddr_t bind_address;
114 isc_sockaddr_t bind_any;
115 int sendcount = 0;
116 int recvcount = 0;
117 int sockcount = 0;
118 int ndots = -1;
119 int tries = 3;
120 int lookup_counter = 0;
121
122 /*
123  * Exit Codes:
124  *   0   Everything went well, including things like NXDOMAIN
125  *   1   Usage error
126  *   7   Got too many RR's or Names
127  *   8   Couldn't open batch file
128  *   9   No reply from server
129  *   10  Internal error
130  */
131 int exitcode = 0;
132 int fatalexit = 0;
133 char keynametext[MXNAME];
134 char keyfile[MXNAME] = "";
135 char keysecret[MXNAME] = "";
136 isc_buffer_t *namebuf = NULL;
137 dns_tsigkey_t *key = NULL;
138 isc_boolean_t validated = ISC_TRUE;
139 isc_entropy_t *entp = NULL;
140 isc_mempool_t *commctx = NULL;
141 isc_boolean_t debugging = ISC_FALSE;
142 isc_boolean_t memdebugging = ISC_FALSE;
143 char *progname = NULL;
144 isc_mutex_t lookup_lock;
145 dig_lookup_t *current_lookup = NULL;
146
147 #ifdef DIG_SIGCHASE
148
149 isc_result_t      get_trusted_key(isc_mem_t *mctx);
150 dns_rdataset_t *  sigchase_scanname(dns_rdatatype_t type,
151                                     dns_rdatatype_t covers,
152                                     isc_boolean_t *lookedup,
153                                     dns_name_t *rdata_name);
154 dns_rdataset_t *  chase_scanname_section(dns_message_t *msg,
155                                          dns_name_t *name,
156                                          dns_rdatatype_t type,
157                                          dns_rdatatype_t covers,
158                                          int section);
159 isc_result_t      advanced_rrsearch(dns_rdataset_t **rdataset,
160                                     dns_name_t *name,
161                                     dns_rdatatype_t type,
162                                     dns_rdatatype_t covers,
163                                     isc_boolean_t *lookedup);
164 isc_result_t      sigchase_verify_sig_key(dns_name_t *name,
165                                           dns_rdataset_t *rdataset,
166                                           dst_key_t* dnsseckey,
167                                           dns_rdataset_t *sigrdataset,
168                                           isc_mem_t *mctx);
169 isc_result_t      sigchase_verify_sig(dns_name_t *name,
170                                       dns_rdataset_t *rdataset,
171                                       dns_rdataset_t *keyrdataset,
172                                       dns_rdataset_t *sigrdataset,
173                                       isc_mem_t *mctx);
174 isc_result_t      sigchase_verify_ds(dns_name_t *name,
175                                      dns_rdataset_t *keyrdataset,
176                                      dns_rdataset_t *dsrdataset,
177                                      isc_mem_t *mctx);
178 void              sigchase(dns_message_t *msg);
179 void              print_rdata(dns_rdata_t *rdata, isc_mem_t *mctx);
180 void              print_rdataset(dns_name_t *name,
181                                  dns_rdataset_t *rdataset, isc_mem_t *mctx);
182 void              dup_name(dns_name_t *source, dns_name_t* target,
183                            isc_mem_t *mctx);
184 void              free_name(dns_name_t *name, isc_mem_t *mctx);
185 void              dump_database(void);
186 void              dump_database_section(dns_message_t *msg, int section);
187 dns_rdataset_t *  search_type(dns_name_t *name, dns_rdatatype_t type,
188                               dns_rdatatype_t covers);
189 isc_result_t      contains_trusted_key(dns_name_t *name,
190                                        dns_rdataset_t *rdataset,
191                                        dns_rdataset_t *sigrdataset,
192                                        isc_mem_t *mctx);
193 void              print_type(dns_rdatatype_t type);
194 isc_result_t      prove_nx_domain(dns_message_t * msg,
195                                   dns_name_t * name,
196                                   dns_name_t * rdata_name,
197                                   dns_rdataset_t ** rdataset,
198                                   dns_rdataset_t ** sigrdataset);
199 isc_result_t      prove_nx_type(dns_message_t * msg, dns_name_t *name,
200                                 dns_rdataset_t *nsec,
201                                 dns_rdataclass_t class,
202                                 dns_rdatatype_t type,
203                                 dns_name_t * rdata_name,
204                                 dns_rdataset_t ** rdataset,
205                                 dns_rdataset_t ** sigrdataset);
206 isc_result_t      prove_nx(dns_message_t * msg, dns_name_t * name,
207                            dns_rdataclass_t class,
208                            dns_rdatatype_t type,
209                            dns_name_t * rdata_name,
210                            dns_rdataset_t ** rdataset,
211                            dns_rdataset_t ** sigrdataset);
212 static void       nameFromString(const char *str, dns_name_t *p_ret);
213 int               inf_name(dns_name_t * name1, dns_name_t * name2);
214 isc_result_t      opentmpkey(isc_mem_t *mctx, const char *file,
215                              char **tempp, FILE **fp);
216 isc_result_t      removetmpkey(isc_mem_t *mctx, const char *file);
217 void              clean_trustedkey(void);
218 void              insert_trustedkey(dst_key_t  * key);
219 #if DIG_SIGCHASE_BU
220 isc_result_t      getneededrr(dns_message_t *msg);
221 void              sigchase_bottom_up(dns_message_t *msg);
222 void              sigchase_bu(dns_message_t *msg);
223 #endif
224 #if DIG_SIGCHASE_TD
225 isc_result_t      initialization(dns_name_t *name);
226 isc_result_t      prepare_lookup(dns_name_t *name);
227 isc_result_t      grandfather_pb_test(dns_name_t * zone_name,
228                                       dns_rdataset_t *sigrdataset);
229 isc_result_t      child_of_zone(dns_name_t *name,
230                                 dns_name_t *zone_name,
231                                 dns_name_t *child_name);
232 void              sigchase_td(dns_message_t *msg);
233 #endif
234 char trustedkey[MXNAME] = "";
235
236 dns_rdataset_t *chase_rdataset = NULL;
237 dns_rdataset_t *chase_sigrdataset = NULL;
238 dns_rdataset_t *chase_dsrdataset = NULL;
239 dns_rdataset_t *chase_sigdsrdataset = NULL;
240 dns_rdataset_t *chase_keyrdataset = NULL;
241 dns_rdataset_t *chase_sigkeyrdataset = NULL;
242 dns_rdataset_t *chase_nsrdataset = NULL;
243
244 dns_name_t chase_name; /* the query name */
245 #if DIG_SIGCHASE_TD
246 /*
247  * the current name is the parent name when we follow delegation
248  */
249 dns_name_t chase_current_name;
250 /*
251  * the child name is used for delegation (NS DS responses in AUTHORITY section)
252  */
253 dns_name_t chase_authority_name;
254 #endif
255 #if DIG_SIGCHASE_BU
256 dns_name_t chase_signame;
257 #endif
258
259
260 isc_boolean_t chase_siglookedup = ISC_FALSE;
261 isc_boolean_t chase_keylookedup = ISC_FALSE;
262 isc_boolean_t chase_sigkeylookedup = ISC_FALSE;
263 isc_boolean_t chase_dslookedup = ISC_FALSE;
264 isc_boolean_t chase_sigdslookedup = ISC_FALSE;
265 #if DIG_SIGCHASE_TD
266 isc_boolean_t chase_nslookedup = ISC_FALSE;
267 isc_boolean_t chase_lookedup = ISC_FALSE;
268
269
270 isc_boolean_t delegation_follow = ISC_FALSE;
271 isc_boolean_t grandfather_pb = ISC_FALSE;
272 isc_boolean_t have_response = ISC_FALSE;
273 isc_boolean_t have_delegation_ns = ISC_FALSE;
274 dns_message_t * error_message = NULL;
275 #endif
276
277 isc_boolean_t dsvalidating = ISC_FALSE;
278 isc_boolean_t chase_name_dup = ISC_FALSE;
279
280 ISC_LIST(dig_message_t) chase_message_list;
281 ISC_LIST(dig_message_t) chase_message_list2;
282
283
284 #define MAX_TRUSTED_KEY 5
285 typedef struct struct_trusted_key_list {
286         dst_key_t * key[MAX_TRUSTED_KEY];
287         int nb_tk;
288 } struct_tk_list;
289
290 struct_tk_list tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0};
291
292 #endif
293
294 #define DIG_MAX_ADDRESSES 20
295
296 /*
297  * Apply and clear locks at the event level in global task.
298  * Can I get rid of these using shutdown events?  XXX
299  */
300 #define LOCK_LOOKUP {\
301         debug("lock_lookup %s:%d", __FILE__, __LINE__);\
302         check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\
303         debug("success");\
304 }
305 #define UNLOCK_LOOKUP {\
306         debug("unlock_lookup %s:%d", __FILE__, __LINE__);\
307         check_result(isc_mutex_unlock((&lookup_lock)),\
308                      "isc_mutex_unlock");\
309 }
310
311 static void
312 cancel_lookup(dig_lookup_t *lookup);
313
314 static void
315 recv_done(isc_task_t *task, isc_event_t *event);
316
317 static void
318 send_udp(dig_query_t *query);
319
320 static void
321 connect_timeout(isc_task_t *task, isc_event_t *event);
322
323 static void
324 launch_next_query(dig_query_t *query, isc_boolean_t include_question);
325
326
327 static void *
328 mem_alloc(void *arg, size_t size) {
329         return (isc_mem_get(arg, size));
330 }
331
332 static void
333 mem_free(void *arg, void *mem, size_t size) {
334         isc_mem_put(arg, mem, size);
335 }
336
337 char *
338 next_token(char **stringp, const char *delim) {
339         char *res;
340
341         do {
342                 res = strsep(stringp, delim);
343                 if (res == NULL)
344                         break;
345         } while (*res == '\0');
346         return (res);
347 }
348
349 static int
350 count_dots(char *string) {
351         char *s;
352         int i = 0;
353
354         s = string;
355         while (*s != '\0') {
356                 if (*s == '.')
357                         i++;
358                 s++;
359         }
360         return (i);
361 }
362
363 static void
364 hex_dump(isc_buffer_t *b) {
365         unsigned int len;
366         isc_region_t r;
367
368         isc_buffer_usedregion(b, &r);
369
370         printf("%d bytes\n", r.length);
371         for (len = 0; len < r.length; len++) {
372                 printf("%02x ", r.base[len]);
373                 if (len % 16 == 15)
374                         printf("\n");
375         }
376         if (len % 16 != 0)
377                 printf("\n");
378 }
379
380 /*
381  * Append 'len' bytes of 'text' at '*p', failing with
382  * ISC_R_NOSPACE if that would advance p past 'end'.
383  */
384 static isc_result_t
385 append(const char *text, int len, char **p, char *end) {
386         if (len > end - *p)
387                 return (ISC_R_NOSPACE);
388         memcpy(*p, text, len);
389         *p += len;
390         return (ISC_R_SUCCESS);
391 }
392
393 static isc_result_t
394 reverse_octets(const char *in, char **p, char *end) {
395         char *dot = strchr(in, '.');
396         int len;
397         if (dot != NULL) {
398                 isc_result_t result;
399                 result = reverse_octets(dot + 1, p, end);
400                 if (result != ISC_R_SUCCESS)
401                         return (result);
402                 result = append(".", 1, p, end);
403                 if (result != ISC_R_SUCCESS)
404                         return (result);
405                 len = dot - in;
406         } else {
407                 len = strlen(in);
408         }
409         return (append(in, len, p, end));
410 }
411
412 isc_result_t
413 get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int,
414             isc_boolean_t strict)
415 {
416         int r;
417         isc_result_t result;
418         isc_netaddr_t addr;
419
420         addr.family = AF_INET6;
421         r = inet_pton(AF_INET6, value, &addr.type.in6);
422         if (r > 0) {
423                 /* This is a valid IPv6 address. */
424                 dns_fixedname_t fname;
425                 dns_name_t *name;
426                 unsigned int options = 0;
427
428                 if (ip6_int)
429                         options |= DNS_BYADDROPT_IPV6INT;
430                 dns_fixedname_init(&fname);
431                 name = dns_fixedname_name(&fname);
432                 result = dns_byaddr_createptrname2(&addr, options, name);
433                 if (result != ISC_R_SUCCESS)
434                         return (result);
435                 dns_name_format(name, reverse, len);
436                 return (ISC_R_SUCCESS);
437         } else {
438                 /*
439                  * Not a valid IPv6 address.  Assume IPv4.
440                  * If 'strict' is not set, construct the
441                  * in-addr.arpa name by blindly reversing
442                  * octets whether or not they look like integers,
443                  * so that this can be used for RFC2317 names
444                  * and such.
445                  */
446                 char *p = reverse;
447                 char *end = reverse + len;
448                 if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1)
449                         return (DNS_R_BADDOTTEDQUAD);
450                 result = reverse_octets(value, &p, end);
451                 if (result != ISC_R_SUCCESS)
452                         return (result);
453                 /* Append .in-addr.arpa. and a terminating NUL. */
454                 result = append(".in-addr.arpa.", 15, &p, end);
455                 if (result != ISC_R_SUCCESS)
456                         return (result);
457                 return (ISC_R_SUCCESS);
458         }
459 }
460
461 void
462 fatal(const char *format, ...) {
463         va_list args;
464
465         fprintf(stderr, "%s: ", progname);
466         va_start(args, format);
467         vfprintf(stderr, format, args);
468         va_end(args);
469         fprintf(stderr, "\n");
470         if (exitcode < 10)
471                 exitcode = 10;
472         if (fatalexit != 0)
473                 exitcode = fatalexit;
474         exit(exitcode);
475 }
476
477 void
478 debug(const char *format, ...) {
479         va_list args;
480
481         if (debugging) {
482                 va_start(args, format);
483                 vfprintf(stderr, format, args);
484                 va_end(args);
485                 fprintf(stderr, "\n");
486         }
487 }
488
489 void
490 check_result(isc_result_t result, const char *msg) {
491         if (result != ISC_R_SUCCESS) {
492                 fatal("%s: %s", msg, isc_result_totext(result));
493         }
494 }
495
496 /*
497  * Create a server structure, which is part of the lookup structure.
498  * This is little more than a linked list of servers to query in hopes
499  * of finding the answer the user is looking for
500  */
501 dig_server_t *
502 make_server(const char *servname, const char *userarg) {
503         dig_server_t *srv;
504
505         REQUIRE(servname != NULL);
506
507         debug("make_server(%s)", servname);
508         srv = isc_mem_allocate(mctx, sizeof(struct dig_server));
509         if (srv == NULL)
510                 fatal("memory allocation failure in %s:%d",
511                       __FILE__, __LINE__);
512         strncpy(srv->servername, servname, MXNAME);
513         strncpy(srv->userarg, userarg, MXNAME);
514         srv->servername[MXNAME-1] = 0;
515         srv->userarg[MXNAME-1] = 0;
516         ISC_LINK_INIT(srv, link);
517         return (srv);
518 }
519
520 static int
521 addr2af(int lwresaddrtype)
522 {
523         int af = 0;
524
525         switch (lwresaddrtype) {
526         case LWRES_ADDRTYPE_V4:
527                 af = AF_INET;
528                 break;
529
530         case LWRES_ADDRTYPE_V6:
531                 af = AF_INET6;
532                 break;
533         }
534
535         return (af);
536 }
537
538 /*
539  * Create a copy of the server list from the lwres configuration structure.
540  * The dest list must have already had ISC_LIST_INIT applied.
541  */
542 static void
543 copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) {
544         dig_server_t *newsrv;
545         char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
546         int af;
547         int i;
548
549         debug("copy_server_list()");
550         for (i = 0; i < confdata->nsnext; i++) {
551                 af = addr2af(confdata->nameservers[i].family);
552
553                 lwres_net_ntop(af, confdata->nameservers[i].address,
554                                    tmp, sizeof(tmp));
555                 newsrv = make_server(tmp, tmp);
556                 ISC_LINK_INIT(newsrv, link);
557                 ISC_LIST_ENQUEUE(*dest, newsrv, link);
558         }
559 }
560
561 void
562 flush_server_list(void) {
563         dig_server_t *s, *ps;
564
565         debug("flush_server_list()");
566         s = ISC_LIST_HEAD(server_list);
567         while (s != NULL) {
568                 ps = s;
569                 s = ISC_LIST_NEXT(s, link);
570                 ISC_LIST_DEQUEUE(server_list, ps, link);
571                 isc_mem_free(mctx, ps);
572         }
573 }
574
575 void
576 set_nameserver(char *opt) {
577         isc_result_t result;
578         isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
579         isc_netaddr_t netaddr;
580         int count, i;
581         dig_server_t *srv;
582         char tmp[ISC_NETADDR_FORMATSIZE];
583
584         if (opt == NULL)
585                 return;
586
587         result = bind9_getaddresses(opt, 0, sockaddrs,
588                                     DIG_MAX_ADDRESSES, &count);
589         if (result != ISC_R_SUCCESS)
590                 fatal("couldn't get address for '%s': %s",
591                       opt, isc_result_totext(result));
592
593         flush_server_list();
594         
595         for (i = 0; i < count; i++) {
596                 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
597                 isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
598                 srv = make_server(tmp, opt);
599                 if (srv == NULL)
600                         fatal("memory allocation failure");
601                 ISC_LIST_APPEND(server_list, srv, link);
602         }
603 }
604
605 static isc_result_t
606 add_nameserver(lwres_conf_t *confdata, const char *addr, int af) {
607
608         int i = confdata->nsnext;
609
610         if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS)
611                 return (ISC_R_FAILURE);
612
613         switch (af) {
614         case AF_INET:
615                 confdata->nameservers[i].family = LWRES_ADDRTYPE_V4;
616                 confdata->nameservers[i].length = NS_INADDRSZ;
617                 break;
618         case AF_INET6:
619                 confdata->nameservers[i].family = LWRES_ADDRTYPE_V6;
620                 confdata->nameservers[i].length = NS_IN6ADDRSZ;
621                 break;
622         default:
623                 return (ISC_R_FAILURE);
624         }
625
626         if (lwres_net_pton(af, addr, &confdata->nameservers[i].address) == 1) {
627                 confdata->nsnext++;
628                 return (ISC_R_SUCCESS);
629         }
630         return (ISC_R_FAILURE);
631 }
632
633 /*
634  * Produce a cloned server list.  The dest list must have already had
635  * ISC_LIST_INIT applied.
636  */
637 void
638 clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
639         dig_server_t *srv, *newsrv;
640
641         debug("clone_server_list()");
642         srv = ISC_LIST_HEAD(src);
643         while (srv != NULL) {
644                 newsrv = make_server(srv->servername, srv->userarg);
645                 ISC_LINK_INIT(newsrv, link);
646                 ISC_LIST_ENQUEUE(*dest, newsrv, link);
647                 srv = ISC_LIST_NEXT(srv, link);
648         }
649 }
650
651 /*
652  * Create an empty lookup structure, which holds all the information needed
653  * to get an answer to a user's question.  This structure contains two
654  * linked lists: the server list (servers to query) and the query list
655  * (outstanding queries which have been made to the listed servers).
656  */
657 dig_lookup_t *
658 make_empty_lookup(void) {
659         dig_lookup_t *looknew;
660
661         debug("make_empty_lookup()");
662
663         INSIST(!free_now);
664
665         looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
666         if (looknew == NULL)
667                 fatal("memory allocation failure in %s:%d",
668                        __FILE__, __LINE__);
669         looknew->pending = ISC_TRUE;
670         looknew->textname[0] = 0;
671         looknew->cmdline[0] = 0;
672         looknew->rdtype = dns_rdatatype_a;
673         looknew->qrdtype = dns_rdatatype_a;
674         looknew->rdclass = dns_rdataclass_in;
675         looknew->rdtypeset = ISC_FALSE;
676         looknew->rdclassset = ISC_FALSE;
677         looknew->sendspace = NULL;
678         looknew->sendmsg = NULL;
679         looknew->name = NULL;
680         looknew->oname = NULL;
681         looknew->timer = NULL;
682         looknew->xfr_q = NULL;
683         looknew->current_query = NULL;
684         looknew->doing_xfr = ISC_FALSE;
685         looknew->ixfr_serial = ISC_FALSE;
686         looknew->trace = ISC_FALSE;
687         looknew->trace_root = ISC_FALSE;
688         looknew->identify = ISC_FALSE;
689         looknew->identify_previous_line = ISC_FALSE;
690         looknew->ignore = ISC_FALSE;
691         looknew->servfail_stops = ISC_TRUE;
692         looknew->besteffort = ISC_TRUE;
693         looknew->dnssec = ISC_FALSE;
694 #ifdef DIG_SIGCHASE
695         looknew->sigchase = ISC_FALSE;
696 #if DIG_SIGCHASE_TD
697         looknew->do_topdown = ISC_FALSE;
698         looknew->trace_root_sigchase = ISC_FALSE;
699         looknew->rdtype_sigchaseset = ISC_FALSE;
700         looknew->rdtype_sigchase = dns_rdatatype_any;
701         looknew->qrdtype_sigchase = dns_rdatatype_any;
702         looknew->rdclass_sigchase = dns_rdataclass_in;
703         looknew->rdclass_sigchaseset = ISC_FALSE;
704 #endif
705 #endif
706         looknew->udpsize = 0;
707         looknew->recurse = ISC_TRUE;
708         looknew->aaonly = ISC_FALSE;
709         looknew->adflag = ISC_FALSE;
710         looknew->cdflag = ISC_FALSE;
711         looknew->ns_search_only = ISC_FALSE;
712         looknew->origin = NULL;
713         looknew->tsigctx = NULL;
714         looknew->querysig = NULL;
715         looknew->retries = tries;
716         looknew->nsfound = 0;
717         looknew->tcp_mode = ISC_FALSE;
718         looknew->ip6_int = ISC_FALSE;
719         looknew->comments = ISC_TRUE;
720         looknew->stats = ISC_TRUE;
721         looknew->section_question = ISC_TRUE;
722         looknew->section_answer = ISC_TRUE;
723         looknew->section_authority = ISC_TRUE;
724         looknew->section_additional = ISC_TRUE;
725         looknew->new_search = ISC_FALSE;
726         ISC_LINK_INIT(looknew, link);
727         ISC_LIST_INIT(looknew->q);
728         ISC_LIST_INIT(looknew->my_server_list);
729         return (looknew);
730 }
731
732 /*
733  * Clone a lookup, perhaps copying the server list.  This does not clone
734  * the query list, since it will be regenerated by the setup_lookup()
735  * function, nor does it queue up the new lookup for processing.
736  * Caution: If you don't clone the servers, you MUST clone the server
737  * list seperately from somewhere else, or construct it by hand.
738  */
739 dig_lookup_t *
740 clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
741         dig_lookup_t *looknew;
742
743         debug("clone_lookup()");
744
745         INSIST(!free_now);
746
747         looknew = make_empty_lookup();
748         INSIST(looknew != NULL);
749         strncpy(looknew->textname, lookold->textname, MXNAME);
750 #if DIG_SIGCHASE_TD
751         strncpy(looknew->textnamesigchase, lookold->textnamesigchase, MXNAME);
752 #endif
753         strncpy(looknew->cmdline, lookold->cmdline, MXNAME);
754         looknew->textname[MXNAME-1] = 0;
755         looknew->rdtype = lookold->rdtype;
756         looknew->qrdtype = lookold->qrdtype;
757         looknew->rdclass = lookold->rdclass;
758         looknew->rdtypeset = lookold->rdtypeset;
759         looknew->rdclassset = lookold->rdclassset;
760         looknew->doing_xfr = lookold->doing_xfr;
761         looknew->ixfr_serial = lookold->ixfr_serial;
762         looknew->trace = lookold->trace;
763         looknew->trace_root = lookold->trace_root;
764         looknew->identify = lookold->identify;
765         looknew->identify_previous_line = lookold->identify_previous_line;
766         looknew->ignore = lookold->ignore;
767         looknew->servfail_stops = lookold->servfail_stops;
768         looknew->besteffort = lookold->besteffort;
769         looknew->dnssec = lookold->dnssec;
770 #ifdef DIG_SIGCHASE
771         looknew->sigchase = lookold->sigchase;
772 #if DIG_SIGCHASE_TD
773         looknew->do_topdown = lookold->do_topdown;
774         looknew->trace_root_sigchase = lookold->trace_root_sigchase;
775         looknew->rdtype_sigchaseset = lookold->rdtype_sigchaseset;
776         looknew->rdtype_sigchase = lookold->rdtype_sigchase;
777         looknew->qrdtype_sigchase = lookold->qrdtype_sigchase;
778         looknew->rdclass_sigchase = lookold->rdclass_sigchase;
779         looknew->rdclass_sigchaseset = lookold->rdclass_sigchaseset;
780 #endif
781 #endif
782         looknew->udpsize = lookold->udpsize;
783         looknew->recurse = lookold->recurse;
784         looknew->aaonly = lookold->aaonly;
785         looknew->adflag = lookold->adflag;
786         looknew->cdflag = lookold->cdflag;
787         looknew->ns_search_only = lookold->ns_search_only;
788         looknew->tcp_mode = lookold->tcp_mode;
789         looknew->comments = lookold->comments;
790         looknew->stats = lookold->stats;
791         looknew->section_question = lookold->section_question;
792         looknew->section_answer = lookold->section_answer;
793         looknew->section_authority = lookold->section_authority;
794         looknew->section_additional = lookold->section_additional;
795         looknew->retries = lookold->retries;
796         looknew->tsigctx = NULL;
797
798         if (servers)
799                 clone_server_list(lookold->my_server_list,
800                                   &looknew->my_server_list);
801         return (looknew);
802 }
803
804 /*
805  * Requeue a lookup for further processing, perhaps copying the server
806  * list.  The new lookup structure is returned to the caller, and is
807  * queued for processing.  If servers are not cloned in the requeue, they
808  * must be added before allowing the current event to complete, since the
809  * completion of the event may result in the next entry on the lookup
810  * queue getting run.
811  */
812 dig_lookup_t *
813 requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
814         dig_lookup_t *looknew;
815
816         debug("requeue_lookup()");
817
818         lookup_counter++;
819         if (lookup_counter > LOOKUP_LIMIT)
820                 fatal("too many lookups");
821
822         looknew = clone_lookup(lookold, servers);
823         INSIST(looknew != NULL);
824
825         debug("before insertion, init@%p -> %p, new@%p -> %p",
826               lookold, lookold->link.next, looknew, looknew->link.next);
827         ISC_LIST_PREPEND(lookup_list, looknew, link);
828         debug("after insertion, init -> %p, new = %p, new -> %p",
829               lookold, looknew, looknew->link.next);
830         return (looknew);
831 }
832
833
834 static void
835 setup_text_key(void) {
836         isc_result_t result;
837         dns_name_t keyname;
838         isc_buffer_t secretbuf;
839         int secretsize;
840         unsigned char *secretstore;
841
842         debug("setup_text_key()");
843         result = isc_buffer_allocate(mctx, &namebuf, MXNAME);
844         check_result(result, "isc_buffer_allocate");
845         dns_name_init(&keyname, NULL);
846         check_result(result, "dns_name_init");
847         isc_buffer_putstr(namebuf, keynametext);
848         secretsize = strlen(keysecret) * 3 / 4;
849         secretstore = isc_mem_allocate(mctx, secretsize);
850         if (secretstore == NULL)
851                 fatal("memory allocation failure in %s:%d",
852                       __FILE__, __LINE__);
853         isc_buffer_init(&secretbuf, secretstore, secretsize);
854         result = isc_base64_decodestring(keysecret, &secretbuf);
855         if (result != ISC_R_SUCCESS)
856                 goto failure;
857         
858         secretsize = isc_buffer_usedlength(&secretbuf);
859
860         result = dns_name_fromtext(&keyname, namebuf,
861                                    dns_rootname, ISC_FALSE,
862                                    namebuf);
863         if (result != ISC_R_SUCCESS)
864                 goto failure;
865
866         result = dns_tsigkey_create(&keyname, dns_tsig_hmacmd5_name,
867                                     secretstore, secretsize,
868                                     ISC_FALSE, NULL, 0, 0, mctx,
869                                     NULL, &key);
870  failure:
871         if (result != ISC_R_SUCCESS)
872                 printf(";; Couldn't create key %s: %s\n",
873                        keynametext, isc_result_totext(result));
874
875         isc_mem_free(mctx, secretstore);
876         dns_name_invalidate(&keyname);
877         isc_buffer_free(&namebuf);
878 }
879
880 static void
881 setup_file_key(void) {
882         isc_result_t result;
883         dst_key_t *dstkey = NULL;
884
885         debug("setup_file_key()");
886         result = dst_key_fromnamedfile(keyfile, DST_TYPE_PRIVATE | DST_TYPE_KEY,
887                                        mctx, &dstkey);
888         if (result != ISC_R_SUCCESS) {
889                 fprintf(stderr, "Couldn't read key from %s: %s\n",
890                         keyfile, isc_result_totext(result));
891                 goto failure;
892         }
893
894         result = dns_tsigkey_createfromkey(dst_key_name(dstkey),
895                                            dns_tsig_hmacmd5_name,
896                                            dstkey, ISC_FALSE, NULL, 0, 0,
897                                            mctx, NULL, &key);
898         if (result != ISC_R_SUCCESS) {
899                 printf(";; Couldn't create key %s: %s\n",
900                        keynametext, isc_result_totext(result));
901                 goto failure;
902         }
903         dstkey = NULL;
904  failure:
905         if (dstkey != NULL)
906                 dst_key_free(&dstkey);
907 }
908
909 static dig_searchlist_t *
910 make_searchlist_entry(char *domain) {
911         dig_searchlist_t *search;
912         search = isc_mem_allocate(mctx, sizeof(*search));
913         if (search == NULL)
914                 fatal("memory allocation failure in %s:%d",
915                       __FILE__, __LINE__);
916         strncpy(search->origin, domain, MXNAME);
917         search->origin[MXNAME-1] = 0;
918         ISC_LINK_INIT(search, link);
919         return (search);
920 }
921
922 static void
923 create_search_list(lwres_conf_t *confdata) {
924         int i;
925         dig_searchlist_t *search;
926
927         debug("create_search_list()");
928         ISC_LIST_INIT(search_list);
929
930         for (i = 0; i < confdata->searchnxt; i++) {
931                 search = make_searchlist_entry(confdata->search[i]);
932                 ISC_LIST_APPEND(search_list, search, link);
933         }
934 }
935
936 /*
937  * Setup the system as a whole, reading key information and resolv.conf
938  * settings.
939  */
940 void
941 setup_system(void) {
942         dig_searchlist_t *domain = NULL;
943         lwres_result_t lwresult;
944
945         debug("setup_system()");
946
947         lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1);
948         if (lwresult != LWRES_R_SUCCESS)
949                 fatal("lwres_context_create failed");
950
951         lwresult = lwres_conf_parse(lwctx, RESOLV_CONF);
952         if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND)
953                 fatal("parse of %s failed", RESOLV_CONF);
954
955         lwconf = lwres_conf_get(lwctx);
956
957         /* Make the search list */
958         if (lwconf->searchnxt > 0)
959                 create_search_list(lwconf);
960         else { /* No search list. Use the domain name if any */
961                 if (lwconf->domainname != NULL) {
962                         domain = make_searchlist_entry(lwconf->domainname);
963                         ISC_LIST_INITANDAPPEND(search_list, domain, link);
964                         domain  = NULL;
965                 }
966         }
967                         
968         if (ndots == -1) {
969                 ndots = lwconf->ndots;
970                 debug("ndots is %d.", ndots);
971         }
972
973         /* If we don't find a nameserver fall back to localhost */
974         if (lwconf->nsnext == 0) {
975                 if (have_ipv4) {
976                         lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET);
977                         if (lwresult != ISC_R_SUCCESS)
978                                 fatal("add_nameserver failed");
979                 }
980                 if (have_ipv6) {
981                         lwresult = add_nameserver(lwconf, "::1", AF_INET6);
982                         if (lwresult != ISC_R_SUCCESS)
983                                 fatal("add_nameserver failed");
984                 }
985         }
986
987         if (ISC_LIST_EMPTY(server_list))
988                 copy_server_list(lwconf, &server_list);
989
990         if (keyfile[0] != 0)
991                 setup_file_key();
992         else if (keysecret[0] != 0)
993                 setup_text_key();
994 #ifdef DIG_SIGCHASE
995         /* Setup the list of messages for +sigchase */
996         ISC_LIST_INIT(chase_message_list);
997         ISC_LIST_INIT(chase_message_list2);
998         dns_name_init(&chase_name, NULL);
999 #if DIG_SIGCHASE_TD
1000         dns_name_init(&chase_current_name, NULL);
1001         dns_name_init(&chase_authority_name, NULL);
1002 #endif
1003 #if DIG_SIGCHASE_BU
1004         dns_name_init(&chase_signame, NULL);
1005 #endif
1006
1007 #endif
1008
1009 }
1010
1011 static void
1012 clear_searchlist(void) {
1013         dig_searchlist_t *search;
1014         while ((search = ISC_LIST_HEAD(search_list)) != NULL) {
1015                 ISC_LIST_UNLINK(search_list, search, link);
1016                 isc_mem_free(mctx, search);
1017         }
1018 }
1019
1020 /*
1021  * Override the search list derived from resolv.conf by 'domain'.
1022  */
1023 void
1024 set_search_domain(char *domain) {
1025         dig_searchlist_t *search;
1026         
1027         clear_searchlist();
1028         search = make_searchlist_entry(domain);
1029         ISC_LIST_APPEND(search_list, search, link);
1030 }
1031
1032 /*
1033  * Setup the ISC and DNS libraries for use by the system.
1034  */
1035 void
1036 setup_libs(void) {
1037         isc_result_t result;
1038
1039         debug("setup_libs()");
1040
1041         result = isc_net_probeipv4();
1042         if (result == ISC_R_SUCCESS)
1043                 have_ipv4 = ISC_TRUE;
1044
1045         result = isc_net_probeipv6();
1046         if (result == ISC_R_SUCCESS)
1047                 have_ipv6 = ISC_TRUE;
1048         if (!have_ipv6 && !have_ipv4)
1049                 fatal("can't find either v4 or v6 networking");
1050
1051         result = isc_mem_create(0, 0, &mctx);
1052         check_result(result, "isc_mem_create");
1053
1054         result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
1055         check_result(result, "isc_taskmgr_create");
1056
1057         result = isc_task_create(taskmgr, 0, &global_task);
1058         check_result(result, "isc_task_create");
1059
1060         result = isc_timermgr_create(mctx, &timermgr);
1061         check_result(result, "isc_timermgr_create");
1062
1063         result = isc_socketmgr_create(mctx, &socketmgr);
1064         check_result(result, "isc_socketmgr_create");
1065
1066         result = isc_entropy_create(mctx, &entp);
1067         check_result(result, "isc_entropy_create");
1068
1069         result = dst_lib_init(mctx, entp, 0);
1070         check_result(result, "dst_lib_init");
1071         is_dst_up = ISC_TRUE;
1072
1073         result = isc_mempool_create(mctx, COMMSIZE, &commctx);
1074         check_result(result, "isc_mempool_create");
1075         isc_mempool_setname(commctx, "COMMPOOL");
1076         /*
1077          * 6 and 2 set as reasonable parameters for 3 or 4 nameserver
1078          * systems.
1079          */
1080         isc_mempool_setfreemax(commctx, 6);
1081         isc_mempool_setfillcount(commctx, 2);
1082
1083         result = isc_mutex_init(&lookup_lock);
1084         check_result(result, "isc_mutex_init");
1085
1086         dns_result_register();
1087 }
1088
1089 /*
1090  * Add EDNS0 option record to a message.  Currently, the only supported
1091  * options are UDP buffer size and the DO bit.
1092  */
1093 static void
1094 add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_boolean_t dnssec) {
1095         dns_rdataset_t *rdataset = NULL;
1096         dns_rdatalist_t *rdatalist = NULL;
1097         dns_rdata_t *rdata = NULL;
1098         isc_result_t result;
1099
1100         debug("add_opt()");
1101         result = dns_message_gettemprdataset(msg, &rdataset);
1102         check_result(result, "dns_message_gettemprdataset");
1103         dns_rdataset_init(rdataset);
1104         result = dns_message_gettemprdatalist(msg, &rdatalist);
1105         check_result(result, "dns_message_gettemprdatalist");
1106         result = dns_message_gettemprdata(msg, &rdata);
1107         check_result(result, "dns_message_gettemprdata");
1108
1109         debug("setting udp size of %d", udpsize);
1110         rdatalist->type = dns_rdatatype_opt;
1111         rdatalist->covers = 0;
1112         rdatalist->rdclass = udpsize;
1113         rdatalist->ttl = 0;
1114         if (dnssec)
1115                 rdatalist->ttl = DNS_MESSAGEEXTFLAG_DO;
1116         rdata->data = NULL;
1117         rdata->length = 0;
1118         ISC_LIST_INIT(rdatalist->rdata);
1119         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1120         dns_rdatalist_tordataset(rdatalist, rdataset);
1121         result = dns_message_setopt(msg, rdataset);
1122         check_result(result, "dns_message_setopt");
1123 }
1124
1125 /*
1126  * Add a question section to a message, asking for the specified name,
1127  * type, and class.
1128  */
1129 static void
1130 add_question(dns_message_t *message, dns_name_t *name,
1131              dns_rdataclass_t rdclass, dns_rdatatype_t rdtype)
1132 {
1133         dns_rdataset_t *rdataset;
1134         isc_result_t result;
1135
1136         debug("add_question()");
1137         rdataset = NULL;
1138         result = dns_message_gettemprdataset(message, &rdataset);
1139         check_result(result, "dns_message_gettemprdataset()");
1140         dns_rdataset_init(rdataset);
1141         dns_rdataset_makequestion(rdataset, rdclass, rdtype);
1142         ISC_LIST_APPEND(name->list, rdataset, link);
1143 }
1144
1145 /*
1146  * Check if we're done with all the queued lookups, which is true iff
1147  * all sockets, sends, and recvs are accounted for (counters == 0),
1148  * and the lookup list is empty.
1149  * If we are done, pass control back out to dighost_shutdown() (which is
1150  * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
1151  * a whole or reseed the lookup list.
1152  */
1153 static void
1154 check_if_done(void) {
1155         debug("check_if_done()");
1156         debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
1157         if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
1158             sendcount == 0) {
1159                 INSIST(sockcount == 0);
1160                 INSIST(recvcount == 0);
1161                 debug("shutting down");
1162                 dighost_shutdown();
1163         }
1164 }
1165
1166 /*
1167  * Clear out a query when we're done with it.  WARNING: This routine
1168  * WILL invalidate the query pointer.
1169  */
1170 static void
1171 clear_query(dig_query_t *query) {
1172         dig_lookup_t *lookup;
1173
1174         REQUIRE(query != NULL);
1175
1176         debug("clear_query(%p)", query);
1177
1178         lookup = query->lookup;
1179
1180         if (lookup->current_query == query)
1181                 lookup->current_query = NULL;
1182
1183         ISC_LIST_UNLINK(lookup->q, query, link);
1184         if (ISC_LINK_LINKED(&query->recvbuf, link))
1185                 ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf,
1186                                  link);
1187         if (ISC_LINK_LINKED(&query->lengthbuf, link))
1188                 ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf,
1189                                  link);
1190         INSIST(query->recvspace != NULL);
1191         if (query->sock != NULL) {
1192                 isc_socket_detach(&query->sock);
1193                 sockcount--;
1194                 debug("sockcount=%d", sockcount);
1195         }
1196         isc_mempool_put(commctx, query->recvspace);
1197         isc_buffer_invalidate(&query->recvbuf);
1198         isc_buffer_invalidate(&query->lengthbuf);
1199         if (query->waiting_senddone)
1200                 query->pending_free = ISC_TRUE;
1201         else
1202                 isc_mem_free(mctx, query);
1203 }
1204
1205 /*
1206  * Try and clear out a lookup if we're done with it.  Return ISC_TRUE if
1207  * the lookup was successfully cleared.  If ISC_TRUE is returned, the
1208  * lookup pointer has been invalidated.
1209  */
1210 static isc_boolean_t
1211 try_clear_lookup(dig_lookup_t *lookup) {
1212         dig_server_t *s;
1213         dig_query_t *q;
1214         void *ptr;
1215
1216         REQUIRE(lookup != NULL);
1217
1218         debug("try_clear_lookup(%p)", lookup);
1219
1220         if (ISC_LIST_HEAD(lookup->q) != NULL) {
1221                 if (debugging) {
1222                         q = ISC_LIST_HEAD(lookup->q);
1223                         while (q != NULL) {
1224                                 debug("query to %s still pending", q->servname);
1225                                 q = ISC_LIST_NEXT(q, link);
1226                         }
1227                 }
1228                 return (ISC_FALSE);
1229         }
1230
1231         /*
1232          * At this point, we know there are no queries on the lookup,
1233          * so can make it go away also.
1234          */
1235         debug("cleared");
1236         s = ISC_LIST_HEAD(lookup->my_server_list);
1237         while (s != NULL) {
1238                 debug("freeing server %p belonging to %p", s, lookup);
1239                 ptr = s;
1240                 s = ISC_LIST_NEXT(s, link);
1241                 ISC_LIST_DEQUEUE(lookup->my_server_list,
1242                                  (dig_server_t *)ptr, link);
1243                 isc_mem_free(mctx, ptr);
1244         }
1245         if (lookup->sendmsg != NULL)
1246                 dns_message_destroy(&lookup->sendmsg);
1247         if (lookup->querysig != NULL) {
1248                 debug("freeing buffer %p", lookup->querysig);
1249                 isc_buffer_free(&lookup->querysig);
1250         }
1251         if (lookup->timer != NULL)
1252                 isc_timer_detach(&lookup->timer);
1253         if (lookup->sendspace != NULL)
1254                 isc_mempool_put(commctx, lookup->sendspace);
1255
1256         if (lookup->tsigctx != NULL)
1257                 dst_context_destroy(&lookup->tsigctx);
1258
1259         isc_mem_free(mctx, lookup);
1260         return (ISC_TRUE);
1261 }
1262
1263 /*
1264  * If we can, start the next lookup in the queue running.
1265  * This assumes that the lookup on the head of the queue hasn't been
1266  * started yet.  It also removes the lookup from the head of the queue,
1267  * setting the current_lookup pointer pointing to it.
1268  */
1269 void
1270 start_lookup(void) {
1271         debug("start_lookup()");
1272         if (cancel_now)
1273                 return;
1274
1275         /*
1276          * If there's a current lookup running, we really shouldn't get
1277          * here.
1278          */
1279         INSIST(current_lookup == NULL);
1280
1281         current_lookup = ISC_LIST_HEAD(lookup_list);
1282         /*
1283          * Put the current lookup somewhere so cancel_all can find it
1284          */
1285         if (current_lookup != NULL) {
1286                 ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
1287 #if DIG_SIGCHASE_TD
1288                 if (current_lookup->do_topdown &&
1289                     !current_lookup->rdtype_sigchaseset) {
1290                         dst_key_t *trustedkey = NULL;
1291                         isc_buffer_t *b = NULL;
1292                         isc_region_t r;
1293                         isc_result_t result;
1294                         dns_name_t query_name;
1295                         dns_name_t *key_name;
1296                         int i;
1297
1298                         result = get_trusted_key(mctx);
1299                         if (result != ISC_R_SUCCESS) {
1300                                 printf("\n;; No trusted key, "
1301                                        "+sigchase option is disabled\n");
1302                                 current_lookup->sigchase = ISC_FALSE;
1303                                 goto novalidation;
1304                         }
1305                         dns_name_init(&query_name, NULL);
1306                         nameFromString(current_lookup->textname, &query_name);
1307
1308                         for (i = 0; i < tk_list.nb_tk; i++) {
1309                                 key_name = dst_key_name(tk_list.key[i]);
1310
1311                                 if (dns_name_issubdomain(&query_name,
1312                                                          key_name) == ISC_TRUE)
1313                                         trustedkey = tk_list.key[i];
1314                                 /*
1315                                  * Verifier que la temp est bien la plus basse
1316                                  * WARNING
1317                                  */
1318                         }
1319                         if (trustedkey == NULL) {
1320                                 printf("\n;; The queried zone: ");
1321                                 dns_name_print(&query_name, stdout);
1322                                 printf(" isn't a subdomain of any Trusted Keys"
1323                                        ": +sigchase option is disable\n");
1324                                 current_lookup->sigchase = ISC_FALSE;
1325                                 free_name(&query_name, mctx);
1326                                 goto novalidation;
1327                         }
1328                         free_name(&query_name, mctx);
1329
1330                         current_lookup->rdtype_sigchase
1331                                 = current_lookup->rdtype;
1332                         current_lookup->rdtype_sigchaseset
1333                                 = current_lookup->rdtypeset;
1334                         current_lookup->rdtype = dns_rdatatype_ns;
1335
1336                         current_lookup->qrdtype_sigchase
1337                                 = current_lookup->qrdtype;
1338                         current_lookup->qrdtype = dns_rdatatype_ns;
1339                 
1340                         current_lookup->rdclass_sigchase
1341                                 = current_lookup->rdclass;
1342                         current_lookup->rdclass_sigchaseset
1343                                 = current_lookup->rdclassset;
1344                         current_lookup->rdclass = dns_rdataclass_in;
1345
1346                         strncpy(current_lookup->textnamesigchase,
1347                                 current_lookup->textname, MXNAME);
1348
1349                         current_lookup->trace_root_sigchase = ISC_TRUE;
1350
1351                         result = isc_buffer_allocate(mctx, &b, BUFSIZE);
1352                         check_result(result, "isc_buffer_allocate");
1353                         result = dns_name_totext(dst_key_name(trustedkey),
1354                                                  ISC_FALSE, b);
1355                         check_result(result, "dns_name_totext");
1356                         isc_buffer_usedregion(b, &r);
1357                         r.base[r.length] = '\0';
1358                         strncpy(current_lookup->textname, (char*)r.base,
1359                                 MXNAME);
1360                         isc_buffer_free(&b);
1361
1362                         nameFromString(current_lookup->textnamesigchase,
1363                                        &chase_name);
1364
1365                         dns_name_init(&chase_authority_name, NULL);
1366                 }
1367         novalidation:
1368 #endif
1369                 setup_lookup(current_lookup);
1370                 do_lookup(current_lookup);
1371         } else {
1372                 check_if_done();
1373         }
1374 }
1375
1376 /*
1377  * If we can, clear the current lookup and start the next one running.
1378  * This calls try_clear_lookup, so may invalidate the lookup pointer.
1379  */
1380 static void
1381 check_next_lookup(dig_lookup_t *lookup) {
1382
1383         INSIST(!free_now);
1384
1385         debug("check_next_lookup(%p)", lookup);
1386
1387         if (ISC_LIST_HEAD(lookup->q) != NULL) {
1388                 debug("still have a worker");
1389                 return;
1390         }
1391         if (try_clear_lookup(lookup)) {
1392                 current_lookup = NULL;
1393                 start_lookup();
1394         }
1395 }
1396
1397 /*
1398  * Create and queue a new lookup as a followup to the current lookup,
1399  * based on the supplied message and section.  This is used in trace and
1400  * name server search modes to start a new lookup using servers from
1401  * NS records in a reply. Returns the number of followup lookups made.
1402  */
1403 static int
1404 followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section)
1405 {
1406         dig_lookup_t *lookup = NULL;
1407         dig_server_t *srv = NULL;
1408         dns_rdataset_t *rdataset = NULL;
1409         dns_rdata_t rdata = DNS_RDATA_INIT;
1410         dns_name_t *name = NULL;
1411         isc_result_t result;
1412         isc_boolean_t success = ISC_FALSE;
1413         int numLookups = 0;
1414
1415         INSIST(!free_now);
1416
1417         debug("following up %s", query->lookup->textname);
1418         
1419         for (result = dns_message_firstname(msg, section);
1420              result == ISC_R_SUCCESS;
1421              result = dns_message_nextname(msg, section)) {
1422                 name = NULL;
1423                 dns_message_currentname(msg, section, &name);
1424
1425                 if (section == DNS_SECTION_AUTHORITY) {
1426                         rdataset = NULL;
1427                         result = dns_message_findtype(name, dns_rdatatype_soa,
1428                                                       0, &rdataset);
1429                         if (result == ISC_R_SUCCESS)
1430                                 return (0);
1431                 }
1432                 rdataset = NULL;
1433                 result = dns_message_findtype(name, dns_rdatatype_ns, 0,
1434                                               &rdataset);
1435                 if (result != ISC_R_SUCCESS)
1436                         continue;
1437
1438                 debug("found NS set");
1439
1440                 for (result = dns_rdataset_first(rdataset);
1441                      result == ISC_R_SUCCESS;
1442                      result = dns_rdataset_next(rdataset)) {
1443                         char namestr[DNS_NAME_FORMATSIZE];
1444                         dns_rdata_ns_t ns;
1445
1446                         if (query->lookup->trace_root &&
1447                             query->lookup->nsfound >= MXSERV)
1448                                 break;
1449
1450                         dns_rdataset_current(rdataset, &rdata);
1451
1452                         query->lookup->nsfound++;
1453                         (void)dns_rdata_tostruct(&rdata, &ns, NULL);
1454                         dns_name_format(&ns.name, namestr, sizeof(namestr));
1455                         dns_rdata_freestruct(&ns);
1456
1457                         /* Initialize lookup if we've not yet */
1458                         debug("found NS %d %s", numLookups, namestr);
1459                         numLookups++;
1460                         if (!success) {
1461                                 success = ISC_TRUE;
1462                                 lookup_counter++;
1463                                 lookup = requeue_lookup(query->lookup,
1464                                                         ISC_FALSE);
1465                                 cancel_lookup(query->lookup);
1466                                 lookup->doing_xfr = ISC_FALSE;
1467                                 if (!lookup->trace_root &&
1468                                     section == DNS_SECTION_ANSWER)
1469                                         lookup->trace = ISC_FALSE;
1470                                 else
1471                                         lookup->trace = query->lookup->trace;
1472                                 lookup->ns_search_only =
1473                                         query->lookup->ns_search_only;
1474                                 lookup->trace_root = ISC_FALSE;
1475                                 if (lookup->ns_search_only)
1476                                         lookup->recurse = ISC_FALSE;
1477                         }
1478                         srv = make_server(namestr, namestr);
1479                         debug("adding server %s", srv->servername);
1480                         ISC_LIST_APPEND(lookup->my_server_list, srv, link);
1481                         dns_rdata_reset(&rdata);
1482                 }
1483         }
1484
1485         if (lookup == NULL &&
1486             section == DNS_SECTION_ANSWER &&
1487             (query->lookup->trace || query->lookup->ns_search_only))
1488                 return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY));
1489
1490         return numLookups;
1491 }
1492
1493 /*
1494  * Create and queue a new lookup using the next origin from the search
1495  * list, read in setup_system().
1496  *
1497  * Return ISC_TRUE iff there was another searchlist entry.
1498  */
1499 static isc_boolean_t
1500 next_origin(dns_message_t *msg, dig_query_t *query) {
1501         dig_lookup_t *lookup;
1502
1503         UNUSED(msg);
1504
1505         INSIST(!free_now);
1506
1507         debug("next_origin()");
1508         debug("following up %s", query->lookup->textname);
1509
1510         if (!usesearch)
1511                 /*
1512                  * We're not using a search list, so don't even think
1513                  * about finding the next entry.
1514                  */
1515                 return (ISC_FALSE);
1516         if (query->lookup->origin == NULL)
1517                 /*
1518                  * Then we just did rootorg; there's nothing left.
1519                  */
1520                 return (ISC_FALSE);
1521         lookup = requeue_lookup(query->lookup, ISC_TRUE);
1522         lookup->origin = ISC_LIST_NEXT(query->lookup->origin, link);
1523         cancel_lookup(query->lookup);
1524         return (ISC_TRUE);
1525 }
1526
1527 /*
1528  * Insert an SOA record into the sendmessage in a lookup.  Used for
1529  * creating IXFR queries.
1530  */
1531 static void
1532 insert_soa(dig_lookup_t *lookup) {
1533         isc_result_t result;
1534         dns_rdata_soa_t soa;
1535         dns_rdata_t *rdata = NULL;
1536         dns_rdatalist_t *rdatalist = NULL;
1537         dns_rdataset_t *rdataset = NULL;
1538         dns_name_t *soaname = NULL;
1539
1540         debug("insert_soa()");
1541         soa.mctx = mctx;
1542         soa.serial = lookup->ixfr_serial;
1543         soa.refresh = 0;
1544         soa.retry = 0;
1545         soa.expire = 0;
1546         soa.minimum = 0;
1547         soa.common.rdclass = lookup->rdclass;
1548         soa.common.rdtype = dns_rdatatype_soa;
1549
1550         dns_name_init(&soa.origin, NULL);
1551         dns_name_init(&soa.contact, NULL);
1552
1553         dns_name_clone(dns_rootname, &soa.origin);
1554         dns_name_clone(dns_rootname, &soa.contact);
1555
1556         isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
1557                         sizeof(lookup->rdatastore));
1558
1559         result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
1560         check_result(result, "dns_message_gettemprdata");
1561
1562         result = dns_rdata_fromstruct(rdata, lookup->rdclass,
1563                                       dns_rdatatype_soa, &soa,
1564                                       &lookup->rdatabuf);
1565         check_result(result, "isc_rdata_fromstruct");
1566
1567         result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
1568         check_result(result, "dns_message_gettemprdatalist");
1569
1570         result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
1571         check_result(result, "dns_message_gettemprdataset");
1572
1573         dns_rdatalist_init(rdatalist);
1574         rdatalist->type = dns_rdatatype_soa;
1575         rdatalist->rdclass = lookup->rdclass;
1576         rdatalist->covers = 0;
1577         rdatalist->ttl = 0;
1578         ISC_LIST_INIT(rdatalist->rdata);
1579         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1580
1581         dns_rdataset_init(rdataset);
1582         dns_rdatalist_tordataset(rdatalist, rdataset);
1583
1584         result = dns_message_gettempname(lookup->sendmsg, &soaname);
1585         check_result(result, "dns_message_gettempname");
1586         dns_name_init(soaname, NULL);
1587         dns_name_clone(lookup->name, soaname);
1588         ISC_LIST_INIT(soaname->list);
1589         ISC_LIST_APPEND(soaname->list, rdataset, link);
1590         dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
1591 }
1592
1593 /*
1594  * Setup the supplied lookup structure, making it ready to start sending
1595  * queries to servers.  Create and initialize the message to be sent as
1596  * well as the query structures and buffer space for the replies.  If the
1597  * server list is empty, clone it from the system default list.
1598  */
1599 void
1600 setup_lookup(dig_lookup_t *lookup) {
1601         isc_result_t result;
1602         isc_uint32_t id;
1603         int len;
1604         dig_server_t *serv;
1605         dig_query_t *query;
1606         isc_buffer_t b;
1607         dns_compress_t cctx;
1608         char store[MXNAME];
1609
1610         REQUIRE(lookup != NULL);
1611         INSIST(!free_now);
1612
1613         debug("setup_lookup(%p)", lookup);
1614
1615         result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
1616                                     &lookup->sendmsg);
1617         check_result(result, "dns_message_create");
1618
1619         if (lookup->new_search) {
1620                 debug("resetting lookup counter.");
1621                 lookup_counter = 0;
1622         }
1623
1624         if (ISC_LIST_EMPTY(lookup->my_server_list)) {
1625                 debug("cloning server list");
1626                 clone_server_list(server_list, &lookup->my_server_list);
1627         }
1628         result = dns_message_gettempname(lookup->sendmsg, &lookup->name);
1629         check_result(result, "dns_message_gettempname");
1630         dns_name_init(lookup->name, NULL);
1631
1632         isc_buffer_init(&lookup->namebuf, lookup->namespace,
1633                         sizeof(lookup->namespace));
1634         isc_buffer_init(&lookup->onamebuf, lookup->onamespace,
1635                         sizeof(lookup->onamespace));
1636
1637         /*
1638          * If the name has too many dots, force the origin to be NULL
1639          * (which produces an absolute lookup).  Otherwise, take the origin
1640          * we have if there's one in the struct already.  If it's NULL,
1641          * take the first entry in the searchlist iff either usesearch
1642          * is TRUE or we got a domain line in the resolv.conf file.
1643          */
1644         /* XXX New search here? */
1645         if ((count_dots(lookup->textname) >= ndots) || !usesearch)
1646                 lookup->origin = NULL; /* Force abs lookup */
1647         else if (lookup->origin == NULL && lookup->new_search && usesearch)
1648                 lookup->origin = ISC_LIST_HEAD(search_list);
1649
1650         if (lookup->origin != NULL) {
1651                 debug("trying origin %s", lookup->origin->origin);
1652                 result = dns_message_gettempname(lookup->sendmsg,
1653                                                  &lookup->oname);
1654                 check_result(result, "dns_message_gettempname");
1655                 dns_name_init(lookup->oname, NULL);
1656                 /* XXX Helper funct to conv char* to name? */
1657                 len = strlen(lookup->origin->origin);
1658                 isc_buffer_init(&b, lookup->origin->origin, len);
1659                 isc_buffer_add(&b, len);
1660                 result = dns_name_fromtext(lookup->oname, &b, dns_rootname,
1661                                            ISC_FALSE, &lookup->onamebuf);
1662                 if (result != ISC_R_SUCCESS) {
1663                         dns_message_puttempname(lookup->sendmsg,
1664                                                 &lookup->name);
1665                         dns_message_puttempname(lookup->sendmsg,
1666                                                 &lookup->oname);
1667                         fatal("'%s' is not in legal name syntax (%s)",
1668                               lookup->origin->origin,
1669                               isc_result_totext(result));
1670                 }
1671                 if (lookup->trace && lookup->trace_root) {
1672                         dns_name_clone(dns_rootname, lookup->name);
1673                 } else {
1674                         len = strlen(lookup->textname);
1675                         isc_buffer_init(&b, lookup->textname, len);
1676                         isc_buffer_add(&b, len);
1677                         result = dns_name_fromtext(lookup->name, &b,
1678                                                    lookup->oname, ISC_FALSE,
1679                                                    &lookup->namebuf);
1680                 }
1681                 if (result != ISC_R_SUCCESS) {
1682                         dns_message_puttempname(lookup->sendmsg,
1683                                                 &lookup->name);
1684                         dns_message_puttempname(lookup->sendmsg,
1685                                                 &lookup->oname);
1686                         fatal("'%s' is not in legal name syntax (%s)",
1687                               lookup->textname, isc_result_totext(result));
1688                 }
1689                 dns_message_puttempname(lookup->sendmsg, &lookup->oname);
1690         } else {
1691                 debug("using root origin");
1692                 if (lookup->trace && lookup->trace_root)
1693                         dns_name_clone(dns_rootname, lookup->name);
1694                 else {
1695                         len = strlen(lookup->textname);
1696                         isc_buffer_init(&b, lookup->textname, len);
1697                         isc_buffer_add(&b, len);
1698                         result = dns_name_fromtext(lookup->name, &b,
1699                                                    dns_rootname,
1700                                                    ISC_FALSE,
1701                                                    &lookup->namebuf);
1702                 }
1703                 if (result != ISC_R_SUCCESS) {
1704                         dns_message_puttempname(lookup->sendmsg,
1705                                                 &lookup->name);
1706                         isc_buffer_init(&b, store, MXNAME);
1707                         fatal("'%s' is not a legal name "
1708                               "(%s)", lookup->textname,
1709                               isc_result_totext(result));
1710                 }
1711         }
1712         dns_name_format(lookup->name, store, sizeof(store));
1713         trying(store, lookup);
1714         INSIST(dns_name_isabsolute(lookup->name));
1715
1716         isc_random_get(&id);
1717         lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
1718         lookup->sendmsg->opcode = dns_opcode_query;
1719         lookup->msgcounter = 0;
1720         /*
1721          * If this is a trace request, completely disallow recursion, since
1722          * it's meaningless for traces.
1723          */
1724         if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root))
1725                 lookup->recurse = ISC_FALSE;
1726
1727         if (lookup->recurse &&
1728             lookup->rdtype != dns_rdatatype_axfr &&
1729             lookup->rdtype != dns_rdatatype_ixfr) {
1730                 debug("recursive query");
1731                 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD;
1732         }
1733
1734         /* XXX aaflag */
1735         if (lookup->aaonly) {
1736                 debug("AA query");
1737                 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA;
1738         }
1739
1740         if (lookup->adflag) {
1741                 debug("AD query");
1742                 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD;
1743         }
1744
1745         if (lookup->cdflag) {
1746                 debug("CD query");
1747                 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD;
1748         }
1749
1750         dns_message_addname(lookup->sendmsg, lookup->name,
1751                             DNS_SECTION_QUESTION);
1752
1753         if (lookup->trace && lookup->trace_root) {
1754                 lookup->qrdtype = lookup->rdtype;
1755                 lookup->rdtype = dns_rdatatype_ns;
1756         }
1757
1758         if ((lookup->rdtype == dns_rdatatype_axfr) ||
1759             (lookup->rdtype == dns_rdatatype_ixfr)) {
1760                 lookup->doing_xfr = ISC_TRUE;
1761                 /*
1762                  * Force TCP mode if we're doing an xfr.
1763                  * XXX UDP ixfr's would be useful
1764                  */
1765                 lookup->tcp_mode = ISC_TRUE;
1766         }
1767
1768         add_question(lookup->sendmsg, lookup->name, lookup->rdclass,
1769                      lookup->rdtype);
1770
1771         /* add_soa */
1772         if (lookup->rdtype == dns_rdatatype_ixfr)
1773                 insert_soa(lookup);
1774
1775         /* XXX Insist this? */
1776         lookup->tsigctx = NULL;
1777         lookup->querysig = NULL;
1778         if (key != NULL) {
1779                 debug("initializing keys");
1780                 result = dns_message_settsigkey(lookup->sendmsg, key);
1781                 check_result(result, "dns_message_settsigkey");
1782         }
1783
1784         lookup->sendspace = isc_mempool_get(commctx);
1785         if (lookup->sendspace == NULL)
1786                 fatal("memory allocation failure");
1787
1788         result = dns_compress_init(&cctx, -1, mctx);
1789         check_result(result, "dns_compress_init");
1790
1791         debug("starting to render the message");
1792         isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE);
1793         result = dns_message_renderbegin(lookup->sendmsg, &cctx,
1794                                          &lookup->renderbuf);
1795         check_result(result, "dns_message_renderbegin");
1796         if (lookup->udpsize > 0 || lookup->dnssec) {
1797                 if (lookup->udpsize == 0)
1798                         lookup->udpsize = 2048;
1799                 add_opt(lookup->sendmsg, lookup->udpsize, lookup->dnssec);
1800         }
1801
1802         result = dns_message_rendersection(lookup->sendmsg,
1803                                            DNS_SECTION_QUESTION, 0);
1804         check_result(result, "dns_message_rendersection");
1805         result = dns_message_rendersection(lookup->sendmsg,
1806                                            DNS_SECTION_AUTHORITY, 0);
1807         check_result(result, "dns_message_rendersection");
1808         result = dns_message_renderend(lookup->sendmsg);
1809         check_result(result, "dns_message_renderend");
1810         debug("done rendering");
1811
1812         dns_compress_invalidate(&cctx);
1813
1814         /*
1815          * Force TCP mode if the request is larger than 512 bytes.
1816          */
1817         if (isc_buffer_usedlength(&lookup->renderbuf) > 512)
1818                 lookup->tcp_mode = ISC_TRUE;
1819
1820         lookup->pending = ISC_FALSE;
1821
1822         for (serv = ISC_LIST_HEAD(lookup->my_server_list);
1823              serv != NULL;
1824              serv = ISC_LIST_NEXT(serv, link)) {
1825                 query = isc_mem_allocate(mctx, sizeof(dig_query_t));
1826                 if (query == NULL)
1827                         fatal("memory allocation failure in %s:%d",
1828                               __FILE__, __LINE__);
1829                 debug("create query %p linked to lookup %p",
1830                        query, lookup);
1831                 query->lookup = lookup;
1832                 query->waiting_connect = ISC_FALSE;
1833                 query->waiting_senddone = ISC_FALSE;
1834                 query->pending_free = ISC_FALSE;
1835                 query->recv_made = ISC_FALSE;
1836                 query->first_pass = ISC_TRUE;
1837                 query->first_soa_rcvd = ISC_FALSE;
1838                 query->second_rr_rcvd = ISC_FALSE;
1839                 query->first_repeat_rcvd = ISC_FALSE;
1840                 query->warn_id = ISC_TRUE;
1841                 query->first_rr_serial = 0;
1842                 query->second_rr_serial = 0;
1843                 query->servname = serv->servername;
1844                 query->userarg = serv->userarg;
1845                 query->rr_count = 0;
1846                 query->msg_count = 0;
1847                 ISC_LINK_INIT(query, link);
1848                 ISC_LIST_INIT(query->recvlist);
1849                 ISC_LIST_INIT(query->lengthlist);
1850                 query->sock = NULL;
1851                 query->recvspace = isc_mempool_get(commctx);
1852                 if (query->recvspace == NULL)
1853                         fatal("memory allocation failure");
1854
1855                 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
1856                 isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
1857                 isc_buffer_init(&query->slbuf, query->slspace, 2);
1858                 query->sendbuf = lookup->renderbuf;
1859
1860                 ISC_LINK_INIT(query, link);
1861                 ISC_LIST_ENQUEUE(lookup->q, query, link);
1862         }
1863         /* XXX qrflag, print_query, etc... */
1864         if (!ISC_LIST_EMPTY(lookup->q) && qr) {
1865                 printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg,
1866                              ISC_TRUE);
1867         }
1868 }
1869
1870 /*
1871  * Event handler for send completion.  Track send counter, and clear out
1872  * the query if the send was canceled.
1873  */
1874 static void
1875 send_done(isc_task_t *_task, isc_event_t *event) {
1876         isc_socketevent_t *sevent = (isc_socketevent_t *)event;
1877         isc_buffer_t *b = NULL;
1878         dig_query_t *query, *next;
1879         dig_lookup_t *l;
1880
1881         REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1882
1883         UNUSED(_task);
1884
1885         LOCK_LOOKUP;
1886
1887         debug("send_done()");
1888         sendcount--;
1889         debug("sendcount=%d", sendcount);
1890         INSIST(sendcount >= 0);
1891
1892         for  (b = ISC_LIST_HEAD(sevent->bufferlist);
1893               b != NULL;
1894               b = ISC_LIST_HEAD(sevent->bufferlist)) 
1895                 ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
1896
1897         query = event->ev_arg;
1898         query->waiting_senddone = ISC_FALSE;
1899         l = query->lookup;
1900
1901         if (l->ns_search_only && !l->trace_root) {
1902                 debug("sending next, since searching");
1903                 next = ISC_LIST_NEXT(query, link);
1904                 if (next != NULL)
1905                         send_udp(next);
1906         }
1907
1908         isc_event_free(&event);
1909
1910         if (query->pending_free)
1911                 isc_mem_free(mctx, query);
1912
1913         check_if_done();
1914         UNLOCK_LOOKUP;
1915 }
1916
1917 /*
1918  * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
1919  * IO sockets.  The cancel handlers should take care of cleaning up the
1920  * query and lookup structures
1921  */
1922 static void
1923 cancel_lookup(dig_lookup_t *lookup) {
1924         dig_query_t *query, *next;
1925
1926         debug("cancel_lookup()");
1927         query = ISC_LIST_HEAD(lookup->q);
1928         while (query != NULL) {
1929                 next = ISC_LIST_NEXT(query, link);
1930                 if (query->sock != NULL) {
1931                         isc_socket_cancel(query->sock, global_task,
1932                                           ISC_SOCKCANCEL_ALL);
1933                         check_if_done();
1934                 } else {
1935                         clear_query(query);
1936                 }
1937                 query = next;
1938         }
1939         if (lookup->timer != NULL)
1940                 isc_timer_detach(&lookup->timer);
1941         lookup->pending = ISC_FALSE;
1942         lookup->retries = 0;
1943 }
1944
1945 static void
1946 bringup_timer(dig_query_t *query, unsigned int default_timeout) {
1947         dig_lookup_t *l;
1948         unsigned int local_timeout;
1949         isc_result_t result;
1950
1951         debug("bringup_timer()");
1952         /*
1953          * If the timer already exists, that means we're calling this
1954          * a second time (for a retry).  Don't need to recreate it,
1955          * just reset it.
1956          */
1957         l = query->lookup;
1958         if (ISC_LIST_NEXT(query, link) != NULL)
1959                 local_timeout = SERVER_TIMEOUT;
1960         else {
1961                 if (timeout == 0)
1962                         local_timeout = default_timeout;
1963                 else
1964                         local_timeout = timeout;
1965         }
1966         debug("have local timeout of %d", local_timeout);
1967         isc_interval_set(&l->interval, local_timeout, 0);
1968         if (l->timer != NULL)
1969                 isc_timer_detach(&l->timer);
1970         result = isc_timer_create(timermgr, isc_timertype_once, NULL,
1971                                   &l->interval, global_task, connect_timeout,
1972                                   l, &l->timer);
1973         check_result(result, "isc_timer_create");
1974 }       
1975
1976 static void
1977 connect_done(isc_task_t *task, isc_event_t *event);
1978
1979 /*
1980  * Unlike send_udp, this can't be called multiple times with the same
1981  * query.  When we retry TCP, we requeue the whole lookup, which should
1982  * start anew.
1983  */
1984 static void
1985 send_tcp_connect(dig_query_t *query) {
1986         isc_result_t result;
1987         dig_query_t *next;
1988         dig_lookup_t *l;
1989
1990         debug("send_tcp_connect(%p)", query);
1991
1992         l = query->lookup;
1993         query->waiting_connect = ISC_TRUE;
1994         query->lookup->current_query = query;
1995         get_address(query->servname, port, &query->sockaddr);
1996         
1997         if (specified_source &&
1998             (isc_sockaddr_pf(&query->sockaddr) !=
1999              isc_sockaddr_pf(&bind_address))) {
2000                 printf(";; Skipping server %s, incompatible "
2001                        "address family\n", query->servname);
2002                 query->waiting_connect = ISC_FALSE;
2003                 next = ISC_LIST_NEXT(query, link);
2004                 l = query->lookup;
2005                 clear_query(query);
2006                 if (next == NULL) {
2007                         printf(";; No acceptable nameservers\n");
2008                         check_next_lookup(l);
2009                         return;
2010                 }
2011                 send_tcp_connect(next);
2012                 return;
2013         }
2014         INSIST(query->sock == NULL);
2015         result = isc_socket_create(socketmgr,
2016                                    isc_sockaddr_pf(&query->sockaddr),
2017                                    isc_sockettype_tcp, &query->sock);
2018         check_result(result, "isc_socket_create");
2019         sockcount++;
2020         debug("sockcount=%d", sockcount);
2021         if (specified_source)
2022                 result = isc_socket_bind(query->sock, &bind_address);
2023         else {
2024                 if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
2025                     have_ipv4)
2026                         isc_sockaddr_any(&bind_any);
2027                 else
2028                         isc_sockaddr_any6(&bind_any);
2029                 result = isc_socket_bind(query->sock, &bind_any);
2030         }
2031         check_result(result, "isc_socket_bind");
2032         bringup_timer(query, TCP_TIMEOUT);
2033         result = isc_socket_connect(query->sock, &query->sockaddr,
2034                                     global_task, connect_done, query);
2035         check_result(result, "isc_socket_connect");
2036         /*
2037          * If we're at the endgame of a nameserver search, we need to
2038          * immediately bring up all the queries.  Do it here.
2039          */
2040         if (l->ns_search_only && !l->trace_root) {
2041                 debug("sending next, since searching");
2042                 next = ISC_LIST_NEXT(query, link);
2043                 if (next != NULL)
2044                         send_tcp_connect(next);
2045         }
2046 }
2047
2048 /*
2049  * Send a UDP packet to the remote nameserver, possible starting the
2050  * recv action as well.  Also make sure that the timer is running and
2051  * is properly reset.
2052  */
2053 static void
2054 send_udp(dig_query_t *query) {
2055         dig_lookup_t *l = NULL;
2056         isc_result_t result;
2057
2058         debug("send_udp(%p)", query);
2059
2060         l = query->lookup;
2061         bringup_timer(query, UDP_TIMEOUT);
2062         l->current_query = query;
2063         debug("working on lookup %p, query %p", query->lookup, query);
2064         if (!query->recv_made) {
2065                 /* XXX Check the sense of this, need assertion? */
2066                 query->waiting_connect = ISC_FALSE;
2067                 get_address(query->servname, port, &query->sockaddr);
2068
2069                 result = isc_socket_create(socketmgr,
2070                                            isc_sockaddr_pf(&query->sockaddr),
2071                                            isc_sockettype_udp, &query->sock);
2072                 check_result(result, "isc_socket_create");
2073                 sockcount++;
2074                 debug("sockcount=%d", sockcount);
2075                 if (specified_source) {
2076                         result = isc_socket_bind(query->sock, &bind_address);
2077                 } else {
2078                         isc_sockaddr_anyofpf(&bind_any,
2079                                         isc_sockaddr_pf(&query->sockaddr));
2080                         result = isc_socket_bind(query->sock, &bind_any);
2081                 }
2082                 check_result(result, "isc_socket_bind");
2083
2084                 query->recv_made = ISC_TRUE;
2085                 ISC_LINK_INIT(&query->recvbuf, link);
2086                 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf,
2087                                  link);
2088                 debug("recving with lookup=%p, query=%p, sock=%p",
2089                       query->lookup, query, query->sock);
2090                 result = isc_socket_recvv(query->sock, &query->recvlist, 1,
2091                                           global_task, recv_done, query);
2092                 check_result(result, "isc_socket_recvv");
2093                 recvcount++;
2094                 debug("recvcount=%d", recvcount);
2095         }
2096         ISC_LIST_INIT(query->sendlist);
2097         ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link);
2098         debug("sending a request");
2099         TIME_NOW(&query->time_sent);
2100         INSIST(query->sock != NULL);
2101         query->waiting_senddone = ISC_TRUE;
2102         result = isc_socket_sendtov(query->sock, &query->sendlist,
2103                                     global_task, send_done, query,
2104                                     &query->sockaddr, NULL);
2105         check_result(result, "isc_socket_sendtov");
2106         sendcount++;
2107 }
2108
2109 /*
2110  * IO timeout handler, used for both connect and recv timeouts.  If
2111  * retries are still allowed, either resend the UDP packet or queue a
2112  * new TCP lookup.  Otherwise, cancel the lookup.
2113  */
2114 static void
2115 connect_timeout(isc_task_t *task, isc_event_t *event) {
2116         dig_lookup_t *l = NULL;
2117         dig_query_t *query = NULL, *cq;
2118
2119         UNUSED(task);
2120         REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE);
2121
2122         debug("connect_timeout()");
2123
2124         LOCK_LOOKUP;
2125         l = event->ev_arg;
2126         query = l->current_query;
2127         isc_event_free(&event);
2128
2129         INSIST(!free_now);
2130
2131         if ((query != NULL) && (query->lookup->current_query != NULL) &&
2132             (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) {
2133                 debug("trying next server...");
2134                 cq = query->lookup->current_query;
2135                 if (!l->tcp_mode)
2136                         send_udp(ISC_LIST_NEXT(cq, link));
2137                 else
2138                         send_tcp_connect(ISC_LIST_NEXT(cq, link));
2139                 UNLOCK_LOOKUP;
2140                 return;
2141         }
2142
2143         if (l->retries > 1) {
2144                 if (!l->tcp_mode) {
2145                         l->retries--;
2146                         debug("resending UDP request to first server");
2147                         send_udp(ISC_LIST_HEAD(l->q));
2148                 } else {
2149                         debug("making new TCP request, %d tries left",
2150                               l->retries);
2151                         l->retries--;
2152                         requeue_lookup(l, ISC_TRUE);
2153                         cancel_lookup(l);
2154                         check_next_lookup(l);
2155                 }
2156         } else {
2157                 fputs(l->cmdline, stdout);
2158                 printf(";; connection timed out; no servers could be "
2159                        "reached\n");
2160                 cancel_lookup(l);
2161                 check_next_lookup(l);
2162                 if (exitcode < 9)
2163                         exitcode = 9;
2164         }
2165         UNLOCK_LOOKUP;
2166 }
2167
2168 /*
2169  * Event handler for the TCP recv which gets the length header of TCP
2170  * packets.  Start the next recv of length bytes.
2171  */
2172 static void
2173 tcp_length_done(isc_task_t *task, isc_event_t *event) {
2174         isc_socketevent_t *sevent;
2175         isc_buffer_t *b = NULL;
2176         isc_result_t result;
2177         dig_query_t *query = NULL;
2178         dig_lookup_t *l;
2179         isc_uint16_t length;
2180
2181         REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
2182         INSIST(!free_now);
2183
2184         UNUSED(task);
2185
2186         debug("tcp_length_done()");
2187
2188         LOCK_LOOKUP;
2189         sevent = (isc_socketevent_t *)event;
2190         query = event->ev_arg;
2191
2192         recvcount--;
2193         INSIST(recvcount >= 0);
2194
2195         b = ISC_LIST_HEAD(sevent->bufferlist);
2196         INSIST(b ==  &query->lengthbuf);
2197         ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2198
2199         if (sevent->result == ISC_R_CANCELED) {
2200                 isc_event_free(&event);
2201                 l = query->lookup;
2202                 clear_query(query);
2203                 check_next_lookup(l);
2204                 UNLOCK_LOOKUP;
2205                 return;
2206         }
2207         if (sevent->result != ISC_R_SUCCESS) {
2208                 char sockstr[ISC_SOCKADDR_FORMATSIZE];
2209                 isc_sockaddr_format(&query->sockaddr, sockstr,
2210                                     sizeof(sockstr));
2211                 printf(";; communications error to %s: %s\n",
2212                        sockstr, isc_result_totext(sevent->result));
2213                 l = query->lookup;
2214                 isc_socket_detach(&query->sock);
2215                 sockcount--;
2216                 debug("sockcount=%d", sockcount);
2217                 INSIST(sockcount >= 0);
2218                 isc_event_free(&event);
2219                 clear_query(query);
2220                 check_next_lookup(l);
2221                 UNLOCK_LOOKUP;
2222                 return;
2223         }
2224         length = isc_buffer_getuint16(b);
2225         if (length == 0) {
2226                 isc_event_free(&event);
2227                 launch_next_query(query, ISC_FALSE);
2228                 UNLOCK_LOOKUP;
2229                 return;
2230         }
2231
2232         /*
2233          * Even though the buffer was already init'ed, we need
2234          * to redo it now, to force the length we want.
2235          */
2236         isc_buffer_invalidate(&query->recvbuf);
2237         isc_buffer_init(&query->recvbuf, query->recvspace, length);
2238         ENSURE(ISC_LIST_EMPTY(query->recvlist));
2239         ISC_LINK_INIT(&query->recvbuf, link);
2240         ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
2241         debug("recving with lookup=%p, query=%p", query->lookup, query);
2242         result = isc_socket_recvv(query->sock, &query->recvlist, length, task,
2243                                   recv_done, query);
2244         check_result(result, "isc_socket_recvv");
2245         recvcount++;
2246         debug("resubmitted recv request with length %d, recvcount=%d",
2247               length, recvcount);
2248         isc_event_free(&event);
2249         UNLOCK_LOOKUP;
2250 }
2251
2252 /*
2253  * For transfers that involve multiple recvs (XFR's in particular),
2254  * launch the next recv.
2255  */
2256 static void
2257 launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
2258         isc_result_t result;
2259         dig_lookup_t *l;
2260
2261         INSIST(!free_now);
2262
2263         debug("launch_next_query()");
2264
2265         if (!query->lookup->pending) {
2266                 debug("ignoring launch_next_query because !pending");
2267                 isc_socket_detach(&query->sock);
2268                 sockcount--;
2269                 debug("sockcount=%d", sockcount);
2270                 INSIST(sockcount >= 0);
2271                 query->waiting_connect = ISC_FALSE;
2272                 l = query->lookup;
2273                 clear_query(query);
2274                 check_next_lookup(l);
2275                 return;
2276         }
2277
2278         isc_buffer_clear(&query->slbuf);
2279         isc_buffer_clear(&query->lengthbuf);
2280         isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->sendbuf.used);
2281         ISC_LIST_INIT(query->sendlist);
2282         ISC_LINK_INIT(&query->slbuf, link);
2283         ISC_LIST_ENQUEUE(query->sendlist, &query->slbuf, link);
2284         if (include_question)
2285                 ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link);
2286         ISC_LINK_INIT(&query->lengthbuf, link);
2287         ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
2288
2289         result = isc_socket_recvv(query->sock, &query->lengthlist, 0,
2290                                   global_task, tcp_length_done, query);
2291         check_result(result, "isc_socket_recvv");
2292         recvcount++;
2293         debug("recvcount=%d", recvcount);
2294         if (!query->first_soa_rcvd) {
2295                 debug("sending a request in launch_next_query");
2296                 TIME_NOW(&query->time_sent);
2297                 query->waiting_senddone = ISC_TRUE;
2298                 result = isc_socket_sendv(query->sock, &query->sendlist,
2299                                           global_task, send_done, query);
2300                 check_result(result, "isc_socket_sendv");
2301                 sendcount++;
2302                 debug("sendcount=%d", sendcount);
2303         }
2304         query->waiting_connect = ISC_FALSE;
2305 #if 0
2306         check_next_lookup(query->lookup);
2307 #endif
2308         return;
2309 }
2310
2311 /*
2312  * Event handler for TCP connect complete.  Make sure the connection was
2313  * successful, then pass into launch_next_query to actually send the
2314  * question.
2315  */
2316 static void
2317 connect_done(isc_task_t *task, isc_event_t *event) {
2318         isc_socketevent_t *sevent = NULL;
2319         dig_query_t *query = NULL, *next;
2320         dig_lookup_t *l;
2321
2322         UNUSED(task);
2323
2324         REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
2325         INSIST(!free_now);
2326
2327         debug("connect_done()");
2328
2329         LOCK_LOOKUP;
2330         sevent = (isc_socketevent_t *)event;
2331         query = sevent->ev_arg;
2332
2333         INSIST(query->waiting_connect);
2334
2335         query->waiting_connect = ISC_FALSE;
2336
2337         if (sevent->result == ISC_R_CANCELED) {
2338                 debug("in cancel handler");
2339                 isc_socket_detach(&query->sock);
2340                 sockcount--;
2341                 INSIST(sockcount >= 0);
2342                 debug("sockcount=%d", sockcount);
2343                 query->waiting_connect = ISC_FALSE;
2344                 isc_event_free(&event);
2345                 l = query->lookup;
2346                 clear_query(query);
2347                 check_next_lookup(l);
2348                 UNLOCK_LOOKUP;
2349                 return;
2350         }
2351         if (sevent->result != ISC_R_SUCCESS) {
2352                 char sockstr[ISC_SOCKADDR_FORMATSIZE];
2353
2354                 debug("unsuccessful connection: %s",
2355                       isc_result_totext(sevent->result));
2356                 isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
2357                 if (sevent->result != ISC_R_CANCELED)
2358                         printf(";; Connection to %s(%s) for %s failed: "
2359                                "%s.\n", sockstr,
2360                                query->servname, query->lookup->textname,
2361                                isc_result_totext(sevent->result));
2362                 isc_socket_detach(&query->sock);
2363                 sockcount--;
2364                 INSIST(sockcount >= 0);
2365                 /* XXX Clean up exitcodes */
2366                 if (exitcode < 9)
2367                         exitcode = 9;
2368                 debug("sockcount=%d", sockcount);
2369                 query->waiting_connect = ISC_FALSE;
2370                 isc_event_free(&event);
2371                 l = query->lookup;
2372                 if (l->current_query != NULL)
2373                         next = ISC_LIST_NEXT(l->current_query, link);
2374                 else
2375                         next = NULL;
2376                 clear_query(query);
2377                 if (next != NULL) {
2378                         bringup_timer(next, TCP_TIMEOUT);
2379                         send_tcp_connect(next);
2380                 } else {
2381                         check_next_lookup(l);
2382                 }
2383                 UNLOCK_LOOKUP;
2384                 return;
2385         }
2386         launch_next_query(query, ISC_TRUE);
2387         isc_event_free(&event);
2388         UNLOCK_LOOKUP;
2389 }
2390
2391 /*
2392  * Check if the ongoing XFR needs more data before it's complete, using
2393  * the semantics of IXFR and AXFR protocols.  Much of the complexity of
2394  * this routine comes from determining when an IXFR is complete.
2395  * ISC_FALSE means more data is on the way, and the recv has been issued.
2396  */
2397 static isc_boolean_t
2398 check_for_more_data(dig_query_t *query, dns_message_t *msg,
2399                     isc_socketevent_t *sevent)
2400 {
2401         dns_rdataset_t *rdataset = NULL;
2402         dns_rdata_t rdata = DNS_RDATA_INIT;
2403         dns_rdata_soa_t soa;
2404         isc_uint32_t serial;
2405         isc_result_t result;
2406
2407         debug("check_for_more_data()");
2408
2409         /*
2410          * By the time we're in this routine, we know we're doing
2411          * either an AXFR or IXFR.  If there's no second_rr_type,
2412          * then we don't yet know which kind of answer we got back
2413          * from the server.  Here, we're going to walk through the
2414          * rr's in the message, acting as necessary whenever we hit
2415          * an SOA rr.
2416          */
2417
2418         query->msg_count++;
2419         result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
2420         if (result != ISC_R_SUCCESS) {
2421                 puts("; Transfer failed.");
2422                 return (ISC_TRUE);
2423         }
2424         do {
2425                 dns_name_t *name;
2426                 name = NULL;
2427                 dns_message_currentname(msg, DNS_SECTION_ANSWER,
2428                                         &name);
2429                 for (rdataset = ISC_LIST_HEAD(name->list);
2430                      rdataset != NULL;
2431                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
2432                         result = dns_rdataset_first(rdataset);
2433                         if (result != ISC_R_SUCCESS)
2434                                 continue;
2435                         do {
2436                                 query->rr_count++;
2437                                 dns_rdata_reset(&rdata);
2438                                 dns_rdataset_current(rdataset, &rdata);
2439                                 /*
2440                                  * If this is the first rr, make sure
2441                                  * it's an SOA
2442                                  */
2443                                 if ((!query->first_soa_rcvd) &&
2444                                     (rdata.type != dns_rdatatype_soa)) {
2445                                         puts("; Transfer failed.  "
2446                                              "Didn't start with SOA answer.");
2447                                         return (ISC_TRUE);
2448                                 }
2449                                 if ((!query->second_rr_rcvd) &&
2450                                     (rdata.type != dns_rdatatype_soa)) {
2451                                         query->second_rr_rcvd = ISC_TRUE;
2452                                         query->second_rr_serial = 0;
2453                                         debug("got the second rr as nonsoa");
2454                                         goto next_rdata;
2455                                 }
2456
2457                                 /*
2458                                  * If the record is anything except an SOA
2459                                  * now, just continue on...
2460                                  */
2461                                 if (rdata.type != dns_rdatatype_soa)
2462                                         goto next_rdata;
2463                                 /* Now we have an SOA.  Work with it. */
2464                                 debug("got an SOA");
2465                                 (void)dns_rdata_tostruct(&rdata, &soa, NULL);
2466                                 serial = soa.serial;
2467                                 dns_rdata_freestruct(&soa);
2468                                 if (!query->first_soa_rcvd) {
2469                                         query->first_soa_rcvd = ISC_TRUE;
2470                                         query->first_rr_serial = serial;
2471                                         debug("this is the first %d",
2472                                                query->lookup->ixfr_serial);
2473                                         if (query->lookup->ixfr_serial >=
2474                                             serial)
2475                                                 goto doexit;
2476                                         goto next_rdata;
2477                                 }
2478                                 if (query->lookup->rdtype ==
2479                                     dns_rdatatype_axfr) {
2480                                         debug("doing axfr, got second SOA");
2481                                         goto doexit;
2482                                 }
2483                                 if (!query->second_rr_rcvd) {
2484                                         if (query->first_rr_serial == serial) {
2485                                                 debug("doing ixfr, got "
2486                                                       "empty zone");
2487                                                 goto doexit;
2488                                         }
2489                                         debug("this is the second %d",
2490                                                query->lookup->ixfr_serial);
2491                                         query->second_rr_rcvd = ISC_TRUE;
2492                                         query->second_rr_serial = serial;
2493                                         goto next_rdata;
2494                                 }
2495                                 if (query->second_rr_serial == 0) {
2496                                         /*
2497                                          * If the second RR was a non-SOA
2498                                          * record, and we're getting any
2499                                          * other SOA, then this is an
2500                                          * AXFR, and we're done.
2501                                          */
2502                                         debug("done, since axfr");
2503                                         goto doexit;
2504                                 }
2505                                 /*
2506                                  * If we get to this point, we're doing an
2507                                  * IXFR and have to start really looking
2508                                  * at serial numbers.
2509                                  */
2510                                 if (query->first_rr_serial == serial) {
2511                                         debug("got a match for ixfr");
2512                                         if (!query->first_repeat_rcvd) {
2513                                                 query->first_repeat_rcvd =
2514                                                         ISC_TRUE;
2515                                                 goto next_rdata;
2516                                         }
2517                                         debug("done with ixfr");
2518                                         goto doexit;
2519                                 }
2520                                 debug("meaningless soa %d", serial);
2521                         next_rdata:
2522                                 result = dns_rdataset_next(rdataset);
2523                         } while (result == ISC_R_SUCCESS);
2524                 }
2525                 result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
2526         } while (result == ISC_R_SUCCESS);
2527         launch_next_query(query, ISC_FALSE);
2528         return (ISC_FALSE);
2529  doexit:
2530         received(sevent->n, &sevent->address, query);
2531         return (ISC_TRUE);
2532 }
2533
2534 /*
2535  * Event handler for recv complete.  Perform whatever actions are necessary,
2536  * based on the specifics of the user's request.
2537  */
2538 static void
2539 recv_done(isc_task_t *task, isc_event_t *event) {
2540         isc_socketevent_t *sevent = NULL;
2541         dig_query_t *query = NULL;
2542         isc_buffer_t *b = NULL;
2543         dns_message_t *msg = NULL;
2544 #ifdef DIG_SIGCHASE
2545         dig_message_t *chase_msg = NULL;
2546         dig_message_t *chase_msg2 = NULL;
2547 #endif
2548         isc_result_t result;
2549         dig_lookup_t *n, *l;
2550         isc_boolean_t docancel = ISC_FALSE;
2551         isc_boolean_t match = ISC_TRUE;
2552         unsigned int parseflags;
2553         dns_messageid_t id;
2554         unsigned int msgflags;
2555 #ifdef DIG_SIGCHASE
2556         isc_result_t do_sigchase = ISC_FALSE;
2557
2558         dns_message_t *msg_temp = NULL;
2559         isc_region_t r;
2560         isc_buffer_t *buf = NULL;
2561 #endif
2562
2563         UNUSED(task);
2564         INSIST(!free_now);
2565
2566         debug("recv_done()");
2567
2568         LOCK_LOOKUP;
2569         recvcount--;
2570         debug("recvcount=%d", recvcount);
2571         INSIST(recvcount >= 0);
2572
2573         query = event->ev_arg;
2574         debug("lookup=%p, query=%p", query->lookup, query);
2575
2576         l = query->lookup;
2577
2578         REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
2579         sevent = (isc_socketevent_t *)event;
2580
2581         b = ISC_LIST_HEAD(sevent->bufferlist);
2582         INSIST(b == &query->recvbuf);
2583         ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link);
2584
2585         if ((l->tcp_mode) && (l->timer != NULL))
2586                 isc_timer_touch(l->timer);
2587         if ((!l->pending && !l->ns_search_only) || cancel_now) {
2588                 debug("no longer pending.  Got %s",
2589                         isc_result_totext(sevent->result));
2590                 query->waiting_connect = ISC_FALSE;
2591
2592                 isc_event_free(&event);
2593                 clear_query(query);
2594                 check_next_lookup(l);
2595                 UNLOCK_LOOKUP;
2596                 return;
2597         }
2598
2599         if (sevent->result != ISC_R_SUCCESS) {
2600                 if (sevent->result == ISC_R_CANCELED) {
2601                         debug("in recv cancel handler");
2602                         query->waiting_connect = ISC_FALSE;
2603                 } else {
2604                         printf(";; communications error: %s\n",
2605                                isc_result_totext(sevent->result));
2606                         isc_socket_detach(&query->sock);
2607                         sockcount--;
2608                         debug("sockcount=%d", sockcount);
2609                         INSIST(sockcount >= 0);
2610                 }
2611                 isc_event_free(&event);
2612                 clear_query(query);
2613                 check_next_lookup(l);
2614                 UNLOCK_LOOKUP;
2615                 return;
2616         }
2617
2618         if (!l->tcp_mode &&
2619             !isc_sockaddr_equal(&sevent->address, &query->sockaddr)) {
2620                 char buf1[ISC_SOCKADDR_FORMATSIZE];
2621                 char buf2[ISC_SOCKADDR_FORMATSIZE];
2622                 isc_sockaddr_t any;
2623
2624                 if (isc_sockaddr_pf(&query->sockaddr) == AF_INET)
2625                         isc_sockaddr_any(&any);
2626                 else
2627                         isc_sockaddr_any6(&any);
2628
2629 #ifdef ISC_PLATFORM_HAVESCOPEID
2630                 /*
2631                  * Accept answers from any scope if we havn't specified the
2632                  * scope as long as the address and port match.
2633                  */
2634                 if (isc_sockaddr_pf(&query->sockaddr) == AF_INET6 &&
2635                     query->sockaddr.type.sin6.sin6_scope_id == 0 &&
2636                     memcmp(&sevent->address.type.sin6.sin6_addr,
2637                            &query->sockaddr.type.sin6.sin6_addr,
2638                            sizeof(query->sockaddr.type.sin6.sin6_addr)) == 0 &&
2639                     isc_sockaddr_getport(&sevent->address) ==
2640                     isc_sockaddr_getport(&query->sockaddr))
2641                         /* empty */;
2642                 else
2643 #endif
2644                 /*
2645                  * We don't expect a match above when the packet is
2646                  * sent to 0.0.0.0, :: or to a multicast addresses.
2647                  * XXXMPA broadcast needs to be handled here as well.
2648                  */
2649                 if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) &&
2650                      !isc_sockaddr_ismulticast(&query->sockaddr)) ||
2651                     isc_sockaddr_getport(&query->sockaddr) !=
2652                     isc_sockaddr_getport(&sevent->address)) {
2653                         isc_sockaddr_format(&sevent->address, buf1,
2654                         sizeof(buf1));
2655                         isc_sockaddr_format(&query->sockaddr, buf2,
2656                         sizeof(buf2));
2657                         printf(";; reply from unexpected source: %s,"
2658                         " expected %s\n", buf1, buf2);
2659                         match = ISC_FALSE;
2660                 }
2661         }
2662
2663         result = dns_message_peekheader(b, &id, &msgflags);
2664         if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
2665                 match = ISC_FALSE;
2666                 if (l->tcp_mode) {
2667                         isc_boolean_t fail = ISC_TRUE;
2668                         if (result == ISC_R_SUCCESS) {
2669                                 if (!query->first_soa_rcvd ||
2670                                      query->warn_id)
2671                                         printf(";; %s: ID mismatch: "
2672                                                "expected ID %u, got %u\n",
2673                                                query->first_soa_rcvd ?
2674                                                "WARNING" : "ERROR",
2675                                                l->sendmsg->id, id);
2676                                 if (query->first_soa_rcvd)
2677                                         fail = ISC_FALSE;
2678                                 query->warn_id = ISC_FALSE;
2679                         } else
2680                                 printf(";; ERROR: short "
2681                                        "(< header size) message\n");
2682                         if (fail) {
2683                                 isc_event_free(&event);
2684                                 clear_query(query);
2685                                 check_next_lookup(l);
2686                                 UNLOCK_LOOKUP;
2687                                 return;
2688                         }
2689                         match = ISC_TRUE;
2690                 } else if (result == ISC_R_SUCCESS)
2691                         printf(";; Warning: ID mismatch: "
2692                                "expected ID %u, got %u\n", l->sendmsg->id, id);
2693                 else
2694                         printf(";; Warning: short "
2695                                "(< header size) message received\n");
2696         }
2697
2698         if (!match) {
2699                 isc_buffer_invalidate(&query->recvbuf);
2700                 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
2701                 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
2702                 result = isc_socket_recvv(query->sock, &query->recvlist, 1,
2703                                           global_task, recv_done, query);
2704                 check_result(result, "isc_socket_recvv");
2705                 recvcount++;
2706                 isc_event_free(&event);
2707                 UNLOCK_LOOKUP;
2708                 return;
2709         }
2710
2711         result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
2712         check_result(result, "dns_message_create");
2713
2714         if (key != NULL) {
2715                 if (l->querysig == NULL) {
2716                         debug("getting initial querysig");
2717                         result = dns_message_getquerytsig(l->sendmsg, mctx,
2718                                                           &l->querysig);
2719                         check_result(result, "dns_message_getquerytsig");
2720                 }
2721                 result = dns_message_setquerytsig(msg, l->querysig);
2722                 check_result(result, "dns_message_setquerytsig");
2723                 result = dns_message_settsigkey(msg, key);
2724                 check_result(result, "dns_message_settsigkey");
2725                 msg->tsigctx = l->tsigctx;
2726                 l->tsigctx = NULL;
2727                 if (l->msgcounter != 0)
2728                         msg->tcp_continuation = 1;
2729                 l->msgcounter++;
2730         }
2731
2732         debug("before parse starts");
2733         parseflags = DNS_MESSAGEPARSE_PRESERVEORDER;
2734 #ifdef DIG_SIGCHASE
2735         if (!l->sigchase) {
2736                 do_sigchase = ISC_FALSE;
2737         } else {
2738                 parseflags = 0;
2739                 do_sigchase = ISC_TRUE;
2740         }
2741 #endif
2742         if (l->besteffort) {
2743                 parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
2744                 parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
2745         }
2746         result = dns_message_parse(msg, b, parseflags);
2747         if (result == DNS_R_RECOVERABLE) {
2748                 printf(";; Warning: Message parser reports malformed "
2749                        "message packet.\n");
2750                 result = ISC_R_SUCCESS;
2751         }
2752         if (result != ISC_R_SUCCESS) {
2753                 printf(";; Got bad packet: %s\n", isc_result_totext(result));
2754                 hex_dump(b);
2755                 query->waiting_connect = ISC_FALSE;
2756                 dns_message_destroy(&msg);
2757                 isc_event_free(&event);
2758                 clear_query(query);
2759                 cancel_lookup(l);
2760                 check_next_lookup(l);
2761                 UNLOCK_LOOKUP;
2762                 return;
2763         }
2764         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0
2765             && !l->ignore && !l->tcp_mode) {
2766                 printf(";; Truncated, retrying in TCP mode.\n");
2767                 n = requeue_lookup(l, ISC_TRUE);
2768                 n->tcp_mode = ISC_TRUE;
2769                 n->origin = query->lookup->origin;
2770                 dns_message_destroy(&msg);
2771                 isc_event_free(&event);
2772                 clear_query(query);
2773                 cancel_lookup(l);
2774                 check_next_lookup(l);
2775                 UNLOCK_LOOKUP;
2776                 return;
2777         }                       
2778         if (msg->rcode == dns_rcode_servfail && !l->servfail_stops) {
2779                 dig_query_t *next = ISC_LIST_NEXT(query, link);
2780                 if (l->current_query == query)
2781                         l->current_query = NULL;
2782                 if (next != NULL) {
2783                         debug("sending query %p\n", next);
2784                         if (l->tcp_mode)
2785                                 send_tcp_connect(next);
2786                         else
2787                                 send_udp(next);
2788                 }
2789                 /*
2790                  * If our query is at the head of the list and there
2791                  * is no next, we're the only one left, so fall
2792                  * through to print the message.
2793                  */
2794                 if ((ISC_LIST_HEAD(l->q) != query) ||
2795                     (ISC_LIST_NEXT(query, link) != NULL)) {
2796                         printf(";; Got SERVFAIL reply from %s, "
2797                                "trying next server\n",
2798                                query->servname);
2799                         clear_query(query);
2800                         check_next_lookup(l);
2801                         dns_message_destroy(&msg);
2802                         isc_event_free(&event);
2803                         UNLOCK_LOOKUP;
2804                         return;
2805                 }
2806         }
2807
2808         if (key != NULL) {
2809                 result = dns_tsig_verify(&query->recvbuf, msg, NULL, NULL);
2810                 if (result != ISC_R_SUCCESS) {
2811                         printf(";; Couldn't verify signature: %s\n",
2812                                isc_result_totext(result));
2813                         validated = ISC_FALSE;
2814                 }
2815                 l->tsigctx = msg->tsigctx;
2816                 msg->tsigctx = NULL;
2817                 if (l->querysig != NULL) {
2818                         debug("freeing querysig buffer %p", l->querysig);
2819                         isc_buffer_free(&l->querysig);
2820                 }
2821                 result = dns_message_getquerytsig(msg, mctx, &l->querysig);
2822                 check_result(result,"dns_message_getquerytsig");
2823         }
2824
2825         debug("after parse");
2826         if (l->doing_xfr && l->xfr_q == NULL) {
2827                 l->xfr_q = query;
2828                 /*
2829                  * Once we are in the XFR message, increase
2830                  * the timeout to much longer, so brief network
2831                  * outages won't cause the XFR to abort
2832                  */
2833                 if (timeout != INT_MAX && l->timer != NULL) {
2834                         unsigned int local_timeout;
2835
2836                         if (timeout == 0) {
2837                                 if (l->tcp_mode)
2838                                         local_timeout = TCP_TIMEOUT * 4;
2839                                 else
2840                                         local_timeout = UDP_TIMEOUT * 4;
2841                         } else {
2842                                 if (timeout < (INT_MAX / 4))
2843                                         local_timeout = timeout * 4;
2844                                 else
2845                                         local_timeout = INT_MAX;
2846                         }
2847                         debug("have local timeout of %d", local_timeout);
2848                         isc_interval_set(&l->interval, local_timeout, 0);
2849                         result = isc_timer_reset(l->timer,
2850                                                  isc_timertype_once,
2851                                                  NULL,
2852                                                  &l->interval,
2853                                                  ISC_FALSE);
2854                         check_result(result, "isc_timer_reset");
2855                 }
2856         }
2857
2858         if (!l->doing_xfr || l->xfr_q == query) {
2859                 if (msg->rcode != dns_rcode_noerror && l->origin != NULL) {
2860                         if (!next_origin(msg, query)) {
2861                                 printmessage(query, msg, ISC_TRUE);
2862                                 received(b->used, &sevent->address, query);
2863                         }
2864                 } else if (!l->trace && !l->ns_search_only) {
2865 #ifdef DIG_SIGCHASE
2866                         if (!do_sigchase)
2867 #endif
2868                                 printmessage(query, msg, ISC_TRUE);
2869                 } else if (l->trace) {
2870                         int n = 0;
2871                         int count = msg->counts[DNS_SECTION_ANSWER];
2872
2873                         debug("in TRACE code");
2874                         if (!l->ns_search_only)
2875                                 printmessage(query, msg, ISC_TRUE);
2876
2877                         l->rdtype = l->qrdtype;
2878                         if (l->trace_root || (l->ns_search_only && count > 0)) {
2879                                 if (!l->trace_root)
2880                                         l->rdtype = dns_rdatatype_soa;
2881                                 n = followup_lookup(msg, query,
2882                                                     DNS_SECTION_ANSWER);
2883                                 l->trace_root = ISC_FALSE;
2884                         } else if (count == 0)
2885                                 n = followup_lookup(msg, query,
2886                                                     DNS_SECTION_AUTHORITY);
2887                         if (n == 0)
2888                                 docancel = ISC_TRUE;
2889                 } else {
2890                         debug("in NSSEARCH code");
2891
2892                         if (l->trace_root) {
2893                                 /*
2894                                  * This is the initial NS query.
2895                                  */
2896                                 int n;
2897
2898                                 l->rdtype = dns_rdatatype_soa;
2899                                 n = followup_lookup(msg, query,
2900                                                     DNS_SECTION_ANSWER);
2901                                 if (n == 0)
2902                                         docancel = ISC_TRUE;
2903                                 l->trace_root = ISC_FALSE;
2904                         } else
2905 #ifdef DIG_SIGCHASE
2906                                 if (!do_sigchase)
2907 #endif
2908                                 printmessage(query, msg, ISC_TRUE);
2909                 }
2910 #ifdef DIG_SIGCHASE
2911                 if (do_sigchase) {
2912                         chase_msg = isc_mem_allocate(mctx,
2913                                                      sizeof(dig_message_t));
2914                         if (chase_msg == NULL) {
2915                                 fatal("Memory allocation failure in %s:%d",
2916                                       __FILE__, __LINE__);
2917                         }
2918                         ISC_LIST_INITANDAPPEND(chase_message_list, chase_msg,
2919                                                link);
2920                         if (dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
2921                                                &msg_temp) != ISC_R_SUCCESS) {
2922                                 fatal("dns_message_create in %s:%d",
2923                                       __FILE__, __LINE__);
2924                         }
2925
2926                         isc_buffer_usedregion(b, &r);
2927                         result = isc_buffer_allocate(mctx, &buf, r.length);
2928         
2929                         check_result(result, "isc_buffer_allocate");
2930                         result =  isc_buffer_copyregion(buf, &r);
2931                         check_result(result, "isc_buffer_copyregion");
2932         
2933                         result =  dns_message_parse(msg_temp, buf, 0);
2934
2935                         isc_buffer_free(&buf);
2936                         chase_msg->msg = msg_temp;
2937
2938                         chase_msg2 = isc_mem_allocate(mctx,
2939                                                       sizeof(dig_message_t));
2940                         if (chase_msg2 == NULL) {
2941                                 fatal("Memory allocation failure in %s:%d",
2942                                       __FILE__, __LINE__);
2943                         }
2944                         ISC_LIST_INITANDAPPEND(chase_message_list2, chase_msg2,
2945                                                link);
2946                         chase_msg2->msg = msg;
2947                 }
2948 #endif
2949         
2950         }
2951
2952 #ifdef DIG_SIGCHASE
2953         if (l->sigchase && ISC_LIST_EMPTY(lookup_list)) {
2954                 sigchase(msg_temp);
2955         }
2956 #endif
2957
2958         if (l->pending)
2959                 debug("still pending.");
2960         if (l->doing_xfr) {
2961                 if (query != l->xfr_q) {
2962                         dns_message_destroy(&msg);
2963                         isc_event_free(&event);
2964                         query->waiting_connect = ISC_FALSE;
2965                         UNLOCK_LOOKUP;
2966                         return;
2967                 }
2968                 if (!docancel)
2969                         docancel = check_for_more_data(query, msg, sevent);
2970                 if (docancel) {
2971                         dns_message_destroy(&msg);
2972                         clear_query(query);
2973                         cancel_lookup(l);
2974                         check_next_lookup(l);
2975                 }
2976         } else {
2977
2978                 if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
2979
2980 #ifdef DIG_SIGCHASE
2981                         if (!l->sigchase)
2982 #endif
2983                                 received(b->used, &sevent->address, query);
2984                 }
2985
2986                 if (!query->lookup->ns_search_only)
2987                         query->lookup->pending = ISC_FALSE;
2988                 if (!query->lookup->ns_search_only ||
2989                     query->lookup->trace_root || docancel) {
2990 #ifdef DIG_SIGCHASE
2991                         if (!do_sigchase)
2992 #endif
2993                                 dns_message_destroy(&msg);
2994
2995                         cancel_lookup(l);
2996                 }
2997                 clear_query(query);
2998                 check_next_lookup(l);
2999         }
3000         if (msg != NULL) {
3001 #ifdef DIG_SIGCHASE
3002                 if (do_sigchase)
3003                         msg = NULL;
3004                 else
3005 #endif
3006                         dns_message_destroy(&msg);
3007         }
3008         isc_event_free(&event);
3009         UNLOCK_LOOKUP;
3010 }
3011
3012 /*
3013  * Turn a name into an address, using system-supplied routines.  This is
3014  * used in looking up server names, etc... and needs to use system-supplied
3015  * routines, since they may be using a non-DNS system for these lookups.
3016  */
3017 void
3018 get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
3019         int count;
3020         isc_result_t result;
3021
3022         isc_app_block();
3023         result = bind9_getaddresses(host, port, sockaddr, 1, &count);
3024         isc_app_unblock();
3025         if (result != ISC_R_SUCCESS)
3026                 fatal("couldn't get address for '%s': %s",
3027                       host, isc_result_totext(result));
3028         INSIST(count == 1);
3029 }
3030
3031 /*
3032  * Initiate either a TCP or UDP lookup
3033  */
3034 void
3035 do_lookup(dig_lookup_t *lookup) {
3036
3037         REQUIRE(lookup != NULL);
3038
3039         debug("do_lookup()");
3040         lookup->pending = ISC_TRUE;
3041         if (lookup->tcp_mode)
3042                 send_tcp_connect(ISC_LIST_HEAD(lookup->q));
3043         else
3044                 send_udp(ISC_LIST_HEAD(lookup->q));
3045 }
3046
3047 /*
3048  * Start everything in action upon task startup.
3049  */
3050 void
3051 onrun_callback(isc_task_t *task, isc_event_t *event) {
3052         UNUSED(task);
3053
3054         isc_event_free(&event);
3055         LOCK_LOOKUP;
3056         start_lookup();
3057         UNLOCK_LOOKUP;
3058 }
3059
3060 /*
3061  * Make everything on the lookup queue go away.  Mainly used by the
3062  * SIGINT handler.
3063  */
3064 void
3065 cancel_all(void) {
3066         dig_lookup_t *l, *n;
3067         dig_query_t *q, *nq;
3068
3069         debug("cancel_all()");
3070
3071         LOCK_LOOKUP;
3072         if (free_now) {
3073                 UNLOCK_LOOKUP;
3074                 return;
3075         }
3076         cancel_now = ISC_TRUE;
3077         if (current_lookup != NULL) {
3078                 if (current_lookup->timer != NULL)
3079                         isc_timer_detach(&current_lookup->timer);
3080                 q = ISC_LIST_HEAD(current_lookup->q);
3081                 while (q != NULL) {
3082                         debug("cancelling query %p, belonging to %p",
3083                               q, current_lookup);
3084                         nq = ISC_LIST_NEXT(q, link);
3085                         if (q->sock != NULL) {
3086                                 isc_socket_cancel(q->sock, NULL,
3087                                                   ISC_SOCKCANCEL_ALL);
3088                         } else {
3089                                 clear_query(q);
3090                         }
3091                         q = nq;
3092                 }
3093         }
3094         l = ISC_LIST_HEAD(lookup_list);
3095         while (l != NULL) {
3096                 n = ISC_LIST_NEXT(l, link);
3097                 ISC_LIST_DEQUEUE(lookup_list, l, link);
3098                 try_clear_lookup(l);
3099                 l = n;
3100         }
3101         UNLOCK_LOOKUP;
3102 }
3103
3104 /*
3105  * Destroy all of the libs we are using, and get everything ready for a
3106  * clean shutdown.
3107  */
3108 void
3109 destroy_libs(void) {
3110 #ifdef DIG_SIGCHASE
3111         void * ptr;
3112         dig_message_t *chase_msg;
3113 #endif
3114
3115         debug("destroy_libs()");
3116         if (global_task != NULL) {
3117                 debug("freeing task");
3118                 isc_task_detach(&global_task);
3119         }
3120         /*
3121          * The taskmgr_destroy() call blocks until all events are cleared
3122          * from the task.
3123          */
3124         if (taskmgr != NULL) {
3125                 debug("freeing taskmgr");
3126                 isc_taskmgr_destroy(&taskmgr);
3127         }
3128         LOCK_LOOKUP;
3129         REQUIRE(sockcount == 0);
3130         REQUIRE(recvcount == 0);
3131         REQUIRE(sendcount == 0);
3132
3133         INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
3134         INSIST(current_lookup == NULL);
3135         INSIST(!free_now);
3136
3137         free_now = ISC_TRUE;
3138
3139         lwres_conf_clear(lwctx);
3140         lwres_context_destroy(&lwctx);
3141
3142         flush_server_list();
3143
3144         clear_searchlist();
3145         if (commctx != NULL) {
3146                 debug("freeing commctx");
3147                 isc_mempool_destroy(&commctx);
3148         }
3149         if (socketmgr != NULL) {
3150                 debug("freeing socketmgr");
3151                 isc_socketmgr_destroy(&socketmgr);
3152         }
3153         if (timermgr != NULL) {
3154                 debug("freeing timermgr");
3155                 isc_timermgr_destroy(&timermgr);
3156         }
3157         if (key != NULL) {
3158                 debug("freeing key %p", key);
3159                 dns_tsigkey_detach(&key);
3160         }
3161         if (namebuf != NULL)
3162                 isc_buffer_free(&namebuf);
3163
3164         if (is_dst_up) {
3165                 debug("destroy DST lib");
3166                 dst_lib_destroy();
3167                 is_dst_up = ISC_FALSE;
3168         }
3169         if (entp != NULL) {
3170                 debug("detach from entropy");
3171                 isc_entropy_detach(&entp);
3172         }
3173
3174         UNLOCK_LOOKUP;
3175         DESTROYLOCK(&lookup_lock);
3176 #ifdef DIG_SIGCHASE
3177
3178         debug("Destroy the messages kept for sigchase");
3179         /* Destroy the messages kept for sigchase */
3180         chase_msg = ISC_LIST_HEAD(chase_message_list);
3181
3182         while (chase_msg != NULL) {
3183                 INSIST(chase_msg->msg != NULL);
3184                 dns_message_destroy(&(chase_msg->msg));
3185                 ptr = chase_msg;
3186                 chase_msg = ISC_LIST_NEXT(chase_msg, link);
3187                 isc_mem_free(mctx, ptr);
3188         }
3189
3190         chase_msg = ISC_LIST_HEAD(chase_message_list2);
3191
3192         while (chase_msg != NULL) {
3193                 INSIST(chase_msg->msg != NULL);
3194                 dns_message_destroy(&(chase_msg->msg));
3195                 ptr = chase_msg;
3196                 chase_msg = ISC_LIST_NEXT(chase_msg, link);
3197                 isc_mem_free(mctx, ptr);
3198         }
3199         if (dns_name_dynamic(&chase_name))
3200                 free_name(&chase_name, mctx);
3201 #if DIG_SIGCHASE_TD
3202         if (dns_name_dynamic(&chase_current_name))
3203                 free_name(&chase_current_name, mctx);
3204         if (dns_name_dynamic(&chase_authority_name))
3205                 free_name(&chase_authority_name, mctx);
3206 #endif
3207 #if DIG_SIGCHASE_BU
3208         if (dns_name_dynamic(&chase_signame))
3209                 free_name(&chase_signame, mctx);
3210 #endif
3211
3212         debug("Destroy memory");
3213         
3214 #endif
3215         if (memdebugging != 0)
3216                 isc_mem_stats(mctx, stderr);
3217         if (mctx != NULL)
3218                 isc_mem_destroy(&mctx);
3219 }
3220
3221
3222
3223
3224 #ifdef DIG_SIGCHASE
3225 void
3226 print_type(dns_rdatatype_t type)
3227 {
3228         isc_buffer_t * b = NULL;
3229         isc_result_t result;
3230         isc_region_t r;
3231
3232         result = isc_buffer_allocate(mctx, &b, 4000);
3233         check_result(result, "isc_buffer_allocate");
3234
3235         result = dns_rdatatype_totext(type, b);
3236         check_result(result, "print_type");
3237
3238         isc_buffer_usedregion(b, &r);
3239         r.base[r.length] = '\0';
3240
3241         printf("%s", r.base);
3242
3243         isc_buffer_free(&b);
3244 }
3245
3246 void
3247 dump_database_section(dns_message_t *msg, int section)
3248 {
3249         dns_name_t *msg_name=NULL;
3250
3251         dns_rdataset_t *rdataset;
3252
3253         do {
3254                 dns_message_currentname(msg, section, &msg_name);
3255
3256                 for (rdataset = ISC_LIST_HEAD(msg_name->list); rdataset != NULL;
3257                      rdataset = ISC_LIST_NEXT(rdataset, link)) {        
3258                         dns_name_print(msg_name, stdout);
3259                         printf("\n");
3260                         print_rdataset(msg_name, rdataset, mctx);
3261                         printf("end\n");
3262                 }
3263                 msg_name = NULL;
3264         } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
3265 }
3266
3267 void
3268 dump_database(void) {
3269         dig_message_t * msg;
3270
3271         for (msg = ISC_LIST_HEAD(chase_message_list);  msg != NULL;
3272              msg = ISC_LIST_NEXT(msg, link)) {
3273                 if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
3274                     == ISC_R_SUCCESS)
3275                         dump_database_section(msg->msg, DNS_SECTION_ANSWER);
3276
3277                 if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
3278                     == ISC_R_SUCCESS)
3279                         dump_database_section(msg->msg, DNS_SECTION_AUTHORITY);
3280         
3281                 if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
3282                     == ISC_R_SUCCESS)
3283                         dump_database_section(msg->msg, DNS_SECTION_ADDITIONAL);
3284         }
3285 }
3286
3287
3288 dns_rdataset_t *
3289 search_type(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) {
3290         dns_rdataset_t *rdataset;
3291         dns_rdata_sig_t siginfo;
3292         dns_rdata_t sigrdata;
3293         isc_result_t result;
3294
3295         for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
3296              rdataset = ISC_LIST_NEXT(rdataset, link)) {
3297                 if (type == dns_rdatatype_any) {
3298                         if (rdataset->type != dns_rdatatype_rrsig)
3299                                 return (rdataset);
3300                 } else if ((type == dns_rdatatype_rrsig) &&
3301                            (rdataset->type == dns_rdatatype_rrsig)) {
3302                         dns_rdata_init(&sigrdata);
3303                         result = dns_rdataset_first(rdataset);
3304                         check_result(result, "empty rdataset");
3305                         dns_rdataset_current(rdataset, &sigrdata);
3306                         result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
3307                         check_result(result, "sigrdata tostruct siginfo");
3308
3309                         if ((siginfo.covered == covers) ||
3310                             (covers == dns_rdatatype_any)) {
3311                                 dns_rdata_reset(&sigrdata);
3312                                 dns_rdata_freestruct(&siginfo); 
3313                                 return (rdataset);
3314                         }
3315                         dns_rdata_reset(&sigrdata);
3316                         dns_rdata_freestruct(&siginfo);
3317                 } else if (rdataset->type == type)
3318                         return (rdataset);
3319         }
3320         return (NULL);
3321 }
3322
3323 dns_rdataset_t *
3324 chase_scanname_section(dns_message_t *msg, dns_name_t *name,
3325                        dns_rdatatype_t type, dns_rdatatype_t covers,
3326                        int section)
3327 {
3328         dns_rdataset_t *rdataset;
3329         dns_name_t *msg_name = NULL;
3330
3331         do {
3332                 dns_message_currentname(msg, section, &msg_name);
3333                 if (dns_name_compare(msg_name, name) == 0) {
3334                         rdataset = search_type(msg_name, type, covers);
3335                         if (rdataset != NULL)
3336                                 return (rdataset);
3337                 }
3338                 msg_name = NULL;
3339         } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
3340
3341         return (NULL);
3342 }
3343
3344
3345 dns_rdataset_t *
3346 chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers)
3347 {
3348         dns_rdataset_t *rdataset = NULL;
3349         dig_message_t * msg;
3350
3351         for (msg = ISC_LIST_HEAD(chase_message_list2);  msg != NULL;
3352              msg = ISC_LIST_NEXT(msg, link)) {
3353                 if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
3354                     == ISC_R_SUCCESS)
3355                         rdataset = chase_scanname_section(msg->msg, name,
3356                                                           type, covers,
3357                                                           DNS_SECTION_ANSWER);
3358                         if (rdataset != NULL)
3359                                 return (rdataset);
3360                 if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
3361                     == ISC_R_SUCCESS)
3362                         rdataset =
3363                                 chase_scanname_section(msg->msg, name,
3364                                                        type, covers,
3365                                                        DNS_SECTION_AUTHORITY);
3366                         if (rdataset != NULL)
3367                                 return (rdataset);
3368                 if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
3369                     == ISC_R_SUCCESS)
3370                         rdataset =
3371                                 chase_scanname_section(msg->msg, name, type,
3372                                                        covers,
3373                                                        DNS_SECTION_ADDITIONAL);
3374                         if (rdataset != NULL)
3375                                 return (rdataset);
3376         }
3377
3378         return (NULL);
3379 }
3380
3381 dns_rdataset_t *
3382 sigchase_scanname(dns_rdatatype_t type, dns_rdatatype_t covers,
3383                   isc_boolean_t * lookedup, dns_name_t *rdata_name)
3384 {
3385         dig_lookup_t *lookup;
3386         isc_buffer_t *b = NULL;
3387         isc_region_t r;
3388         isc_result_t result;
3389         dns_rdataset_t * temp;
3390         dns_rdatatype_t querytype;
3391
3392         temp = chase_scanname(rdata_name, type, covers);
3393         if (temp != NULL)
3394                 return (temp);
3395
3396         if (*lookedup == ISC_TRUE)
3397                 return (NULL);
3398
3399         lookup = clone_lookup(current_lookup, ISC_TRUE);
3400         lookup->trace_root = ISC_FALSE;
3401         lookup->new_search = ISC_TRUE;
3402
3403         result = isc_buffer_allocate(mctx, &b, BUFSIZE);
3404         check_result(result, "isc_buffer_allocate");
3405         result = dns_name_totext(rdata_name, ISC_FALSE, b);
3406         check_result(result, "dns_name_totext");
3407         isc_buffer_usedregion(b, &r);
3408         r.base[r.length] = '\0';
3409         strcpy(lookup->textname, (char*)r.base);
3410         isc_buffer_free(&b);
3411
3412         if (type ==  dns_rdatatype_rrsig)
3413                 querytype = covers;
3414         else
3415                 querytype = type;
3416
3417         if (querytype == 0 || querytype == 255) {
3418                 printf("Error in the queried type: %d\n", querytype);
3419                 return (NULL);
3420         }
3421
3422         lookup->rdtype = querytype;
3423         lookup->rdtypeset = ISC_TRUE;
3424         lookup->qrdtype = querytype;
3425         *lookedup = ISC_TRUE;
3426
3427         ISC_LIST_APPEND(lookup_list, lookup, link);
3428         printf("\n\nLaunch a query to find a RRset of type ");
3429         print_type(type);
3430         printf(" for zone: %s\n", lookup->textname);
3431         return (NULL);
3432 }
3433
3434 void
3435 insert_trustedkey(dst_key_t * key)
3436 {
3437         if (key == NULL)
3438                 return;
3439         if (tk_list.nb_tk >= MAX_TRUSTED_KEY)
3440                 return;
3441
3442         tk_list.key[tk_list.nb_tk++] = key;
3443         return;
3444 }
3445
3446 void
3447 clean_trustedkey()
3448 {
3449         int i = 0;
3450
3451         for (i= 0; i < MAX_TRUSTED_KEY; i++) {
3452                 if (tk_list.key[i] != NULL) {
3453                         dst_key_free(&tk_list.key[i]);
3454                         tk_list.key[i] = NULL;
3455                 } else
3456                         break;
3457         }
3458         tk_list.nb_tk = 0;
3459         return;
3460 }
3461
3462 char alphnum[] =
3463         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
3464
3465 isc_result_t
3466 removetmpkey(isc_mem_t *mctx, const char *file)
3467 {
3468         char *tempnamekey = NULL;
3469         int tempnamekeylen;
3470         isc_result_t result;
3471
3472         tempnamekeylen = strlen(file)+10;
3473
3474         tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
3475         if (tempnamekey == NULL)
3476                 return (ISC_R_NOMEMORY);
3477
3478         memset(tempnamekey, 0, tempnamekeylen);
3479
3480         strcat(tempnamekey, file);
3481         strcat(tempnamekey,".key");
3482         isc_file_remove(tempnamekey);
3483
3484         result = isc_file_remove(tempnamekey);
3485         isc_mem_free(mctx, tempnamekey);
3486         return (result);
3487 }
3488
3489 isc_result_t
3490 opentmpkey(isc_mem_t *mctx, const char *file, char **tempp, FILE **fp) {
3491         FILE *f = NULL;
3492         isc_result_t result;
3493         char *tempname = NULL;
3494         char *tempnamekey = NULL;
3495         int tempnamelen;
3496         int tempnamekeylen;
3497         char *x;
3498         char *cp;
3499         isc_uint32_t which;
3500
3501         while (1) {
3502                 tempnamelen = strlen(file) + 20;
3503                 tempname = isc_mem_allocate(mctx, tempnamelen);
3504                 if (tempname == NULL)
3505                         return (ISC_R_NOMEMORY);
3506                 memset(tempname, 0, tempnamelen);
3507
3508                 result = isc_file_mktemplate(file, tempname, tempnamelen);
3509                 if (result != ISC_R_SUCCESS)
3510                         goto cleanup;
3511
3512                 cp = tempname;
3513                 while (*cp != '\0')
3514                         cp++;
3515                 if (cp == tempname) {
3516                         isc_mem_free(mctx, tempname);
3517                         return (ISC_R_FAILURE);
3518                 }
3519         
3520                 x = cp--;
3521                 while (cp >= tempname && *cp == 'X') {
3522                         isc_random_get(&which);
3523                         *cp = alphnum[which % (sizeof(alphnum) - 1)];
3524                         x = cp--;
3525                 }
3526
3527                 tempnamekeylen = tempnamelen+5;
3528                 tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
3529                 if (tempnamekey == NULL)
3530                         return (ISC_R_NOMEMORY);
3531         
3532                 memset(tempnamekey, 0, tempnamekeylen);
3533                 strncpy(tempnamekey, tempname, tempnamelen);
3534                 strcat(tempnamekey ,".key");
3535
3536         
3537                 if (isc_file_exists(tempnamekey)) {
3538                         isc_mem_free(mctx, tempnamekey);
3539                         isc_mem_free(mctx, tempname);
3540                         continue;
3541                 }
3542
3543                 if ((f = fopen(tempnamekey, "w")) == NULL) {
3544                         printf("get_trusted_key(): trusted key not found %s\n",
3545                                tempnamekey);
3546                         return (ISC_R_FAILURE);
3547                 }
3548                 break;
3549         }
3550         isc_mem_free(mctx, tempnamekey);
3551         *tempp = tempname;
3552         *fp = f;
3553         return (ISC_R_SUCCESS);
3554
3555  cleanup:
3556         isc_mem_free(mctx, tempname);
3557         
3558         return (result);
3559 }
3560
3561
3562 isc_result_t
3563 get_trusted_key(isc_mem_t *mctx)
3564 {
3565         isc_result_t result;
3566         const char *filename = NULL;
3567         char *filetemp = NULL;
3568         char buf[1500];
3569         FILE *fp, *fptemp;
3570         dst_key_t *key = NULL;
3571
3572         result = isc_file_exists(trustedkey);
3573         if (result !=  ISC_TRUE) {
3574                 result = isc_file_exists("/etc/trusted-key.key");
3575                 if (result !=  ISC_TRUE) {
3576                         result = isc_file_exists("./trusted-key.key");
3577                         if (result !=  ISC_TRUE)
3578                                 return (ISC_R_FAILURE);
3579                         else
3580                                 filename = "./trusted-key.key";
3581                 } else
3582                         filename = "/etc/trusted-key.key";
3583         } else
3584                 filename = trustedkey;
3585
3586         if (filename == NULL) {
3587                 printf("No trusted key\n");
3588                 return (ISC_R_FAILURE);
3589         }
3590
3591         if ((fp = fopen(filename, "r")) == NULL) {
3592                 printf("get_trusted_key(): trusted key not found %s\n",
3593                        filename);
3594                 return (ISC_R_FAILURE);
3595         }
3596         while (fgets(buf, 1500, fp) != NULL) {
3597                 result = opentmpkey(mctx,"tmp_file", &filetemp, &fptemp);
3598                 if (result != ISC_R_SUCCESS) {
3599                         fclose(fp);
3600                         return (ISC_R_FAILURE);
3601                 }
3602                 if (fputs(buf, fptemp) < 0) {
3603                         fclose(fp);
3604                         fclose(fptemp);
3605                         return (ISC_R_FAILURE);
3606                 }
3607                 fclose(fptemp);
3608                 result = dst_key_fromnamedfile(filetemp, DST_TYPE_PUBLIC,
3609                                                mctx, &key);
3610                 removetmpkey(mctx, filetemp);
3611                 isc_mem_free(mctx, filetemp);
3612                 if (result !=  ISC_R_SUCCESS) {
3613                         fclose(fp);
3614                         return (ISC_R_FAILURE);
3615                 }
3616                 insert_trustedkey(key);
3617 #if 0
3618                 dst_key_tofile(key, DST_TYPE_PUBLIC,"/tmp");
3619 #endif
3620                 key = NULL;
3621         }
3622         return (ISC_R_SUCCESS);
3623 }
3624
3625
3626 static void
3627 nameFromString(const char *str, dns_name_t *p_ret) {
3628         size_t len = strlen(str);
3629         isc_result_t result;
3630         isc_buffer_t buffer;
3631         dns_fixedname_t fixedname;
3632
3633         REQUIRE(p_ret != NULL);
3634         REQUIRE(str != NULL);
3635
3636         isc_buffer_init(&buffer, str, len);
3637         isc_buffer_add(&buffer, len);
3638
3639         dns_fixedname_init(&fixedname);
3640         result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer,
3641                                    dns_rootname, ISC_TRUE, NULL);
3642         check_result(result, "nameFromString");
3643
3644         if (dns_name_dynamic(p_ret))
3645                 free_name(p_ret, mctx);
3646
3647         result = dns_name_dup(dns_fixedname_name(&fixedname), mctx, p_ret);
3648         check_result(result, "nameFromString");
3649 }
3650
3651
3652 #if DIG_SIGCHASE_TD
3653 isc_result_t
3654 prepare_lookup(dns_name_t *name)
3655 {
3656         isc_result_t result;
3657         dig_lookup_t *lookup = NULL;
3658         dig_server_t *s;
3659         void *ptr;
3660
3661         lookup = clone_lookup(current_lookup, ISC_TRUE);
3662         lookup->trace_root = ISC_FALSE;
3663         lookup->new_search = ISC_TRUE;
3664         lookup->trace_root_sigchase = ISC_FALSE;
3665
3666         strncpy(lookup->textname, lookup->textnamesigchase, MXNAME);
3667
3668         lookup->rdtype = lookup->rdtype_sigchase;
3669         lookup->rdtypeset = ISC_TRUE;
3670         lookup->qrdtype = lookup->qrdtype_sigchase;
3671
3672         s = ISC_LIST_HEAD(lookup->my_server_list);
3673         while (s != NULL) {
3674                 debug("freeing server %p belonging to %p",
3675                       s, lookup);
3676                 ptr = s;
3677                 s = ISC_LIST_NEXT(s, link);
3678                 ISC_LIST_DEQUEUE(lookup->my_server_list,
3679                                  (dig_server_t *)ptr, link);
3680                 isc_mem_free(mctx, ptr);
3681         }
3682
3683
3684         for (result = dns_rdataset_first(chase_nsrdataset);
3685              result == ISC_R_SUCCESS;
3686              result = dns_rdataset_next(chase_nsrdataset)) {
3687                 char namestr[DNS_NAME_FORMATSIZE];
3688                 dns_rdata_ns_t ns;
3689                 dns_rdata_t rdata = DNS_RDATA_INIT;
3690                 dig_server_t * srv = NULL;
3691 #define __FOLLOW_GLUE__
3692 #ifdef __FOLLOW_GLUE__
3693                 isc_buffer_t *b = NULL;
3694                 isc_result_t result;
3695                 isc_region_t r;
3696                 dns_rdataset_t *rdataset = NULL;
3697                 isc_boolean_t true = ISC_TRUE;
3698 #endif
3699
3700                 memset(namestr, 0, DNS_NAME_FORMATSIZE);
3701
3702                 dns_rdataset_current(chase_nsrdataset, &rdata);
3703
3704                 (void)dns_rdata_tostruct(&rdata, &ns, NULL);
3705
3706
3707
3708 #ifdef __FOLLOW_GLUE__
3709
3710                 result = advanced_rrsearch(&rdataset, &ns.name,
3711                                            dns_rdatatype_aaaa,
3712                                            dns_rdatatype_any, &true);
3713                 if (result == ISC_R_SUCCESS) {
3714                         for (result = dns_rdataset_first(rdataset);
3715                              result == ISC_R_SUCCESS;
3716                              result = dns_rdataset_next(rdataset)) {
3717                                 dns_rdata_t aaaa = DNS_RDATA_INIT;
3718                                 dns_rdataset_current(rdataset, &aaaa);
3719
3720                                 result = isc_buffer_allocate(mctx, &b, 80);
3721                                 check_result(result, "isc_buffer_allocate");
3722
3723                                 dns_rdata_totext(&aaaa, &ns.name, b);
3724                                 isc_buffer_usedregion(b, &r);
3725                                 r.base[r.length] = '\0';
3726                                 strncpy(namestr, (char*)r.base,
3727                                         DNS_NAME_FORMATSIZE);
3728                                 isc_buffer_free(&b);
3729                                 dns_rdata_reset(&aaaa);
3730
3731
3732                                 srv = make_server(namestr, namestr);
3733         
3734                                 ISC_LIST_APPEND(lookup->my_server_list,
3735                                                 srv, link);
3736                         }
3737                 }
3738
3739                 rdataset = NULL;
3740                 result = advanced_rrsearch(&rdataset, &ns.name, dns_rdatatype_a,
3741                                            dns_rdatatype_any, &true);
3742                 if (result == ISC_R_SUCCESS) {
3743                         for (result = dns_rdataset_first(rdataset);
3744                              result == ISC_R_SUCCESS;
3745                              result = dns_rdataset_next(rdataset)) {
3746                                 dns_rdata_t a = DNS_RDATA_INIT;
3747                                 dns_rdataset_current(rdataset, &a);
3748
3749                                 result = isc_buffer_allocate(mctx, &b, 80);
3750                                 check_result(result, "isc_buffer_allocate");
3751
3752                                 dns_rdata_totext(&a, &ns.name, b);
3753                                 isc_buffer_usedregion(b, &r);
3754                                 r.base[r.length] = '\0';
3755                                 strncpy(namestr, (char*)r.base,
3756                                         DNS_NAME_FORMATSIZE);
3757                                 isc_buffer_free(&b);
3758                                 dns_rdata_reset(&a);
3759                                 printf("ns name: %s\n", namestr);
3760
3761
3762                                 srv = make_server(namestr, namestr);
3763         
3764                                 ISC_LIST_APPEND(lookup->my_server_list,
3765                                                 srv, link);
3766                         }
3767                 }
3768 #else
3769
3770                 dns_name_format(&ns.name, namestr, sizeof(namestr));
3771                 printf("ns name: ");
3772                 dns_name_print(&ns.name, stdout);
3773                 printf("\n");
3774                 srv = make_server(namestr, namestr);
3775         
3776                 ISC_LIST_APPEND(lookup->my_server_list, srv, link);
3777
3778 #endif
3779                 dns_rdata_freestruct(&ns);
3780                 dns_rdata_reset(&rdata);
3781
3782         }
3783
3784         ISC_LIST_APPEND(lookup_list, lookup, link);
3785         printf("\nLaunch a query to find a RRset of type ");
3786         print_type(lookup->rdtype);
3787         printf(" for zone: %s", lookup->textname);
3788         printf(" with nameservers:");
3789         printf("\n");
3790         print_rdataset(name, chase_nsrdataset, mctx);
3791         return (ISC_R_SUCCESS);
3792 }
3793
3794
3795 isc_result_t
3796 child_of_zone(dns_name_t * name, dns_name_t * zone_name,
3797               dns_name_t * child_name)
3798 {
3799         dns_namereln_t name_reln;
3800         int orderp;
3801         unsigned int nlabelsp;
3802
3803         name_reln = dns_name_fullcompare(name, zone_name, &orderp, &nlabelsp);
3804         if (name_reln != dns_namereln_subdomain ||
3805             dns_name_countlabels(name) <= dns_name_countlabels(zone_name) + 1) {
3806                 printf("\n;; ERROR : ");
3807                 dns_name_print(name, stdout);
3808                 printf(" is not a subdomain of: ");
3809                 dns_name_print(zone_name, stdout);
3810                 printf(" FAILED\n\n");
3811                 return (ISC_R_FAILURE);
3812         }
3813
3814         dns_name_getlabelsequence(name,
3815                                   dns_name_countlabels(name) -
3816                                   dns_name_countlabels(zone_name) -1,
3817                                   dns_name_countlabels(zone_name) +1,
3818                                   child_name);
3819         return (ISC_R_SUCCESS);
3820 }
3821
3822 isc_result_t
3823 grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t  *sigrdataset)
3824 {
3825         isc_result_t result;
3826         dns_rdata_t sigrdata;
3827         dns_rdata_sig_t siginfo;
3828
3829         result = dns_rdataset_first(sigrdataset);
3830         check_result(result, "empty RRSIG dataset");
3831         dns_rdata_init(&sigrdata);
3832
3833         do {
3834                 dns_rdataset_current(sigrdataset, &sigrdata);
3835
3836                 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
3837                 check_result(result, "sigrdata tostruct siginfo");
3838
3839                 if (dns_name_compare(&siginfo.signer, zone_name) == 0) {
3840                         dns_rdata_freestruct(&siginfo);
3841                         dns_rdata_reset(&sigrdata);
3842                         return (ISC_R_SUCCESS);
3843                 }
3844
3845                 dns_rdata_freestruct(&siginfo);
3846
3847         } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
3848
3849         dns_rdata_reset(&sigrdata);
3850
3851         return (ISC_R_FAILURE);
3852 }
3853
3854
3855 isc_result_t
3856 initialization(dns_name_t *name)
3857 {
3858         isc_result_t   result;
3859         isc_boolean_t  true = ISC_TRUE;
3860
3861         chase_nsrdataset = NULL;
3862         result = advanced_rrsearch(&chase_nsrdataset, name, dns_rdatatype_ns,
3863                                    dns_rdatatype_any, &true);
3864         if (result != ISC_R_SUCCESS) {
3865                 printf("\n;; NS RRset is missing to continue validation:"
3866                        " FAILED\n\n");
3867                 return (ISC_R_FAILURE);
3868         }
3869         INSIST(chase_nsrdataset != NULL);
3870         prepare_lookup(name);
3871
3872         dup_name(name, &chase_current_name, mctx);
3873
3874         return (ISC_R_SUCCESS);
3875 }
3876 #endif
3877
3878 void
3879 print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset, isc_mem_t *mctx)
3880 {
3881         isc_buffer_t *b = NULL;
3882         isc_result_t result;
3883         isc_region_t r;
3884
3885         result = isc_buffer_allocate(mctx, &b, 9000);
3886         check_result(result, "isc_buffer_allocate");
3887
3888         printrdataset(name, rdataset, b);
3889
3890         isc_buffer_usedregion(b, &r);
3891         r.base[r.length] = '\0';
3892
3893
3894         printf("%s\n", r.base);
3895
3896         isc_buffer_free(&b);
3897 }
3898
3899
3900 void
3901 dup_name(dns_name_t *source, dns_name_t *target, isc_mem_t *mctx) {
3902         isc_result_t result;
3903
3904         if (dns_name_dynamic(target))
3905                 free_name(target, mctx);
3906         result = dns_name_dup(source, mctx, target);
3907         check_result(result, "dns_name_dup");
3908 }
3909
3910 void
3911 free_name(dns_name_t *name, isc_mem_t *mctx) {
3912         dns_name_free(name, mctx);
3913         dns_name_init(name, NULL);
3914 }
3915
3916 /*
3917  *
3918  * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter
3919  * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key
3920  *                      and the RRset is valid
3921  * return ISC_R_NOTFOUND if not contains trusted key
3922                         or if the RRset isn't valid
3923  * return ISC_R_FAILURE if problem
3924  *
3925  */
3926 isc_result_t
3927 contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset,
3928                      dns_rdataset_t *sigrdataset,
3929                      isc_mem_t *mctx)
3930 {
3931         isc_result_t result;
3932         dns_rdata_t rdata;
3933         dst_key_t *trustedKey = NULL;
3934         dst_key_t *dnsseckey = NULL;
3935         int i;
3936
3937         if (name == NULL || rdataset == NULL)
3938                 return (ISC_R_FAILURE);
3939
3940         result = dns_rdataset_first(rdataset);
3941         check_result(result, "empty rdataset");
3942         dns_rdata_init(&rdata);
3943
3944         do {
3945                 dns_rdataset_current(rdataset, &rdata);
3946                 INSIST(rdata.type == dns_rdatatype_dnskey);
3947         
3948                 result = dns_dnssec_keyfromrdata(name, &rdata,
3949                                                  mctx, &dnsseckey);
3950                 check_result(result, "dns_dnssec_keyfromrdata");
3951
3952
3953                 for (i = 0; i < tk_list.nb_tk; i++) {
3954                         if (dst_key_compare(tk_list.key[i], dnsseckey)
3955                             == ISC_TRUE) {
3956                                 dns_rdata_reset(&rdata);
3957         
3958                                 printf(";; Ok, find a Trusted Key in the "
3959                                        "DNSKEY RRset: %d\n",
3960                                        dst_key_id(dnsseckey));
3961                                 if (sigchase_verify_sig_key(name, rdataset,
3962                                                             dnsseckey,
3963                                                             sigrdataset,
3964                                                             mctx)
3965                                     == ISC_R_SUCCESS) {
3966                                         dst_key_free(&dnsseckey);
3967                                         dnsseckey = NULL;
3968                                         return (ISC_R_SUCCESS);
3969                                 }
3970                         }
3971                 }
3972
3973                 dns_rdata_reset(&rdata);
3974                 if (dnsseckey != NULL)
3975                         dst_key_free(&dnsseckey);
3976         } while (dns_rdataset_next(rdataset) == ISC_R_SUCCESS);
3977
3978         if (trustedKey != NULL)
3979                 dst_key_free(&trustedKey);
3980         trustedKey = NULL;
3981
3982         return (ISC_R_NOTFOUND);
3983 }
3984
3985 isc_result_t
3986 sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset,
3987                     dns_rdataset_t *keyrdataset,
3988                     dns_rdataset_t *sigrdataset,
3989                     isc_mem_t *mctx)
3990 {
3991         isc_result_t result;
3992         dns_rdata_t keyrdata;
3993         dst_key_t *dnsseckey = NULL;
3994
3995         result = dns_rdataset_first(keyrdataset);
3996         check_result(result, "empty DNSKEY dataset");
3997         dns_rdata_init(&keyrdata);
3998
3999         do {
4000                 dns_rdataset_current(keyrdataset, &keyrdata);
4001                 INSIST(keyrdata.type == dns_rdatatype_dnskey);
4002         
4003                 result = dns_dnssec_keyfromrdata(name, &keyrdata,
4004                                                  mctx, &dnsseckey);
4005                 check_result(result, "dns_dnssec_keyfromrdata");
4006
4007                 result = sigchase_verify_sig_key(name, rdataset, dnsseckey,
4008                                                  sigrdataset, mctx);
4009                 if (result == ISC_R_SUCCESS) {
4010                         dns_rdata_reset(&keyrdata);
4011                         dst_key_free(&dnsseckey);
4012                         return (ISC_R_SUCCESS);
4013                 }
4014                 dst_key_free(&dnsseckey);
4015         } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
4016
4017         dns_rdata_reset(&keyrdata);
4018
4019         return (ISC_R_NOTFOUND);
4020 }
4021
4022 isc_result_t
4023 sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset,
4024                         dst_key_t *dnsseckey, dns_rdataset_t *sigrdataset,
4025                         isc_mem_t *mctx)
4026 {
4027         isc_result_t result;
4028         dns_rdata_t sigrdata;
4029         dns_rdata_sig_t siginfo;
4030
4031         result = dns_rdataset_first(sigrdataset);
4032         check_result(result, "empty RRSIG dataset");
4033         dns_rdata_init(&sigrdata);
4034
4035         do {
4036                 dns_rdataset_current(sigrdataset, &sigrdata);
4037
4038                 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4039                 check_result(result, "sigrdata tostruct siginfo");
4040
4041                 /*
4042                  * Test if the id of the DNSKEY is
4043                  * the id of the DNSKEY signer's
4044                  */
4045                 if (siginfo.keyid == dst_key_id(dnsseckey)) {
4046
4047                         result = dns_rdataset_first(rdataset);
4048                         check_result(result, "empty DS dataset");
4049
4050                         result = dns_dnssec_verify(name, rdataset, dnsseckey,
4051                                                    ISC_FALSE, mctx, &sigrdata);
4052
4053                         printf(";; VERIFYING ");
4054                         print_type(rdataset->type);
4055                         printf(" RRset for ");
4056                         dns_name_print(name, stdout);
4057                         printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey),
4058                                isc_result_totext(result));
4059
4060                         if (result == ISC_R_SUCCESS) {
4061                                 dns_rdata_reset(&sigrdata);
4062                                 return (result);
4063                         }
4064                 }
4065                 dns_rdata_freestruct(&siginfo);
4066
4067         } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
4068
4069         dns_rdata_reset(&sigrdata);
4070
4071         return (ISC_R_NOTFOUND);
4072 }
4073
4074
4075 isc_result_t
4076 sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset,
4077                    dns_rdataset_t *dsrdataset, isc_mem_t *mctx)
4078 {
4079         isc_result_t result;
4080         dns_rdata_t keyrdata;
4081         dns_rdata_t newdsrdata;
4082         dns_rdata_t dsrdata;
4083         dns_rdata_ds_t dsinfo;
4084         dst_key_t *dnsseckey = NULL;
4085         unsigned char dsbuf[DNS_DS_BUFFERSIZE];
4086
4087         result = dns_rdataset_first(dsrdataset);
4088         check_result(result, "empty DSset dataset");
4089         dns_rdata_init(&dsrdata);
4090         do {
4091                 dns_rdataset_current(dsrdataset, &dsrdata);
4092
4093                 result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL);
4094                 check_result(result, "dns_rdata_tostruct  for DS");
4095
4096                 result = dns_rdataset_first(keyrdataset);
4097                 check_result(result, "empty KEY dataset");
4098                 dns_rdata_init(&keyrdata);      
4099
4100                 do {
4101                         dns_rdataset_current(keyrdataset, &keyrdata);
4102                         INSIST(keyrdata.type == dns_rdatatype_dnskey);
4103         
4104                         result = dns_dnssec_keyfromrdata(name, &keyrdata,
4105                                                          mctx, &dnsseckey);
4106                         check_result(result, "dns_dnssec_keyfromrdata");
4107
4108                         /*
4109                          * Test if the id of the DNSKEY is the
4110                          * id of DNSKEY referenced by the DS
4111                          */
4112                         if (dsinfo.key_tag == dst_key_id(dnsseckey)) {
4113                                 dns_rdata_init(&newdsrdata);
4114
4115                                 result = dns_ds_buildrdata(name, &keyrdata,
4116                                                            dsinfo.digest_type,
4117                                                            dsbuf, &newdsrdata);
4118                                 dns_rdata_freestruct(&dsinfo);
4119
4120                                 if (result != ISC_R_SUCCESS) {
4121                                         dns_rdata_reset(&keyrdata);
4122                                         dns_rdata_reset(&newdsrdata);
4123                                         dns_rdata_reset(&dsrdata);
4124                                         dst_key_free(&dnsseckey);
4125                                         dns_rdata_freestruct(&dsinfo);
4126                                         printf("Oops: impossible to build"
4127                                                " new DS rdata\n");
4128                                         return (result);
4129                                 }
4130         
4131         
4132                                 if (dns_rdata_compare(&dsrdata,
4133                                                       &newdsrdata) == 0) {
4134                                         printf(";; OK a DS valids a DNSKEY"
4135                                                " in the RRset\n");
4136                                         printf(";; Now verify that this"
4137                                                " DNSKEY validates the "
4138                                                "DNSKEY RRset\n");
4139         
4140                                         result = sigchase_verify_sig_key(name,
4141                                                          keyrdataset,
4142                                                          dnsseckey,
4143                                                          chase_sigkeyrdataset,
4144                                                          mctx);
4145                                         if (result ==  ISC_R_SUCCESS) {
4146                                                 dns_rdata_reset(&keyrdata);
4147                                                 dns_rdata_reset(&newdsrdata);
4148                                                 dns_rdata_reset(&dsrdata);
4149                                                 dst_key_free(&dnsseckey);
4150                 
4151                                                 return (result);
4152                                         }
4153                                 } else {
4154                                         printf(";; This DS is NOT the DS for"
4155                                                " the chasing KEY: FAILED\n");
4156                                 }
4157
4158                                 dns_rdata_reset(&newdsrdata);
4159                         }
4160                         dst_key_free(&dnsseckey);
4161                         dnsseckey = NULL;
4162                 } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
4163                 dns_rdata_reset(&keyrdata);
4164
4165         } while (dns_rdataset_next(chase_dsrdataset) == ISC_R_SUCCESS);
4166 #if 0
4167         dns_rdata_reset(&dsrdata); WARNING
4168 #endif
4169
4170         return (ISC_R_NOTFOUND);
4171 }
4172
4173 /*
4174  *
4175  * take a pointer on a rdataset in parameter and try to resolv it.
4176  * the searched rrset is a rrset on 'name' with type 'type'
4177  * (and if the type is a rrsig the signature cover 'covers').
4178  * the lookedup is to known if you have already done the query on the net.
4179  * ISC_R_SUCCESS: if we found the rrset
4180  * ISC_R_NOTFOUND: we do not found the rrset in cache
4181  * and we do a query on the net
4182  * ISC_R_FAILURE: rrset not found
4183  */
4184 isc_result_t
4185 advanced_rrsearch(dns_rdataset_t **rdataset, dns_name_t *name,
4186                   dns_rdatatype_t type, dns_rdatatype_t covers,
4187                   isc_boolean_t *lookedup)
4188 {
4189         isc_boolean_t  tmplookedup;
4190
4191         INSIST(rdataset != NULL);
4192
4193         if (*rdataset != NULL)
4194                 return (ISC_R_SUCCESS);
4195
4196         tmplookedup = *lookedup;
4197         if ((*rdataset = sigchase_scanname(type, covers,
4198                                            lookedup, name)) == NULL) {
4199                 if (tmplookedup)
4200                         return (ISC_R_FAILURE);
4201                 return (ISC_R_NOTFOUND);
4202         }
4203         *lookedup = ISC_FALSE;
4204         return (ISC_R_SUCCESS);
4205 }
4206
4207
4208
4209 #if DIG_SIGCHASE_TD
4210 void
4211 sigchase_td(dns_message_t *msg)
4212 {
4213         isc_result_t result;
4214         dns_name_t *name = NULL;
4215         isc_boolean_t have_answer = ISC_FALSE;
4216         isc_boolean_t true = ISC_TRUE;
4217
4218         if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
4219             == ISC_R_SUCCESS) {
4220                 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
4221                 if (current_lookup->trace_root_sigchase) {
4222                         initialization(name);
4223                         return;
4224                 }
4225                 have_answer = true;
4226         } else {
4227                 if (!current_lookup->trace_root_sigchase) {
4228                         result = dns_message_firstname(msg,
4229                                                        DNS_SECTION_AUTHORITY);
4230                         if (result == ISC_R_SUCCESS)
4231                                 dns_message_currentname(msg,
4232                                                         DNS_SECTION_AUTHORITY,
4233                                                         &name);
4234                         chase_nsrdataset
4235                                 = chase_scanname_section(msg, name,
4236                                                          dns_rdatatype_ns,
4237                                                          dns_rdatatype_any,
4238                                                          DNS_SECTION_AUTHORITY);
4239                         dup_name(name, &chase_authority_name, mctx);
4240                         if (chase_nsrdataset != NULL) {
4241                                 have_delegation_ns = ISC_TRUE;
4242                                 printf("no response but there is a delegation"
4243                                        " in authority section:");
4244                                 dns_name_print(name, stdout);
4245                                 printf("\n");
4246                         } else {
4247                                 printf("no response and no delegation in "
4248                                        "authority section but a reference"
4249                                        " to: ");
4250                                 dns_name_print(name, stdout);
4251                                 printf("\n");
4252                                 error_message = msg;
4253                         }
4254                 } else {
4255                         printf(";; NO ANSWERS: %s\n",
4256                                isc_result_totext(result));
4257                         free_name(&chase_name, mctx);
4258                         clean_trustedkey();
4259                         return;
4260                 }
4261         }
4262
4263
4264         if (have_answer) {
4265                 chase_rdataset
4266                         = chase_scanname_section(msg, &chase_name,
4267                                                  current_lookup
4268                                                  ->rdtype_sigchase,
4269                                                  dns_rdatatype_any,
4270                                                  DNS_SECTION_ANSWER);
4271                 if (chase_rdataset != NULL)
4272                         have_response = ISC_TRUE;
4273         }
4274
4275         result = advanced_rrsearch(&chase_keyrdataset,
4276                                    &chase_current_name,
4277                                    dns_rdatatype_dnskey,
4278                                    dns_rdatatype_any,
4279                                    &chase_keylookedup);
4280         if (result == ISC_R_FAILURE) {
4281                 printf("\n;; DNSKEY is missing to continue validation:"
4282                        " FAILED\n\n");
4283                 goto cleanandgo;
4284         }
4285         if (result == ISC_R_NOTFOUND)
4286                 return;
4287         INSIST(chase_keyrdataset != NULL);
4288         printf("\n;; DNSKEYset:\n");
4289         print_rdataset(&chase_current_name , chase_keyrdataset, mctx);
4290
4291
4292         result = advanced_rrsearch(&chase_sigkeyrdataset,
4293                                    &chase_current_name,
4294                                    dns_rdatatype_rrsig,
4295                                    dns_rdatatype_dnskey,
4296                                    &chase_sigkeylookedup);
4297         if (result == ISC_R_FAILURE) {
4298                 printf("\n;; RRSIG of DNSKEY is missing to continue validation:"
4299                        " FAILED\n\n");
4300                 goto cleanandgo;
4301         }
4302         if (result == ISC_R_NOTFOUND)
4303                 return;
4304         INSIST(chase_sigkeyrdataset != NULL);
4305         printf("\n;; RRSIG of the DNSKEYset:\n");
4306         print_rdataset(&chase_current_name , chase_sigkeyrdataset, mctx);
4307
4308
4309         if (!chase_dslookedup && !chase_nslookedup) {
4310                 if (!delegation_follow) {
4311                         result = contains_trusted_key(&chase_current_name,
4312                                                       chase_keyrdataset,
4313                                                       chase_sigkeyrdataset,
4314                                                       mctx);
4315                 } else {
4316                         INSIST(chase_dsrdataset != NULL);
4317                         INSIST(chase_sigdsrdataset != NULL);
4318                         result = sigchase_verify_ds(&chase_current_name,
4319                                                     chase_keyrdataset,
4320                                                     chase_dsrdataset,
4321                                                     mctx);
4322                 }
4323
4324                 if (result != ISC_R_SUCCESS) {
4325                         printf("\n;; chain of trust can't be validated:"
4326                                " FAILED\n\n");
4327                         goto cleanandgo;
4328                 } else {
4329                         chase_dsrdataset = NULL;
4330                         chase_sigdsrdataset = NULL;
4331                 }
4332         }
4333
4334         if (have_response || (!have_delegation_ns && !have_response)) {
4335                 /* test if it's a grand father case */
4336
4337                 if (have_response) {
4338                         result = advanced_rrsearch(&chase_sigrdataset,
4339                                                    &chase_name,
4340                                                    dns_rdatatype_rrsig,
4341                                                    current_lookup
4342                                                    ->rdtype_sigchase,
4343                                                    &true);
4344                         if (result == ISC_R_FAILURE) {
4345                                 printf("\n;; RRset is missing to continue"
4346                                        " validation SHOULD NOT APPEND:"
4347                                        " FAILED\n\n");
4348                                 goto cleanandgo;
4349                         }
4350
4351                 } else {
4352                         result = advanced_rrsearch(&chase_sigrdataset,
4353                                                    &chase_authority_name,
4354                                                    dns_rdatatype_rrsig,
4355                                                    dns_rdatatype_any,
4356                                                    &true);
4357                         if (result == ISC_R_FAILURE) {
4358                                 printf("\n;; RRSIG is missing  to continue"
4359                                        " validation SHOULD NOT APPEND:"
4360                                        " FAILED\n\n");
4361                                 goto cleanandgo;
4362                         }
4363                 }
4364                 result =  grandfather_pb_test(&chase_current_name,
4365                                               chase_sigrdataset);
4366                 if (result != ISC_R_SUCCESS) {
4367                         dns_name_t tmp_name;
4368
4369                         printf("\n;; We are in a Grand Father Problem:"
4370                                " See 2.2.1 in RFC 3568\n");
4371                         chase_rdataset = NULL;
4372                         chase_sigrdataset = NULL;
4373                         have_response = ISC_FALSE;
4374                         have_delegation_ns = ISC_FALSE;
4375         
4376                         dns_name_init(&tmp_name, NULL);
4377                         result = child_of_zone(&chase_name, &chase_current_name,
4378                                                &tmp_name);
4379                         if (dns_name_dynamic(&chase_authority_name))
4380                                 free_name(&chase_authority_name, mctx);
4381                         dup_name(&tmp_name, &chase_authority_name, mctx);
4382                         printf(";; and we try to continue chain of trust"
4383                                " validation of the zone: ");
4384                         dns_name_print(&chase_authority_name, stdout);
4385                         printf("\n");
4386                         have_delegation_ns = ISC_TRUE;
4387                 } else {
4388                         if (have_response)
4389                                 goto finalstep;
4390                         else
4391                                 chase_sigrdataset = NULL;
4392                 }
4393         }
4394
4395         if (have_delegation_ns) {
4396                 chase_nsrdataset = NULL;
4397                 result = advanced_rrsearch(&chase_nsrdataset,
4398                                            &chase_authority_name,
4399                                            dns_rdatatype_ns,
4400                                            dns_rdatatype_any,
4401                                            &chase_nslookedup);
4402                 if (result == ISC_R_FAILURE) {
4403                         printf("\n;;NSset is missing to continue validation:"
4404                                " FAILED\n\n");
4405                         goto cleanandgo;
4406                 }
4407                 if (result == ISC_R_NOTFOUND) {
4408                         return;
4409                 }
4410                 INSIST(chase_nsrdataset != NULL);
4411
4412                 result = advanced_rrsearch(&chase_dsrdataset,
4413                                            &chase_authority_name,
4414                                            dns_rdatatype_ds,
4415                                            dns_rdatatype_any,
4416                                            &chase_dslookedup);
4417                 if (result == ISC_R_FAILURE) {
4418                         printf("\n;; DSset is missing to continue validation:"
4419                                " FAILED\n\n");
4420                         goto cleanandgo;
4421                 }
4422                 if (result == ISC_R_NOTFOUND)
4423                         return;
4424                 INSIST(chase_dsrdataset != NULL);
4425                 printf("\n;; DSset:\n");
4426                 print_rdataset(&chase_authority_name , chase_dsrdataset, mctx);
4427
4428                 result = advanced_rrsearch(&chase_sigdsrdataset,
4429                                            &chase_authority_name,
4430                                            dns_rdatatype_rrsig,
4431                                            dns_rdatatype_ds,
4432                                            &true);
4433                 if (result != ISC_R_SUCCESS) {
4434                         printf("\n;; DSset is missing to continue validation:"
4435                                " FAILED\n\n");
4436                         goto cleanandgo;
4437                 }
4438                 printf("\n;; RRSIGset of DSset\n");
4439                 print_rdataset(&chase_authority_name,
4440                                chase_sigdsrdataset, mctx);
4441                 INSIST(chase_sigdsrdataset != NULL);
4442
4443                 result = sigchase_verify_sig(&chase_authority_name,
4444                                              chase_dsrdataset,
4445                                              chase_keyrdataset,
4446                                              chase_sigdsrdataset, mctx);
4447                 if (result != ISC_R_SUCCESS) {
4448                         printf("\n;; Impossible to verify the DSset:"
4449                                " FAILED\n\n");
4450                         goto cleanandgo;
4451                 }
4452                 chase_keyrdataset = NULL;
4453                 chase_sigkeyrdataset = NULL;
4454
4455
4456                 prepare_lookup(&chase_authority_name);
4457         
4458                 have_response = ISC_FALSE;
4459                 have_delegation_ns = ISC_FALSE;
4460                 delegation_follow = ISC_TRUE;
4461                 error_message = NULL;
4462                 dup_name(&chase_authority_name, &chase_current_name, mctx);
4463                 free_name(&chase_authority_name, mctx);
4464                 return;
4465         }
4466
4467
4468         if (error_message != NULL) {
4469                 dns_rdataset_t *rdataset;
4470                 dns_rdataset_t *sigrdataset;
4471                 dns_name_t rdata_name;
4472                 isc_result_t ret = ISC_R_FAILURE;
4473
4474                 dns_name_init(&rdata_name, NULL);
4475                 result = prove_nx(error_message, &chase_name,
4476                                   current_lookup->rdclass_sigchase,
4477                                   current_lookup->rdtype_sigchase, &rdata_name,
4478                                   &rdataset, &sigrdataset);
4479                 if (rdataset == NULL || sigrdataset == NULL ||
4480                     dns_name_countlabels(&rdata_name) == 0) {
4481                         printf("\n;; Impossible to verify the non-existence,"
4482                                " the NSEC RRset can't be validated:"
4483                                " FAILED\n\n");
4484                         goto cleanandgo;
4485                 }
4486                 ret = sigchase_verify_sig(&rdata_name, rdataset,
4487                                           chase_keyrdataset,
4488                                           sigrdataset, mctx);
4489                 if (ret != ISC_R_SUCCESS) {
4490                         free_name(&rdata_name, mctx);
4491                         printf("\n;; Impossible to verify the NSEC RR to prove"
4492                                " the non-existence : FAILED\n\n");
4493                         goto cleanandgo;
4494                 }
4495                 free_name(&rdata_name, mctx);
4496                 if (result != ISC_R_SUCCESS) {
4497                         printf("\n;; Impossible to verify the non-existence:"
4498                                " FAILED\n\n");
4499                         goto cleanandgo;
4500                 } else {
4501                         printf("\n;; OK the query doesn't have response but"
4502                                " we have validate this fact : SUCCESS\n\n");
4503                         goto cleanandgo;
4504                 }
4505         }
4506
4507  cleanandgo:
4508         printf(";; cleanandgo \n");
4509         if (dns_name_dynamic(&chase_current_name))
4510                 free_name(&chase_current_name, mctx);
4511         if (dns_name_dynamic(&chase_authority_name))
4512                 free_name(&chase_authority_name, mctx);
4513         clean_trustedkey();
4514         return;
4515
4516         finalstep :
4517                 result = advanced_rrsearch(&chase_rdataset, &chase_name,
4518                                            current_lookup->rdtype_sigchase,
4519                                            dns_rdatatype_any ,
4520                                            &true);
4521         if (result == ISC_R_FAILURE) {
4522                 printf("\n;; RRsig of RRset is missing to continue validation"
4523                        " SHOULD NOT APPEND: FAILED\n\n");
4524                 goto cleanandgo;
4525         }
4526         result = sigchase_verify_sig(&chase_name, chase_rdataset,
4527                                      chase_keyrdataset,
4528                                      chase_sigrdataset, mctx);
4529         if (result != ISC_R_SUCCESS) {
4530                 printf("\n;; Impossible to verify the RRset : FAILED\n\n");
4531                 /*
4532                   printf("RRset:\n");
4533                   print_rdataset(&chase_name , chase_rdataset, mctx);
4534                   printf("DNSKEYset:\n");
4535                   print_rdataset(&chase_name , chase_keyrdataset, mctx);
4536                   printf("RRSIG of RRset:\n");
4537                   print_rdataset(&chase_name , chase_sigrdataset, mctx);
4538                   printf("\n");
4539                 */
4540                 goto cleanandgo;
4541         } else {
4542                 printf("\n;; The Answer:\n");
4543                 print_rdataset(&chase_name , chase_rdataset, mctx);
4544
4545                 printf("\n;; FINISH : we have validate the DNSSEC chain"
4546                        " of trust: SUCCESS\n\n");
4547                 goto cleanandgo;
4548         }
4549 }
4550
4551 #endif
4552
4553
4554 #if DIG_SIGCHASE_BU
4555
4556 isc_result_t
4557 getneededrr(dns_message_t *msg)
4558 {
4559         isc_result_t result;
4560         dns_name_t *name = NULL;
4561         dns_rdata_t sigrdata;
4562         dns_rdata_sig_t siginfo;
4563         isc_boolean_t   true = ISC_TRUE;
4564
4565         if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
4566             != ISC_R_SUCCESS) {
4567                 printf(";; NO ANSWERS: %s\n", isc_result_totext(result));
4568
4569                 if (chase_name.ndata == NULL)
4570                         return (ISC_R_ADDRNOTAVAIL);
4571         } else {
4572                 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
4573         }
4574
4575         /* What do we chase? */
4576         if (chase_rdataset == NULL) {
4577                 result = advanced_rrsearch(&chase_rdataset, name,
4578                                            dns_rdatatype_any,
4579                                            dns_rdatatype_any, &true);
4580                 if (result != ISC_R_SUCCESS) {
4581                         printf("\n;; No Answers: Validation FAILED\n\n");
4582                         return (ISC_R_NOTFOUND);
4583                 }
4584                 dup_name(name, &chase_name, mctx);
4585                 printf(";; RRset to chase:\n");
4586                 print_rdataset(&chase_name, chase_rdataset, mctx);
4587         }
4588         INSIST(chase_rdataset != NULL);
4589
4590
4591         if (chase_sigrdataset == NULL) {
4592                 result = advanced_rrsearch(&chase_sigrdataset, name,
4593                                            dns_rdatatype_rrsig,
4594                                            chase_rdataset->type,
4595                                            &chase_siglookedup);
4596                 if (result == ISC_R_FAILURE) {
4597                         printf("\n;; RRSIG is missing for continue validation:"
4598                                " FAILED\n\n");
4599                         if (dns_name_dynamic(&chase_name))
4600                                 free_name(&chase_name, mctx);
4601                         return (ISC_R_NOTFOUND);
4602                 }
4603                 if (result == ISC_R_NOTFOUND) {
4604                         return (ISC_R_NOTFOUND);
4605                 }
4606                 printf("\n;; RRSIG of the RRset to chase:\n");
4607                 print_rdataset(&chase_name, chase_sigrdataset, mctx);
4608         }
4609         INSIST(chase_sigrdataset != NULL);
4610
4611
4612         /* first find the DNSKEY name */
4613         result = dns_rdataset_first(chase_sigrdataset);
4614         check_result(result, "empty RRSIG dataset");
4615         dns_rdata_init(&sigrdata);
4616         dns_rdataset_current(chase_sigrdataset, &sigrdata);
4617         result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4618         check_result(result, "sigrdata tostruct siginfo");
4619         dup_name(&siginfo.signer, &chase_signame, mctx);
4620         dns_rdata_freestruct(&siginfo);
4621         dns_rdata_reset(&sigrdata);
4622
4623         /* Do we have a key?  */
4624         if (chase_keyrdataset == NULL) {
4625                 result = advanced_rrsearch(&chase_keyrdataset,
4626                                            &chase_signame,
4627                                            dns_rdatatype_dnskey,
4628                                            dns_rdatatype_any,
4629                                            &chase_keylookedup);
4630                 if (result == ISC_R_FAILURE) {
4631                         printf("\n;; DNSKEY is missing to continue validation:"
4632                                " FAILED\n\n");
4633                         free_name(&chase_signame, mctx);
4634                         if (dns_name_dynamic(&chase_name))
4635                                 free_name(&chase_name, mctx);
4636                         return (ISC_R_NOTFOUND);
4637                 }
4638                 if (result == ISC_R_NOTFOUND) {
4639                         free_name(&chase_signame, mctx);
4640                         return (ISC_R_NOTFOUND);
4641                 }
4642                 printf("\n;; DNSKEYset that signs the RRset to chase:\n");
4643                 print_rdataset(&chase_signame, chase_keyrdataset, mctx);
4644         }
4645         INSIST(chase_keyrdataset != NULL);
4646
4647         if (chase_sigkeyrdataset == NULL) {
4648                 result = advanced_rrsearch(&chase_sigkeyrdataset,
4649                                            &chase_signame,
4650                                            dns_rdatatype_rrsig,
4651                                            dns_rdatatype_dnskey,
4652                                            &chase_sigkeylookedup);
4653                 if (result == ISC_R_FAILURE) {
4654                         printf("\n;; RRSIG for DNSKEY  is missing  to continue"
4655                                " validation : FAILED\n\n");
4656                         free_name(&chase_signame, mctx);
4657                         if (dns_name_dynamic(&chase_name))
4658                                 free_name(&chase_name, mctx);
4659                         return (ISC_R_NOTFOUND);
4660                 }
4661                 if (result == ISC_R_NOTFOUND) {
4662                         free_name(&chase_signame, mctx);
4663                         return (ISC_R_NOTFOUND);
4664                 }
4665                 printf("\n;; RRSIG of the DNSKEYset that signs the "
4666                        "RRset to chase:\n");
4667                 print_rdataset(&chase_signame, chase_sigkeyrdataset, mctx);
4668         }
4669         INSIST(chase_sigkeyrdataset != NULL);
4670
4671
4672         if (chase_dsrdataset == NULL) {
4673                 result = advanced_rrsearch(&chase_dsrdataset, &chase_signame,
4674                                            dns_rdatatype_ds,
4675                                            dns_rdatatype_any,
4676                 &chase_dslookedup);
4677                 if (result == ISC_R_FAILURE) {
4678                         printf("\n;; WARNING There is no DS for the zone: ");
4679                         dns_name_print(&chase_signame, stdout);
4680                         printf("\n");
4681                 }
4682                 if (result == ISC_R_NOTFOUND) {
4683                         free_name(&chase_signame, mctx);
4684                         return (ISC_R_NOTFOUND);
4685                 }
4686                 if (chase_dsrdataset != NULL) {
4687                         printf("\n;; DSset of the DNSKEYset\n");
4688                         print_rdataset(&chase_signame, chase_dsrdataset, mctx);
4689                 }
4690         }
4691
4692         if (chase_dsrdataset != NULL) {
4693                 /*
4694                  * if there is no RRSIG of DS,
4695                  * we don't want to search on the network
4696                  */
4697                 result = advanced_rrsearch(&chase_sigdsrdataset,
4698                                            &chase_signame,
4699                                            dns_rdatatype_rrsig,
4700                                            dns_rdatatype_ds, &true);
4701                 if (result == ISC_R_FAILURE) {
4702                         printf(";; WARNING : NO RRSIG DS : RRSIG DS"
4703                                " should come with DS\n");
4704                         /*
4705                          * We continue even the DS couldn't be validated,
4706                          * because the DNSKEY could be a Trusted Key.
4707                          */
4708                         chase_dsrdataset = NULL;
4709                 } else {
4710                         printf("\n;; RRSIG of the DSset of the DNSKEYset\n");
4711                         print_rdataset(&chase_signame, chase_sigdsrdataset,
4712                                        mctx);
4713                 }
4714         }
4715         return (1);
4716 }
4717
4718
4719
4720 void
4721 sigchase_bu(dns_message_t *msg)
4722 {
4723         isc_result_t result;
4724         int ret;
4725
4726         if (tk_list.nb_tk == 0) {
4727                 result = get_trusted_key(mctx);
4728                 if (result != ISC_R_SUCCESS) {
4729                         printf("No trusted keys present\n");
4730                         return;
4731                 }
4732         }
4733
4734
4735         ret = getneededrr(msg);
4736         if (ret == ISC_R_NOTFOUND)
4737                 return;
4738
4739         if (ret == ISC_R_ADDRNOTAVAIL) {
4740                 /* We have no response */
4741                 dns_rdataset_t *rdataset;
4742                 dns_rdataset_t *sigrdataset;
4743                 dns_name_t rdata_name;
4744                 dns_name_t query_name;
4745
4746
4747                 dns_name_init(&query_name, NULL);
4748                 dns_name_init(&rdata_name, NULL);
4749                 nameFromString(current_lookup->textname, &query_name);
4750
4751                 result = prove_nx(msg, &query_name, current_lookup->rdclass,
4752                                   current_lookup->rdtype, &rdata_name,
4753                                   &rdataset, &sigrdataset);
4754                 free_name(&query_name, mctx);
4755                 if (rdataset == NULL || sigrdataset == NULL ||
4756                     dns_name_countlabels(&rdata_name) == 0) {
4757                         printf("\n;; Impossible to verify the Non-existence,"
4758                                " the NSEC RRset can't be validated: "
4759                                "FAILED\n\n");
4760                         clean_trustedkey();
4761                         return;
4762                 }
4763
4764                 if (result != ISC_R_SUCCESS) {
4765                         printf("\n No Answers and impossible to prove the"
4766                                " unsecurity : Validation FAILED\n\n");
4767                         clean_trustedkey();
4768                         return;
4769                 }
4770                 printf(";; An NSEC prove the non-existence of a answers,"
4771                        " Now we want validate this NSEC\n");
4772         
4773                 dup_name(&rdata_name, &chase_name, mctx);
4774                 free_name(&rdata_name, mctx);
4775                 chase_rdataset =  rdataset;
4776                 chase_sigrdataset = sigrdataset;
4777                 chase_keyrdataset = NULL;
4778                 chase_sigkeyrdataset = NULL;
4779                 chase_dsrdataset = NULL;
4780                 chase_sigdsrdataset = NULL;
4781                 chase_siglookedup = ISC_FALSE;
4782                 chase_keylookedup = ISC_FALSE;
4783                 chase_dslookedup = ISC_FALSE;
4784                 chase_sigdslookedup = ISC_FALSE;
4785                 sigchase(msg);
4786                 clean_trustedkey();
4787                 return;
4788         }
4789
4790
4791         printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n");
4792
4793         result = sigchase_verify_sig(&chase_name, chase_rdataset,
4794                                      chase_keyrdataset,
4795                                      chase_sigrdataset, mctx);
4796         if (result != ISC_R_SUCCESS) {
4797                 free_name(&chase_name, mctx);
4798                 free_name(&chase_signame, mctx);
4799                 printf(";; No DNSKEY is valid to check the RRSIG"
4800                        " of the RRset: FAILED\n");
4801                 clean_trustedkey();
4802                 return;
4803         }
4804         printf(";; OK We found DNSKEY (or more) to validate the RRset\n");
4805
4806         result = contains_trusted_key(&chase_signame, chase_keyrdataset,
4807                                       chase_sigkeyrdataset, mctx);
4808         if (result ==  ISC_R_SUCCESS) {
4809                 free_name(&chase_name, mctx);
4810                 free_name(&chase_signame, mctx);
4811                 printf("\n;; Ok this DNSKEY is a Trusted Key,"
4812                        " DNSSEC validation is ok: SUCCESS\n\n");
4813                 clean_trustedkey();
4814                 return;
4815         }
4816
4817         printf(";; Now, we are going to validate this DNSKEY by the DS\n");
4818
4819         if (chase_dsrdataset == NULL) {
4820                 free_name(&chase_name, mctx);
4821                 free_name(&chase_signame, mctx);
4822                 printf(";; the DNSKEY isn't trusted-key and there isn't"
4823                        " DS to validate the DNSKEY: FAILED\n");
4824                 clean_trustedkey();
4825                 return;
4826         }
4827
4828         result =  sigchase_verify_ds(&chase_signame, chase_keyrdataset,
4829                                      chase_dsrdataset, mctx);
4830         if (result !=  ISC_R_SUCCESS) {
4831                 free_name(&chase_signame, mctx);
4832                 free_name(&chase_name, mctx);
4833                 printf(";; ERROR no DS validates a DNSKEY in the"
4834                        " DNSKEY RRset: FAILED\n");
4835                 clean_trustedkey();
4836                 return;
4837         } else
4838                 printf(";; OK this DNSKEY (validated by the DS) validates"
4839                        " the RRset of the DNSKEYs, thus the DNSKEY validates"
4840                        " the RRset\n");
4841         INSIST(chase_sigdsrdataset != NULL);
4842
4843         dup_name(&chase_signame, &chase_name, mctx);
4844         free_name(&chase_signame, mctx);
4845         chase_rdataset = chase_dsrdataset;
4846         chase_sigrdataset = chase_sigdsrdataset;
4847         chase_keyrdataset = NULL;
4848         chase_sigkeyrdataset = NULL;
4849         chase_dsrdataset = NULL;
4850         chase_sigdsrdataset = NULL;
4851         chase_siglookedup = chase_keylookedup = ISC_FALSE;
4852         chase_dslookedup = chase_sigdslookedup = ISC_FALSE;
4853
4854         printf(";; Now, we want to validate the DS :  recursive call\n");
4855         sigchase(msg);
4856         return;
4857 }
4858 #endif
4859
4860 void
4861 sigchase(dns_message_t *msg) {
4862 #if DIG_SIGCHASE_TD
4863         if (current_lookup->do_topdown) {
4864                 sigchase_td(msg);
4865                 return;
4866         }
4867 #endif
4868 #if DIG_SIGCHASE_BU
4869         sigchase_bu(msg);
4870         return;
4871 #endif
4872 }
4873
4874
4875 /*
4876  * return 1  if name1  <  name2
4877  *        0  if name1  == name2
4878  *        -1 if name1  >  name2
4879  *    and -2 if problem
4880  */
4881 int
4882 inf_name(dns_name_t *name1, dns_name_t *name2)
4883 {
4884         dns_label_t  label1;
4885         dns_label_t  label2;
4886         unsigned int nblabel1;
4887         unsigned int nblabel2;
4888         int min_lum_label;
4889         int i;
4890         int ret = -2;
4891
4892         nblabel1 = dns_name_countlabels(name1);
4893         nblabel2 = dns_name_countlabels(name2);
4894
4895         if (nblabel1 >= nblabel2)
4896                 min_lum_label = nblabel2;
4897         else
4898                 min_lum_label = nblabel1;
4899
4900
4901         for (i=1 ; i < min_lum_label; i++) {
4902                 dns_name_getlabel(name1, nblabel1 -1  - i, &label1);
4903                 dns_name_getlabel(name2, nblabel2 -1  - i, &label2);
4904                 if ((ret = isc_region_compare(&label1, &label2)) != 0) {
4905                         if (ret < 0)
4906                                 return (-1);
4907                         else if (ret > 0)
4908                                 return (1);
4909                 }
4910         }
4911         if (nblabel1 == nblabel2)
4912                 return (0);
4913
4914         if (nblabel1 < nblabel2)
4915                 return (-1);
4916         else
4917                 return (1);
4918 }
4919
4920 /**
4921  *
4922  *
4923  *
4924  */
4925 isc_result_t
4926 prove_nx_domain(dns_message_t *msg,
4927                 dns_name_t *name,
4928                 dns_name_t *rdata_name,
4929                 dns_rdataset_t **rdataset,
4930                 dns_rdataset_t **sigrdataset)
4931 {
4932         isc_result_t ret = ISC_R_FAILURE;
4933         isc_result_t result = ISC_R_NOTFOUND;
4934         dns_rdataset_t *nsecset = NULL;
4935         dns_rdataset_t *signsecset = NULL ;
4936         dns_rdata_t nsec = DNS_RDATA_INIT;
4937         dns_name_t *nsecname;
4938         dns_rdata_nsec_t nsecstruct;
4939
4940         if ((result = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
4941             != ISC_R_SUCCESS) {
4942                 printf(";; nothing in authority section : impossible to"
4943                        " validate the non-existence : FAILED\n");
4944                 return (ISC_R_FAILURE);
4945         }
4946
4947         do {
4948                 nsecname = NULL;
4949                 dns_message_currentname(msg, DNS_SECTION_AUTHORITY, &nsecname);
4950                 nsecset = search_type(nsecname, dns_rdatatype_nsec,
4951                                       dns_rdatatype_any);
4952                 if (nsecset == NULL)
4953                         continue;
4954
4955                 printf("There is a NSEC for this zone in the"
4956                        " AUTHORITY section:\n");
4957                 print_rdataset(nsecname, nsecset, mctx);
4958
4959                 for (result = dns_rdataset_first(nsecset);
4960                      result == ISC_R_SUCCESS;
4961                      result = dns_rdataset_next(nsecset)) {
4962                         dns_rdataset_current(nsecset, &nsec);
4963
4964
4965                         signsecset
4966                                 = chase_scanname_section(msg, nsecname,
4967                                                  dns_rdatatype_rrsig,
4968                                                  dns_rdatatype_nsec,
4969                                                  DNS_SECTION_AUTHORITY);
4970                         if (signsecset == NULL) {
4971                                 printf(";; no RRSIG NSEC in authority section:"
4972                                        " impossible to validate the "
4973                                        "non-existence: FAILED\n");
4974                                 return (ISC_R_FAILURE);
4975                         }
4976
4977                         ret = dns_rdata_tostruct(&nsec, &nsecstruct, NULL);
4978                         check_result(ret,"dns_rdata_tostruct");
4979
4980                         if ((inf_name(nsecname, &nsecstruct.next) == 1 &&
4981                              inf_name(name, &nsecstruct.next) == 1) ||
4982                             (inf_name(name, nsecname) == 1 &&
4983                              inf_name(&nsecstruct.next, name) == 1)) {
4984                                 dns_rdata_freestruct(&nsecstruct);
4985                                 *rdataset = nsecset;
4986                                 *sigrdataset = signsecset;
4987                                 dup_name(nsecname, rdata_name, mctx);
4988
4989                                 return (ISC_R_SUCCESS);
4990                         }
4991
4992                         dns_rdata_freestruct(&nsecstruct);
4993                 }
4994         } while (dns_message_nextname(msg, DNS_SECTION_AUTHORITY)
4995                  == ISC_R_SUCCESS);
4996
4997         *rdataset = NULL;
4998         *sigrdataset =  NULL;
4999         rdata_name = NULL;
5000         return (ISC_R_FAILURE);
5001 }
5002
5003 /**
5004  *
5005  *
5006  *
5007  *
5008  *
5009  */
5010 isc_result_t
5011 prove_nx_type(dns_message_t *msg, dns_name_t *name, dns_rdataset_t *nsecset,
5012               dns_rdataclass_t class, dns_rdatatype_t type,
5013               dns_name_t *rdata_name, dns_rdataset_t **rdataset,
5014               dns_rdataset_t **sigrdataset)
5015 {
5016         isc_result_t ret;
5017         dns_rdataset_t *signsecset;
5018         dns_rdata_t nsec = DNS_RDATA_INIT;
5019
5020         UNUSED(class);
5021
5022         ret = dns_rdataset_first(nsecset);
5023         check_result(ret,"dns_rdataset_first");
5024         
5025         dns_rdataset_current(nsecset, &nsec);
5026
5027         ret = dns_nsec_typepresent(&nsec, type);
5028         if (ret == ISC_R_SUCCESS)
5029                 printf("OK the NSEC said that the type doesn't exist \n");
5030
5031         signsecset = chase_scanname_section(msg, name,
5032                                             dns_rdatatype_rrsig,
5033                                             dns_rdatatype_nsec,
5034                                             DNS_SECTION_AUTHORITY);
5035         if (signsecset == NULL) {
5036                 printf("There isn't RRSIG NSEC for the zone \n");
5037                 return (ISC_R_FAILURE);
5038         }
5039         dup_name(name, rdata_name, mctx);
5040         *rdataset = nsecset;
5041         *sigrdataset = signsecset;
5042
5043         return (ret);
5044 }
5045
5046 /**
5047  *
5048  *
5049  *
5050  *
5051  */
5052 isc_result_t
5053 prove_nx(dns_message_t *msg, dns_name_t *name, dns_rdataclass_t class,
5054          dns_rdatatype_t type, dns_name_t *rdata_name,
5055          dns_rdataset_t **rdataset, dns_rdataset_t **sigrdataset)
5056 {
5057         isc_result_t ret;
5058         dns_rdataset_t *nsecset = NULL;
5059
5060         printf("We want to prove the non-existance of a type of rdata %d"
5061                " or of the zone: \n", type);
5062
5063         if ((ret = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
5064             != ISC_R_SUCCESS) {
5065                 printf(";; nothing in authority section : impossible to"
5066                        " validate the non-existence : FAILED\n");
5067                 return (ISC_R_FAILURE);
5068         }
5069
5070         nsecset = chase_scanname_section(msg, name, dns_rdatatype_nsec,
5071                                          dns_rdatatype_any,
5072                                          DNS_SECTION_AUTHORITY);
5073         if (nsecset != NULL) {
5074                 printf("We have a NSEC for this zone :OK\n");
5075                 ret = prove_nx_type(msg, name, nsecset, class,
5076                                     type, rdata_name, rdataset,
5077                                     sigrdataset);
5078                 if (ret != ISC_R_SUCCESS) {
5079                         printf("prove_nx: ERROR type exist\n");
5080                         return (ret);
5081                 } else {
5082                         printf("prove_nx: OK type does not exist\n");
5083                         return (ISC_R_SUCCESS);
5084                 }
5085         } else {
5086                 printf("there is no NSEC for this zone: validating "
5087                        "that the zone doesn't exist\n");
5088                 ret = prove_nx_domain(msg, name, rdata_name,
5089                                       rdataset, sigrdataset);
5090                 return (ret);
5091         }
5092 }
5093 #endif