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