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