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