Merge from vendor branch LIBARCHIVE:
[dragonfly.git] / contrib / bind-9.2.4rc7 / bin / dig / dighost.c
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2000-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id: dighost.c,v 1.221.2.22 2004/04/15 06:53:18 marka Exp $ */
19
20 /*
21  * Notice to programmers:  Do not use this code as an example of how to
22  * use the ISC library to perform DNS lookups.  Dig and Host both operate
23  * on the request level, since they allow fine-tuning of output and are
24  * intended as debugging tools.  As a result, they perform many of the
25  * functions which could be better handled using the dns_resolver
26  * functions in most applications.
27  */
28
29 #include <config.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <limits.h>
34
35 #include <dns/byaddr.h>
36 #include <dns/fixedname.h>
37 #include <dns/message.h>
38 #include <dns/name.h>
39 #include <dns/rdata.h>
40 #include <dns/rdataclass.h>
41 #include <dns/rdatalist.h>
42 #include <dns/rdataset.h>
43 #include <dns/rdatastruct.h>
44 #include <dns/rdatatype.h>
45 #include <dns/result.h>
46 #include <dns/tsig.h>
47
48 #include <dst/dst.h>
49
50 #include <isc/app.h>
51 #include <isc/base64.h>
52 #include <isc/entropy.h>
53 #include <isc/lang.h>
54 #include <isc/netaddr.h>
55 #include <isc/netdb.h>
56 #include <isc/print.h>
57 #include <isc/random.h>
58 #include <isc/result.h>
59 #include <isc/string.h>
60 #include <isc/task.h>
61 #include <isc/timer.h>
62 #include <isc/types.h>
63 #include <isc/util.h>
64
65 #include <dig/dig.h>
66
67 #ifdef HAVE_ADDRINFO
68 #ifdef HAVE_GETADDRINFO
69 #ifdef HAVE_GAISTRERROR
70 #define USE_GETADDRINFO
71 #endif
72 #endif
73 #endif
74
75 #ifndef USE_GETADDRINFO
76 #ifndef ISC_PLATFORM_NONSTDHERRNO
77 extern int h_errno;
78 #endif
79 #endif
80
81 ISC_LIST(dig_lookup_t) lookup_list;
82 dig_serverlist_t server_list;
83 ISC_LIST(dig_searchlist_t) search_list;
84
85 isc_boolean_t
86         have_ipv4 = ISC_FALSE,
87         have_ipv6 = ISC_FALSE,
88         specified_source = ISC_FALSE,
89         free_now = ISC_FALSE,
90         cancel_now = ISC_FALSE,
91         usesearch = ISC_FALSE,
92         qr = ISC_FALSE,
93         is_dst_up = ISC_FALSE;
94 in_port_t port = 53;
95 unsigned int timeout = 0;
96 isc_mem_t *mctx = NULL;
97 isc_taskmgr_t *taskmgr = NULL;
98 isc_task_t *global_task = NULL;
99 isc_timermgr_t *timermgr = NULL;
100 isc_socketmgr_t *socketmgr = NULL;
101 isc_sockaddr_t bind_address;
102 isc_sockaddr_t bind_any;
103 int sendcount = 0;
104 int recvcount = 0;
105 int sockcount = 0;
106 int ndots = -1;
107 int tries = 2;
108 int lookup_counter = 0;
109
110 /*
111  * Exit Codes:
112  *   0   Everything went well, including things like NXDOMAIN
113  *   1   Usage error
114  *   7   Got too many RR's or Names
115  *   8   Couldn't open batch file
116  *   9   No reply from server
117  *   10  Internal error
118  */
119 int exitcode = 0;
120 int fatalexit = 0;
121 char keynametext[MXNAME];
122 char keyfile[MXNAME] = "";
123 char keysecret[MXNAME] = "";
124 isc_buffer_t *namebuf = NULL;
125 dns_tsigkey_t *key = NULL;
126 isc_boolean_t validated = ISC_TRUE;
127 isc_entropy_t *entp = NULL;
128 isc_mempool_t *commctx = NULL;
129 isc_boolean_t debugging = ISC_FALSE;
130 isc_boolean_t memdebugging = ISC_FALSE;
131 char *progname = NULL;
132 isc_mutex_t lookup_lock;
133 dig_lookup_t *current_lookup = NULL;
134
135 /*
136  * Apply and clear locks at the event level in global task.
137  * Can I get rid of these using shutdown events?  XXX
138  */
139 #define LOCK_LOOKUP {\
140         debug("lock_lookup %s:%d", __FILE__, __LINE__);\
141         check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\
142         debug("success");\
143 }
144 #define UNLOCK_LOOKUP {\
145         debug("unlock_lookup %s:%d", __FILE__, __LINE__);\
146         check_result(isc_mutex_unlock((&lookup_lock)),\
147                      "isc_mutex_unlock");\
148 }
149
150 static void
151 cancel_lookup(dig_lookup_t *lookup);
152
153 static void
154 recv_done(isc_task_t *task, isc_event_t *event);
155
156 static void
157 connect_timeout(isc_task_t *task, isc_event_t *event);
158
159 static void
160 launch_next_query(dig_query_t *query, isc_boolean_t include_question);
161
162 char *
163 next_token(char **stringp, const char *delim) {
164         char *res;
165
166         do {
167                 res = strsep(stringp, delim);
168                 if (res == NULL)
169                         break;
170         } while (*res == '\0');
171         return (res);
172 }
173
174 static int
175 count_dots(char *string) {
176         char *s;
177         int i = 0;
178
179         s = string;
180         while (*s != '\0') {
181                 if (*s == '.')
182                         i++;
183                 s++;
184         }
185         return (i);
186 }
187
188 static void
189 hex_dump(isc_buffer_t *b) {
190         unsigned int len;
191         isc_region_t r;
192
193         isc_buffer_usedregion(b, &r);
194
195         printf("%d bytes\n", r.length);
196         for (len = 0; len < r.length; len++) {
197                 printf("%02x ", r.base[len]);
198                 if (len % 16 == 15)
199                         printf("\n");
200         }
201         if (len % 16 != 0)
202                 printf("\n");
203 }
204
205 /*
206  * Append 'len' bytes of 'text' at '*p', failing with
207  * ISC_R_NOSPACE if that would advance p past 'end'.
208  */
209 static isc_result_t
210 append(const char *text, int len, char **p, char *end) {
211         if (len > end - *p)
212                 return (ISC_R_NOSPACE);
213         memcpy(*p, text, len);
214         *p += len;
215         return (ISC_R_SUCCESS);
216 }
217
218 static isc_result_t
219 reverse_octets(const char *in, char **p, char *end) {
220         char *dot = strchr(in, '.');
221         int len;
222         if (dot != NULL) {
223                 isc_result_t result;
224                 result = reverse_octets(dot + 1, p, end);
225                 if (result != ISC_R_SUCCESS)
226                         return (result);
227                 result = append(".", 1, p, end);
228                 if (result != ISC_R_SUCCESS)
229                         return (result);
230                 len = dot - in;
231         } else {
232                 len = strlen(in);
233         }
234         return (append(in, len, p, end));
235 }
236
237 isc_result_t
238 get_reverse(char *reverse, char *value, isc_boolean_t ip6_int,
239             isc_boolean_t strict)
240 {
241         int r;
242         isc_result_t result;
243         isc_netaddr_t addr;
244
245         addr.family = AF_INET6;
246         r = inet_pton(AF_INET6, value, &addr.type.in6);
247         if (r > 0) {
248                 /* This is a valid IPv6 address. */
249                 dns_fixedname_t fname;
250                 dns_name_t *name;
251                 unsigned int options = DNS_BYADDROPT_IPV6NIBBLE;
252
253                 if (ip6_int)
254                         options |= DNS_BYADDROPT_IPV6INT;
255                 dns_fixedname_init(&fname);
256                 name = dns_fixedname_name(&fname);
257                 result = dns_byaddr_createptrname2(&addr, options, name);
258                 if (result != ISC_R_SUCCESS)
259                         return (result);
260                 dns_name_format(name, reverse, MXNAME);
261                 return (ISC_R_SUCCESS);
262         } else {
263                 /*
264                  * Not a valid IPv6 address.  Assume IPv4.
265                  * If 'strict' is not set, construct the
266                  * in-addr.arpa name by blindly reversing
267                  * octets whether or not they look like integers,
268                  * so that this can be used for RFC2317 names
269                  * and such.
270                  */
271                 char *p = reverse;
272                 char *end = reverse + MXNAME;
273                 if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1)
274                         return (DNS_R_BADDOTTEDQUAD);
275                 result = reverse_octets(value, &p, end);
276                 if (result != ISC_R_SUCCESS)
277                         return (result);
278                 /* Append .in-addr.arpa. and a terminating NUL. */
279                 result = append(".in-addr.arpa.", 15, &p, end);
280                 if (result != ISC_R_SUCCESS)
281                         return (result);
282                 return (ISC_R_SUCCESS);
283         }
284 }
285
286 void
287 fatal(const char *format, ...) {
288         va_list args;
289
290         fprintf(stderr, "%s: ", progname);
291         va_start(args, format);
292         vfprintf(stderr, format, args);
293         va_end(args);
294         fprintf(stderr, "\n");
295         if (exitcode < 10)
296                 exitcode = 10;
297         if (fatalexit != 0)
298                 exitcode = fatalexit;
299         exit(exitcode);
300 }
301
302 void
303 debug(const char *format, ...) {
304         va_list args;
305
306         if (debugging) {
307                 va_start(args, format);
308                 vfprintf(stderr, format, args);
309                 va_end(args);
310                 fprintf(stderr, "\n");
311         }
312 }
313
314 void
315 check_result(isc_result_t result, const char *msg) {
316         if (result != ISC_R_SUCCESS) {
317                 fatal("%s: %s", msg, isc_result_totext(result));
318         }
319 }
320
321 /*
322  * Create a server structure, which is part of the lookup structure.
323  * This is little more than a linked list of servers to query in hopes
324  * of finding the answer the user is looking for
325  */
326 dig_server_t *
327 make_server(const char *servname) {
328         dig_server_t *srv;
329
330         REQUIRE(servname != NULL);
331
332         debug("make_server(%s)", servname);
333         srv = isc_mem_allocate(mctx, sizeof(struct dig_server));
334         if (srv == NULL)
335                 fatal("Memory allocation failure in %s:%d",
336                       __FILE__, __LINE__);
337         strncpy(srv->servername, servname, MXNAME);
338         srv->servername[MXNAME-1] = 0;
339         ISC_LINK_INIT(srv, link);
340         return (srv);
341 }
342
343 /*
344  * Produce a cloned server list.  The dest list must have already had
345  * ISC_LIST_INIT applied.
346  */
347 void
348 clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
349         dig_server_t *srv, *newsrv;
350
351         debug("clone_server_list()");
352         srv = ISC_LIST_HEAD(src);
353         while (srv != NULL) {
354                 newsrv = make_server(srv->servername);
355                 ISC_LINK_INIT(newsrv, link);
356                 ISC_LIST_ENQUEUE(*dest, newsrv, link);
357                 srv = ISC_LIST_NEXT(srv, link);
358         }
359 }
360
361 /*
362  * Create an empty lookup structure, which holds all the information needed
363  * to get an answer to a user's question.  This structure contains two
364  * linked lists: the server list (servers to query) and the query list
365  * (outstanding queries which have been made to the listed servers).
366  */
367 dig_lookup_t *
368 make_empty_lookup(void) {
369         dig_lookup_t *looknew;
370
371         debug("make_empty_lookup()");
372
373         INSIST(!free_now);
374
375         looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
376         if (looknew == NULL)
377                 fatal("Memory allocation failure in %s:%d",
378                        __FILE__, __LINE__);
379         looknew->pending = ISC_TRUE;
380         looknew->textname[0] = 0;
381         looknew->cmdline[0] = 0;
382         looknew->rdtype = dns_rdatatype_a;
383         looknew->qrdtype = dns_rdatatype_a;
384         looknew->rdclass = dns_rdataclass_in;
385         looknew->rdtypeset = ISC_FALSE;
386         looknew->rdclassset = ISC_FALSE;
387         looknew->sendspace = NULL;
388         looknew->sendmsg = NULL;
389         looknew->name = NULL;
390         looknew->oname = NULL;
391         looknew->timer = NULL;
392         looknew->xfr_q = NULL;
393         looknew->current_query = NULL;
394         looknew->doing_xfr = ISC_FALSE;
395         looknew->ixfr_serial = ISC_FALSE;
396         looknew->trace = ISC_FALSE;
397         looknew->trace_root = ISC_FALSE;
398         looknew->identify = ISC_FALSE;
399         looknew->identify_previous_line = ISC_FALSE;
400         looknew->ignore = ISC_FALSE;
401         looknew->servfail_stops = ISC_TRUE;
402         looknew->besteffort = ISC_TRUE;
403         looknew->dnssec = ISC_FALSE;
404         looknew->udpsize = 0;
405         looknew->recurse = ISC_TRUE;
406         looknew->aaonly = ISC_FALSE;
407         looknew->adflag = ISC_FALSE;
408         looknew->cdflag = ISC_FALSE;
409         looknew->ns_search_only = ISC_FALSE;
410         looknew->origin = NULL;
411         looknew->tsigctx = NULL;
412         looknew->querysig = NULL;
413         looknew->retries = tries;
414         looknew->nsfound = 0;
415         looknew->tcp_mode = ISC_FALSE;
416         looknew->ip6_int = ISC_FALSE;
417         looknew->comments = ISC_TRUE;
418         looknew->stats = ISC_TRUE;
419         looknew->section_question = ISC_TRUE;
420         looknew->section_answer = ISC_TRUE;
421         looknew->section_authority = ISC_TRUE;
422         looknew->section_additional = ISC_TRUE;
423         looknew->new_search = ISC_FALSE;
424         ISC_LINK_INIT(looknew, link);
425         ISC_LIST_INIT(looknew->q);
426         ISC_LIST_INIT(looknew->my_server_list);
427         return (looknew);
428 }
429
430 /*
431  * Clone a lookup, perhaps copying the server list.  This does not clone
432  * the query list, since it will be regenerated by the setup_lookup()
433  * function, nor does it queue up the new lookup for processing.
434  * Caution: If you don't clone the servers, you MUST clone the server
435  * list seperately from somewhere else, or construct it by hand.
436  */
437 dig_lookup_t *
438 clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
439         dig_lookup_t *looknew;
440
441         debug("clone_lookup()");
442
443         INSIST(!free_now);
444
445         looknew = make_empty_lookup();
446         INSIST(looknew != NULL);
447         strncpy(looknew->textname, lookold->textname, MXNAME);
448         strncpy(looknew->cmdline, lookold->cmdline, MXNAME);
449         looknew->textname[MXNAME-1] = 0;
450         looknew->rdtype = lookold->rdtype;
451         looknew->qrdtype = lookold->qrdtype;
452         looknew->rdclass = lookold->rdclass;
453         looknew->rdtypeset = lookold->rdtypeset;
454         looknew->rdclassset = lookold->rdclassset;
455         looknew->doing_xfr = lookold->doing_xfr;
456         looknew->ixfr_serial = lookold->ixfr_serial;
457         looknew->trace = lookold->trace;
458         looknew->trace_root = lookold->trace_root;
459         looknew->identify = lookold->identify;
460         looknew->identify_previous_line = lookold->identify_previous_line;
461         looknew->ignore = lookold->ignore;
462         looknew->servfail_stops = lookold->servfail_stops;
463         looknew->besteffort = lookold->besteffort;
464         looknew->dnssec = lookold->dnssec;
465         looknew->udpsize = lookold->udpsize;
466         looknew->recurse = lookold->recurse;
467         looknew->aaonly = lookold->aaonly;
468         looknew->adflag = lookold->adflag;
469         looknew->cdflag = lookold->cdflag;
470         looknew->ns_search_only = lookold->ns_search_only;
471         looknew->tcp_mode = lookold->tcp_mode;
472         looknew->comments = lookold->comments;
473         looknew->stats = lookold->stats;
474         looknew->section_question = lookold->section_question;
475         looknew->section_answer = lookold->section_answer;
476         looknew->section_authority = lookold->section_authority;
477         looknew->section_additional = lookold->section_additional;
478         looknew->retries = lookold->retries;
479         looknew->tsigctx = NULL;
480
481         if (servers)
482                 clone_server_list(lookold->my_server_list,
483                                   &looknew->my_server_list);
484         return (looknew);
485 }
486
487 /*
488  * Requeue a lookup for further processing, perhaps copying the server
489  * list.  The new lookup structure is returned to the caller, and is
490  * queued for processing.  If servers are not cloned in the requeue, they
491  * must be added before allowing the current event to complete, since the
492  * completion of the event may result in the next entry on the lookup
493  * queue getting run.
494  */
495 dig_lookup_t *
496 requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
497         dig_lookup_t *looknew;
498
499         debug("requeue_lookup()");
500
501         lookup_counter++;
502         if (lookup_counter > LOOKUP_LIMIT)
503                 fatal("Too many lookups");
504
505         looknew = clone_lookup(lookold, servers);
506         INSIST(looknew != NULL);
507
508         debug("before insertion, init@%p -> %p, new@%p -> %p",
509               lookold, lookold->link.next, looknew, looknew->link.next);
510         ISC_LIST_PREPEND(lookup_list, looknew, link);
511         debug("after insertion, init -> %p, new = %p, new -> %p",
512               lookold, looknew, looknew->link.next);
513         return (looknew);
514 }
515
516
517 static void
518 setup_text_key(void) {
519         isc_result_t result;
520         dns_name_t keyname;
521         isc_buffer_t secretbuf;
522         int secretsize;
523         unsigned char *secretstore;
524
525         debug("setup_text_key()");
526         result = isc_buffer_allocate(mctx, &namebuf, MXNAME);
527         check_result(result, "isc_buffer_allocate");
528         dns_name_init(&keyname, NULL);
529         check_result(result, "dns_name_init");
530         isc_buffer_putstr(namebuf, keynametext);
531         secretsize = strlen(keysecret) * 3 / 4;
532         secretstore = isc_mem_allocate(mctx, secretsize);
533         if (secretstore == NULL)
534                 fatal("Memory allocation failure in %s:%d",
535                       __FILE__, __LINE__);
536         isc_buffer_init(&secretbuf, secretstore, secretsize);
537         result = isc_base64_decodestring(keysecret, &secretbuf);
538         if (result != ISC_R_SUCCESS)
539                 goto failure;
540         
541         secretsize = isc_buffer_usedlength(&secretbuf);
542
543         result = dns_name_fromtext(&keyname, namebuf,
544                                    dns_rootname, ISC_FALSE,
545                                    namebuf);
546         if (result != ISC_R_SUCCESS)
547                 goto failure;
548
549         result = dns_tsigkey_create(&keyname, dns_tsig_hmacmd5_name,
550                                     secretstore, secretsize,
551                                     ISC_FALSE, NULL, 0, 0, mctx,
552                                     NULL, &key);
553  failure:
554         if (result != ISC_R_SUCCESS)
555                 printf(";; Couldn't create key %s: %s\n",
556                        keynametext, isc_result_totext(result));
557
558         isc_mem_free(mctx, secretstore);
559         dns_name_invalidate(&keyname);
560         isc_buffer_free(&namebuf);
561 }
562
563 static void
564 setup_file_key(void) {
565         isc_result_t result;
566         dst_key_t *dstkey = NULL;
567
568         debug("setup_file_key()");
569         result = dst_key_fromnamedfile(keyfile, DST_TYPE_PRIVATE,
570                                        mctx, &dstkey);
571         if (result != ISC_R_SUCCESS) {
572                 fprintf(stderr, "Couldn't read key from %s: %s\n",
573                         keyfile, isc_result_totext(result));
574                 goto failure;
575         }
576
577         result = dns_tsigkey_createfromkey(dst_key_name(dstkey),
578                                            dns_tsig_hmacmd5_name,
579                                            dstkey, ISC_FALSE, NULL, 0, 0,
580                                            mctx, NULL, &key);
581         if (result != ISC_R_SUCCESS) {
582                 printf(";; Couldn't create key %s: %s\n",
583                        keynametext, isc_result_totext(result));
584                 goto failure;
585         }
586         dstkey = NULL;
587  failure:
588         if (dstkey != NULL)
589                 dst_key_free(&dstkey);
590 }
591
592 static dig_searchlist_t *
593 make_searchlist_entry(char *domain) {
594         dig_searchlist_t *search;
595         search = isc_mem_allocate(mctx, sizeof(*search));
596         if (search == NULL)
597                 fatal("Memory allocation failure in %s:%d",
598                       __FILE__, __LINE__);
599         strncpy(search->origin, domain, MXNAME);
600         search->origin[MXNAME-1] = 0;
601         ISC_LINK_INIT(search, link);
602         return (search);
603 }
604
605 /*
606  * Setup the system as a whole, reading key information and resolv.conf
607  * settings.
608  */
609 void
610 setup_system(void) {
611         char rcinput[MXNAME];
612         FILE *fp;
613         char *ptr;
614         dig_server_t *srv;
615         dig_searchlist_t *search, *domain = NULL;
616         isc_boolean_t get_servers;
617         char *input;
618
619         debug("setup_system()");
620
621         free_now = ISC_FALSE;
622         get_servers = ISC_TF(server_list.head == NULL);
623         fp = fopen(RESOLV_CONF, "r");
624         /* XXX Use lwres resolv.conf reader */
625         if (fp == NULL)
626                 goto no_file;
627
628         while (fgets(rcinput, MXNAME, fp) != 0) {
629                 input = rcinput;
630                 ptr = next_token(&input, " \t\r\n");
631                 if (ptr != NULL) {
632                         if (get_servers &&
633                             strcasecmp(ptr, "nameserver") == 0) {
634                                 debug("got a nameserver line");
635                                 ptr = next_token(&input, " \t\r\n");
636                                 if (ptr != NULL) {
637                                         srv = make_server(ptr);
638                                         ISC_LIST_APPEND(server_list, srv, link);
639                                 }
640                         } else if (strcasecmp(ptr, "options") == 0) {
641                                 ptr = next_token(&input, " \t\r\n");
642                                 if (ptr != NULL) {
643                                         if (strncasecmp(ptr, "ndots:", 6) == 0
644                                             && ndots == -1)
645                                         {
646                                                 ndots = atoi(&ptr[6]);
647                                                 debug("ndots is %d.", ndots);
648                                         }
649                                 }
650                         } else if (strcasecmp(ptr, "search") == 0){
651                                 while ((ptr = next_token(&input, " \t\r\n"))
652                                        != NULL) {
653                                         debug("adding search %s", ptr);
654                                         search = make_searchlist_entry(ptr);
655                                         ISC_LIST_INITANDAPPEND(search_list,
656                                                                search, link);
657                                 }
658                         } else if (strcasecmp(ptr, "domain") == 0) {
659                                 while ((ptr = next_token(&input, " \t\r\n"))
660                                        != NULL) {
661                                         if (domain != NULL)
662                                                 isc_mem_free(mctx, domain);
663                                         domain = make_searchlist_entry(ptr);
664                                 }
665                         }
666                 }
667         }
668         fclose(fp);
669  no_file:
670
671         if (ISC_LIST_EMPTY(search_list) && domain != NULL) {
672                 ISC_LIST_INITANDAPPEND(search_list, domain, link);
673                 domain = NULL;
674         }
675         if (domain != NULL)
676                 isc_mem_free(mctx, domain);
677         
678         if (ndots == -1)
679                 ndots = 1;
680
681         if (server_list.head == NULL) {
682                 srv = make_server("127.0.0.1");
683                 ISC_LIST_APPEND(server_list, srv, link);
684         }
685
686         if (keyfile[0] != 0)
687                 setup_file_key();
688         else if (keysecret[0] != 0)
689                 setup_text_key();
690 }
691
692 static void
693 clear_searchlist(void) {
694         dig_searchlist_t *search;
695         while ((search = ISC_LIST_HEAD(search_list)) != NULL) {
696                 ISC_LIST_UNLINK(search_list, search, link);
697                 isc_mem_free(mctx, search);
698         }
699 }
700
701 /*
702  * Override the search list derived from resolv.conf by 'domain'.
703  */
704 void
705 set_search_domain(char *domain) {
706         dig_searchlist_t *search;
707         
708         clear_searchlist();
709         search = make_searchlist_entry(domain);
710         ISC_LIST_APPEND(search_list, search, link);
711 }
712
713 /*
714  * Setup the ISC and DNS libraries for use by the system.
715  */
716 void
717 setup_libs(void) {
718         isc_result_t result;
719
720         debug("setup_libs()");
721
722         result = isc_net_probeipv4();
723         if (result == ISC_R_SUCCESS)
724                 have_ipv4 = ISC_TRUE;
725
726         result = isc_net_probeipv6();
727         if (result == ISC_R_SUCCESS)
728                 have_ipv6 = ISC_TRUE;
729         if (!have_ipv6 && !have_ipv4)
730                 fatal("can't find either v4 or v6 networking");
731
732         result = isc_mem_create(0, 0, &mctx);
733         check_result(result, "isc_mem_create");
734
735         result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
736         check_result(result, "isc_taskmgr_create");
737
738         result = isc_task_create(taskmgr, 0, &global_task);
739         check_result(result, "isc_task_create");
740
741         result = isc_timermgr_create(mctx, &timermgr);
742         check_result(result, "isc_timermgr_create");
743
744         result = isc_socketmgr_create(mctx, &socketmgr);
745         check_result(result, "isc_socketmgr_create");
746
747         result = isc_entropy_create(mctx, &entp);
748         check_result(result, "isc_entropy_create");
749
750         result = dst_lib_init(mctx, entp, 0);
751         check_result(result, "dst_lib_init");
752         is_dst_up = ISC_TRUE;
753
754         result = isc_mempool_create(mctx, COMMSIZE, &commctx);
755         check_result(result, "isc_mempool_create");
756         isc_mempool_setname(commctx, "COMMPOOL");
757         /*
758          * 6 and 2 set as reasonable parameters for 3 or 4 nameserver
759          * systems.
760          */
761         isc_mempool_setfreemax(commctx, 6);
762         isc_mempool_setfillcount(commctx, 2);
763
764         result = isc_mutex_init(&lookup_lock);
765         check_result(result, "isc_mutex_init");
766
767         dns_result_register();
768 }
769
770 /*
771  * Add EDNS0 option record to a message.  Currently, the only supported
772  * options are UDP buffer size and the DO bit.
773  */
774 static void
775 add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_boolean_t dnssec) {
776         dns_rdataset_t *rdataset = NULL;
777         dns_rdatalist_t *rdatalist = NULL;
778         dns_rdata_t *rdata = NULL;
779         isc_result_t result;
780
781         debug("add_opt()");
782         result = dns_message_gettemprdataset(msg, &rdataset);
783         check_result(result, "dns_message_gettemprdataset");
784         dns_rdataset_init(rdataset);
785         result = dns_message_gettemprdatalist(msg, &rdatalist);
786         check_result(result, "dns_message_gettemprdatalist");
787         result = dns_message_gettemprdata(msg, &rdata);
788         check_result(result, "dns_message_gettemprdata");
789
790         debug("setting udp size of %d", udpsize);
791         rdatalist->type = dns_rdatatype_opt;
792         rdatalist->covers = 0;
793         rdatalist->rdclass = udpsize;
794         rdatalist->ttl = 0;
795         if (dnssec)
796                 rdatalist->ttl = DNS_MESSAGEEXTFLAG_DO;
797         rdata->data = NULL;
798         rdata->length = 0;
799         ISC_LIST_INIT(rdatalist->rdata);
800         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
801         dns_rdatalist_tordataset(rdatalist, rdataset);
802         result = dns_message_setopt(msg, rdataset);
803         check_result(result, "dns_message_setopt");
804 }
805
806 /*
807  * Add a question section to a message, asking for the specified name,
808  * type, and class.
809  */
810 static void
811 add_question(dns_message_t *message, dns_name_t *name,
812              dns_rdataclass_t rdclass, dns_rdatatype_t rdtype)
813 {
814         dns_rdataset_t *rdataset;
815         isc_result_t result;
816
817         debug("add_question()");
818         rdataset = NULL;
819         result = dns_message_gettemprdataset(message, &rdataset);
820         check_result(result, "dns_message_gettemprdataset()");
821         dns_rdataset_init(rdataset);
822         dns_rdataset_makequestion(rdataset, rdclass, rdtype);
823         ISC_LIST_APPEND(name->list, rdataset, link);
824 }
825
826 /*
827  * Check if we're done with all the queued lookups, which is true iff
828  * all sockets, sends, and recvs are accounted for (counters == 0),
829  * and the lookup list is empty.
830  * If we are done, pass control back out to dighost_shutdown() (which is
831  * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
832  * a whole or reseed the lookup list.
833  */
834 static void
835 check_if_done(void) {
836         debug("check_if_done()");
837         debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
838         if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
839             sendcount == 0) {
840                 INSIST(sockcount == 0);
841                 INSIST(recvcount == 0);
842                 debug("shutting down");
843                 dighost_shutdown();
844         }
845 }
846
847 /*
848  * Clear out a query when we're done with it.  WARNING: This routine
849  * WILL invalidate the query pointer.
850  */
851 static void
852 clear_query(dig_query_t *query) {
853         dig_lookup_t *lookup;
854
855         REQUIRE(query != NULL);
856
857         debug("clear_query(%p)", query);
858
859         lookup = query->lookup;
860
861         if (lookup->current_query == query)
862                 lookup->current_query = NULL;
863
864         ISC_LIST_UNLINK(lookup->q, query, link);
865         if (ISC_LINK_LINKED(&query->recvbuf, link))
866                 ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf,
867                                  link);
868         if (ISC_LINK_LINKED(&query->lengthbuf, link))
869                 ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf,
870                                  link);
871         INSIST(query->recvspace != NULL);
872         if (query->sock != NULL) {
873                 isc_socket_detach(&query->sock);
874                 sockcount--;
875                 debug("sockcount=%d", sockcount);
876         }
877         isc_mempool_put(commctx, query->recvspace);
878         isc_buffer_invalidate(&query->recvbuf);
879         isc_buffer_invalidate(&query->lengthbuf);
880         isc_mem_free(mctx, query);
881 }
882
883 /*
884  * Try and clear out a lookup if we're done with it.  Return ISC_TRUE if
885  * the lookup was successfully cleared.  If ISC_TRUE is returned, the
886  * lookup pointer has been invalidated.
887  */
888 static isc_boolean_t
889 try_clear_lookup(dig_lookup_t *lookup) {
890         dig_server_t *s;
891         dig_query_t *q;
892         void *ptr;
893
894         REQUIRE(lookup != NULL);
895
896         debug("try_clear_lookup(%p)", lookup);
897
898         if (ISC_LIST_HEAD(lookup->q) != NULL) {
899                 if (debugging) {
900                         q = ISC_LIST_HEAD(lookup->q);
901                         while (q != NULL) {
902                                 debug("query to %s still pending",
903                                        q->servname);
904                                 q = ISC_LIST_NEXT(q, link);
905                         }
906                 return (ISC_FALSE);
907                 }
908         }
909         /*
910          * At this point, we know there are no queries on the lookup,
911          * so can make it go away also.
912          */
913         debug("cleared");
914         s = ISC_LIST_HEAD(lookup->my_server_list);
915         while (s != NULL) {
916                 debug("freeing server %p belonging to %p",
917                       s, lookup);
918                 ptr = s;
919                 s = ISC_LIST_NEXT(s, link);
920                 ISC_LIST_DEQUEUE(lookup->my_server_list,
921                                  (dig_server_t *)ptr, link);
922                 isc_mem_free(mctx, ptr);
923         }
924         if (lookup->sendmsg != NULL)
925                 dns_message_destroy(&lookup->sendmsg);
926         if (lookup->querysig != NULL) {
927                 debug("freeing buffer %p", lookup->querysig);
928                 isc_buffer_free(&lookup->querysig);
929         }
930         if (lookup->timer != NULL)
931                 isc_timer_detach(&lookup->timer);
932         if (lookup->sendspace != NULL)
933                 isc_mempool_put(commctx, lookup->sendspace);
934
935         if (lookup->tsigctx != NULL)
936                 dst_context_destroy(&lookup->tsigctx);
937
938         isc_mem_free(mctx, lookup);
939         return (ISC_TRUE);
940 }
941
942
943 /*
944  * If we can, start the next lookup in the queue running.
945  * This assumes that the lookup on the head of the queue hasn't been
946  * started yet.  It also removes the lookup from the head of the queue,
947  * setting the current_lookup pointer pointing to it.
948  */
949 void
950 start_lookup(void) {
951         debug("start_lookup()");
952         if (cancel_now)
953                 return;
954
955         /*
956          * If there's a current lookup running, we really shouldn't get
957          * here.
958          */
959         INSIST(current_lookup == NULL);
960
961         current_lookup = ISC_LIST_HEAD(lookup_list);
962         /*
963          * Put the current lookup somewhere so cancel_all can find it
964          */
965         if (current_lookup != NULL) {
966                 ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
967                 setup_lookup(current_lookup);
968                 do_lookup(current_lookup);
969         } else {
970                 check_if_done();
971         }
972 }
973
974 /*
975  * If we can, clear the current lookup and start the next one running.
976  * This calls try_clear_lookup, so may invalidate the lookup pointer.
977  */
978 static void
979 check_next_lookup(dig_lookup_t *lookup) {
980
981         INSIST(!free_now);
982
983         debug("check_next_lookup(%p)", lookup);
984
985         if (ISC_LIST_HEAD(lookup->q) != NULL) {
986                 debug("still have a worker");
987                 return;
988         }
989         if (try_clear_lookup(lookup)) {
990                 current_lookup = NULL;
991                 start_lookup();
992         }
993 }
994
995 /*
996  * Create and queue a new lookup as a followup to the current lookup,
997  * based on the supplied message and section.  This is used in trace and
998  * name server search modes to start a new lookup using servers from
999  * NS records in a reply. Returns the number of followup lookups made.
1000  */
1001 static int
1002 followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section)
1003 {
1004         dig_lookup_t *lookup = NULL;
1005         dig_server_t *srv = NULL;
1006         dns_rdataset_t *rdataset = NULL;
1007         dns_rdata_t rdata = DNS_RDATA_INIT;
1008         dns_name_t *name = NULL;
1009         isc_result_t result;
1010         isc_boolean_t success = ISC_FALSE;
1011         int numLookups = 0;
1012
1013         INSIST(!free_now);
1014
1015         debug("following up %s", query->lookup->textname);
1016         
1017         for (result = dns_message_firstname(msg, section);
1018              result == ISC_R_SUCCESS;
1019              result = dns_message_nextname(msg, section))
1020         {
1021                 name = NULL;
1022                 dns_message_currentname(msg, section, &name);
1023
1024                 rdataset = NULL;
1025                 result = dns_message_findtype(name, dns_rdatatype_ns, 0,
1026                                               &rdataset);
1027                 if (result != ISC_R_SUCCESS)
1028                         continue;
1029
1030                 debug("found NS set");
1031
1032                 for (result = dns_rdataset_first(rdataset);
1033                      result == ISC_R_SUCCESS;
1034                      result = dns_rdataset_next(rdataset))
1035                 {
1036                         char namestr[DNS_NAME_FORMATSIZE];
1037                         dns_rdata_ns_t ns;
1038
1039                         if (query->lookup->trace_root &&
1040                             query->lookup->nsfound >= MXSERV)
1041                                 break;
1042
1043                         dns_rdataset_current(rdataset, &rdata);
1044
1045                         query->lookup->nsfound++;
1046                         (void)dns_rdata_tostruct(&rdata, &ns, NULL);
1047                         dns_name_format(&ns.name, namestr, sizeof(namestr));
1048                         dns_rdata_freestruct(&ns);
1049
1050                         /* Initialize lookup if we've not yet */
1051                         debug("found NS %d %s", numLookups, namestr);
1052                         numLookups++;
1053                         if (!success) {
1054                                 success = ISC_TRUE;
1055                                 lookup_counter++;
1056                                 lookup = requeue_lookup(query->lookup,
1057                                                         ISC_FALSE);
1058                                 cancel_lookup(query->lookup);
1059                                 lookup->doing_xfr = ISC_FALSE;
1060                                 if (!lookup->trace_root &&
1061                                     section == DNS_SECTION_ANSWER)
1062                                         lookup->trace = ISC_FALSE;
1063                                 else
1064                                         lookup->trace = query->lookup->trace;
1065                                 lookup->ns_search_only =
1066                                         query->lookup->ns_search_only;
1067                                 lookup->trace_root = ISC_FALSE;
1068                         }
1069                         srv = make_server(namestr);
1070                         debug("adding server %s", srv->servername);
1071                         ISC_LIST_APPEND(lookup->my_server_list, srv, link);
1072                         dns_rdata_reset(&rdata);
1073                 }
1074         }
1075
1076         if (lookup == NULL &&
1077             section == DNS_SECTION_ANSWER &&
1078             (query->lookup->trace || query->lookup->ns_search_only))
1079                 return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY));
1080
1081         return numLookups;
1082 }
1083
1084 /*
1085  * Create and queue a new lookup using the next origin from the search
1086  * list, read in setup_system().
1087  *
1088  * Return ISC_TRUE iff there was another searchlist entry.
1089  */
1090 static isc_boolean_t
1091 next_origin(dns_message_t *msg, dig_query_t *query) {
1092         dig_lookup_t *lookup;
1093
1094         UNUSED(msg);
1095
1096         INSIST(!free_now);
1097
1098         debug("next_origin()");
1099         debug("following up %s", query->lookup->textname);
1100
1101         if (!usesearch)
1102                 /*
1103                  * We're not using a search list, so don't even think
1104                  * about finding the next entry.
1105                  */
1106                 return (ISC_FALSE);
1107         if (query->lookup->origin == NULL)
1108                 /*
1109                  * Then we just did rootorg; there's nothing left.
1110                  */
1111                 return (ISC_FALSE);
1112         lookup = requeue_lookup(query->lookup, ISC_TRUE);
1113         lookup->origin = ISC_LIST_NEXT(query->lookup->origin, link);
1114         cancel_lookup(query->lookup);
1115         return (ISC_TRUE);
1116 }
1117
1118 /*
1119  * Insert an SOA record into the sendmessage in a lookup.  Used for
1120  * creating IXFR queries.
1121  */
1122 static void
1123 insert_soa(dig_lookup_t *lookup) {
1124         isc_result_t result;
1125         dns_rdata_soa_t soa;
1126         dns_rdata_t *rdata = NULL;
1127         dns_rdatalist_t *rdatalist = NULL;
1128         dns_rdataset_t *rdataset = NULL;
1129         dns_name_t *soaname = NULL;
1130
1131         debug("insert_soa()");
1132         soa.mctx = mctx;
1133         soa.serial = lookup->ixfr_serial;
1134         soa.refresh = 0;
1135         soa.retry = 0;
1136         soa.expire = 0;
1137         soa.minimum = 0;
1138         soa.common.rdclass = lookup->rdclass;
1139         soa.common.rdtype = dns_rdatatype_soa;
1140
1141         dns_name_init(&soa.origin, NULL);
1142         dns_name_init(&soa.contact, NULL);
1143
1144         dns_name_clone(dns_rootname, &soa.origin);
1145         dns_name_clone(dns_rootname, &soa.contact);
1146
1147         isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
1148                         sizeof(lookup->rdatastore));
1149
1150         result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
1151         check_result(result, "dns_message_gettemprdata");
1152
1153         result = dns_rdata_fromstruct(rdata, lookup->rdclass,
1154                                       dns_rdatatype_soa, &soa,
1155                                       &lookup->rdatabuf);
1156         check_result(result, "isc_rdata_fromstruct");
1157
1158         result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
1159         check_result(result, "dns_message_gettemprdatalist");
1160
1161         result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
1162         check_result(result, "dns_message_gettemprdataset");
1163
1164         dns_rdatalist_init(rdatalist);
1165         rdatalist->type = dns_rdatatype_soa;
1166         rdatalist->rdclass = lookup->rdclass;
1167         rdatalist->covers = 0;
1168         rdatalist->ttl = 0;
1169         ISC_LIST_INIT(rdatalist->rdata);
1170         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1171
1172         dns_rdataset_init(rdataset);
1173         dns_rdatalist_tordataset(rdatalist, rdataset);
1174
1175         result = dns_message_gettempname(lookup->sendmsg, &soaname);
1176         check_result(result, "dns_message_gettempname");
1177         dns_name_init(soaname, NULL);
1178         dns_name_clone(lookup->name, soaname);
1179         ISC_LIST_INIT(soaname->list);
1180         ISC_LIST_APPEND(soaname->list, rdataset, link);
1181         dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
1182 }
1183
1184 /*
1185  * Setup the supplied lookup structure, making it ready to start sending
1186  * queries to servers.  Create and initialize the message to be sent as
1187  * well as the query structures and buffer space for the replies.  If the
1188  * server list is empty, clone it from the system default list.
1189  */
1190 void
1191 setup_lookup(dig_lookup_t *lookup) {
1192         isc_result_t result;
1193         isc_uint32_t id;
1194         int len;
1195         dig_server_t *serv;
1196         dig_query_t *query;
1197         isc_buffer_t b;
1198         dns_compress_t cctx;
1199         char store[MXNAME];
1200
1201         REQUIRE(lookup != NULL);
1202         INSIST(!free_now);
1203
1204         debug("setup_lookup(%p)", lookup);
1205
1206         result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
1207                                     &lookup->sendmsg);
1208         check_result(result, "dns_message_create");
1209
1210         if (lookup->new_search) {
1211                 debug("resetting lookup counter.");
1212                 lookup_counter = 0;
1213         }
1214
1215         if (ISC_LIST_EMPTY(lookup->my_server_list)) {
1216                 debug("cloning server list");
1217                 clone_server_list(server_list, &lookup->my_server_list);
1218         }
1219         result = dns_message_gettempname(lookup->sendmsg, &lookup->name);
1220         check_result(result, "dns_message_gettempname");
1221         dns_name_init(lookup->name, NULL);
1222
1223         isc_buffer_init(&lookup->namebuf, lookup->namespace,
1224                         sizeof(lookup->namespace));
1225         isc_buffer_init(&lookup->onamebuf, lookup->onamespace,
1226                         sizeof(lookup->onamespace));
1227
1228         /*
1229          * If the name has too many dots, force the origin to be NULL
1230          * (which produces an absolute lookup).  Otherwise, take the origin
1231          * we have if there's one in the struct already.  If it's NULL,
1232          * take the first entry in the searchlist iff either usesearch
1233          * is TRUE or we got a domain line in the resolv.conf file.
1234          */
1235         /* XXX New search here? */
1236         if ((count_dots(lookup->textname) >= ndots) || !usesearch)
1237                 lookup->origin = NULL; /* Force abs lookup */
1238         else if (lookup->origin == NULL && lookup->new_search && usesearch) {
1239                 lookup->origin = ISC_LIST_HEAD(search_list);
1240         }
1241         if (lookup->origin != NULL) {
1242                 debug("trying origin %s", lookup->origin->origin);
1243                 result = dns_message_gettempname(lookup->sendmsg,
1244                                                  &lookup->oname);
1245                 check_result(result, "dns_message_gettempname");
1246                 dns_name_init(lookup->oname, NULL);
1247                 /* XXX Helper funct to conv char* to name? */
1248                 len = strlen(lookup->origin->origin);
1249                 isc_buffer_init(&b, lookup->origin->origin, len);
1250                 isc_buffer_add(&b, len);
1251                 result = dns_name_fromtext(lookup->oname, &b, dns_rootname,
1252                                            ISC_FALSE, &lookup->onamebuf);
1253                 if (result != ISC_R_SUCCESS) {
1254                         dns_message_puttempname(lookup->sendmsg,
1255                                                 &lookup->name);
1256                         dns_message_puttempname(lookup->sendmsg,
1257                                                 &lookup->oname);
1258                         fatal("'%s' is not in legal name syntax (%s)",
1259                               lookup->origin->origin,
1260                               isc_result_totext(result));
1261                 }
1262                 if (lookup->trace && lookup->trace_root) {
1263                         dns_name_clone(dns_rootname, lookup->name);
1264                 } else {
1265                         len = strlen(lookup->textname);
1266                         isc_buffer_init(&b, lookup->textname, len);
1267                         isc_buffer_add(&b, len);
1268                         result = dns_name_fromtext(lookup->name, &b,
1269                                                    lookup->oname, ISC_FALSE,
1270                                                    &lookup->namebuf);
1271                 }
1272                 if (result != ISC_R_SUCCESS) {
1273                         dns_message_puttempname(lookup->sendmsg,
1274                                                 &lookup->name);
1275                         dns_message_puttempname(lookup->sendmsg,
1276                                                 &lookup->oname);
1277                         fatal("'%s' is not in legal name syntax (%s)",
1278                               lookup->textname, isc_result_totext(result));
1279                 }
1280                 dns_message_puttempname(lookup->sendmsg, &lookup->oname);
1281         } else {
1282                 debug("using root origin");
1283                 if (lookup->trace && lookup->trace_root)
1284                         dns_name_clone(dns_rootname, lookup->name);
1285                 else {
1286                         len = strlen(lookup->textname);
1287                         isc_buffer_init(&b, lookup->textname, len);
1288                         isc_buffer_add(&b, len);
1289                         result = dns_name_fromtext(lookup->name, &b,
1290                                                    dns_rootname,
1291                                                    ISC_FALSE,
1292                                                    &lookup->namebuf);
1293                 }
1294                 if (result != ISC_R_SUCCESS) {
1295                         dns_message_puttempname(lookup->sendmsg,
1296                                                 &lookup->name);
1297                         isc_buffer_init(&b, store, MXNAME);
1298                         fatal("'%s' is not a legal name "
1299                               "(%s)", lookup->textname,
1300                               isc_result_totext(result));
1301                 }
1302         }
1303         dns_name_format(lookup->name, store, sizeof(store));
1304         trying(store, lookup);
1305         INSIST(dns_name_isabsolute(lookup->name));
1306
1307         isc_random_get(&id);
1308         lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
1309         lookup->sendmsg->opcode = dns_opcode_query;
1310         lookup->msgcounter = 0;
1311         /*
1312          * If this is a trace request, completely disallow recursion, since
1313          * it's meaningless for traces.
1314          */
1315         if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root))
1316                 lookup->recurse = ISC_FALSE;
1317
1318         if (lookup->recurse &&
1319             lookup->rdtype != dns_rdatatype_axfr &&
1320             lookup->rdtype != dns_rdatatype_ixfr) {
1321                 debug("recursive query");
1322                 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD;
1323         }
1324
1325         /* XXX aaflag */
1326         if (lookup->aaonly) {
1327                 debug("AA query");
1328                 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA;
1329         }
1330
1331         if (lookup->adflag) {
1332                 debug("AD query");
1333                 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD;
1334         }
1335
1336         if (lookup->cdflag) {
1337                 debug("CD query");
1338                 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD;
1339         }
1340
1341         dns_message_addname(lookup->sendmsg, lookup->name,
1342                             DNS_SECTION_QUESTION);
1343
1344         if (lookup->trace && lookup->trace_root) {
1345                 lookup->qrdtype = lookup->rdtype;
1346                 lookup->rdtype = dns_rdatatype_ns;
1347         }
1348
1349         if ((lookup->rdtype == dns_rdatatype_axfr) ||
1350             (lookup->rdtype == dns_rdatatype_ixfr)) {
1351                 lookup->doing_xfr = ISC_TRUE;
1352                 /*
1353                  * Force TCP mode if we're doing an xfr.
1354                  * XXX UDP ixfr's would be useful
1355                  */
1356                 lookup->tcp_mode = ISC_TRUE;
1357         }
1358
1359         add_question(lookup->sendmsg, lookup->name, lookup->rdclass,
1360                      lookup->rdtype);
1361
1362         /* add_soa */
1363         if (lookup->rdtype == dns_rdatatype_ixfr)
1364                 insert_soa(lookup);
1365
1366         /* XXX Insist this? */
1367         lookup->tsigctx = NULL;
1368         lookup->querysig = NULL;
1369         if (key != NULL) {
1370                 debug("initializing keys");
1371                 result = dns_message_settsigkey(lookup->sendmsg, key);
1372                 check_result(result, "dns_message_settsigkey");
1373         }
1374
1375         lookup->sendspace = isc_mempool_get(commctx);
1376         if (lookup->sendspace == NULL)
1377                 fatal("memory allocation failure");
1378
1379         result = dns_compress_init(&cctx, -1, mctx);
1380         check_result(result, "dns_compress_init");
1381
1382         debug("starting to render the message");
1383         isc_buffer_init(&lookup->sendbuf, lookup->sendspace, COMMSIZE);
1384         result = dns_message_renderbegin(lookup->sendmsg, &cctx,
1385                                          &lookup->sendbuf);
1386         check_result(result, "dns_message_renderbegin");
1387         if (lookup->udpsize > 0 || lookup->dnssec) {
1388                 if (lookup->udpsize == 0)
1389                         lookup->udpsize = 2048;
1390                 add_opt(lookup->sendmsg, lookup->udpsize, lookup->dnssec);
1391         }
1392
1393         result = dns_message_rendersection(lookup->sendmsg,
1394                                            DNS_SECTION_QUESTION, 0);
1395         check_result(result, "dns_message_rendersection");
1396         result = dns_message_rendersection(lookup->sendmsg,
1397                                            DNS_SECTION_AUTHORITY, 0);
1398         check_result(result, "dns_message_rendersection");
1399         result = dns_message_renderend(lookup->sendmsg);
1400         check_result(result, "dns_message_renderend");
1401         debug("done rendering");
1402
1403         dns_compress_invalidate(&cctx);
1404
1405         /*
1406          * Force TCP mode if the request is larger than 512 bytes.
1407          */
1408         if (isc_buffer_usedlength(&lookup->sendbuf) > 512)
1409                 lookup->tcp_mode = ISC_TRUE;
1410
1411         lookup->pending = ISC_FALSE;
1412
1413         for (serv = ISC_LIST_HEAD(lookup->my_server_list);
1414              serv != NULL;
1415              serv = ISC_LIST_NEXT(serv, link)) {
1416                 query = isc_mem_allocate(mctx, sizeof(dig_query_t));
1417                 if (query == NULL)
1418                         fatal("Memory allocation failure in %s:%d",
1419                               __FILE__, __LINE__);
1420                 debug("create query %p linked to lookup %p",
1421                        query, lookup);
1422                 query->lookup = lookup;
1423                 query->waiting_connect = ISC_FALSE;
1424                 query->recv_made = ISC_FALSE;
1425                 query->first_pass = ISC_TRUE;
1426                 query->first_soa_rcvd = ISC_FALSE;
1427                 query->second_rr_rcvd = ISC_FALSE;
1428                 query->first_repeat_rcvd = ISC_FALSE;
1429                 query->warn_id = ISC_TRUE;
1430                 query->first_rr_serial = 0;
1431                 query->second_rr_serial = 0;
1432                 query->servname = serv->servername;
1433                 query->rr_count = 0;
1434                 ISC_LINK_INIT(query, link);
1435                 ISC_LIST_INIT(query->recvlist);
1436                 ISC_LIST_INIT(query->lengthlist);
1437                 query->sock = NULL;
1438                 query->recvspace = isc_mempool_get(commctx);
1439                 if (query->recvspace == NULL)
1440                         fatal("memory allocation failure");
1441
1442                 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
1443                 isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
1444                 isc_buffer_init(&query->slbuf, query->slspace, 2);
1445
1446                 ISC_LINK_INIT(query, link);
1447                 ISC_LIST_ENQUEUE(lookup->q, query, link);
1448         }
1449         /* XXX qrflag, print_query, etc... */
1450         if (!ISC_LIST_EMPTY(lookup->q) && qr) {
1451                 printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg,
1452                              ISC_TRUE);
1453         }
1454 }
1455
1456 /*
1457  * Event handler for send completion.  Track send counter, and clear out
1458  * the query if the send was canceled.
1459  */
1460 static void
1461 send_done(isc_task_t *_task, isc_event_t *event) {
1462         REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1463
1464         UNUSED(_task);
1465
1466         LOCK_LOOKUP;
1467
1468         isc_event_free(&event);
1469
1470         debug("send_done()");
1471         sendcount--;
1472         debug("sendcount=%d", sendcount);
1473         INSIST(sendcount >= 0);
1474         check_if_done();
1475         UNLOCK_LOOKUP;
1476 }
1477
1478 /*
1479  * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
1480  * IO sockets.  The cancel handlers should take care of cleaning up the
1481  * query and lookup structures
1482  */
1483 static void
1484 cancel_lookup(dig_lookup_t *lookup) {
1485         dig_query_t *query, *next;
1486
1487         debug("cancel_lookup()");
1488         query = ISC_LIST_HEAD(lookup->q);
1489         while (query != NULL) {
1490                 next = ISC_LIST_NEXT(query, link);
1491                 if (query->sock != NULL) {
1492                         isc_socket_cancel(query->sock, global_task,
1493                                           ISC_SOCKCANCEL_ALL);
1494                         check_if_done();
1495                 } else {
1496                         clear_query(query);
1497                 }
1498                 query = next;
1499         }
1500         if (lookup->timer != NULL)
1501                 isc_timer_detach(&lookup->timer);
1502         lookup->pending = ISC_FALSE;
1503         lookup->retries = 0;
1504 }
1505
1506 static void
1507 bringup_timer(dig_query_t *query, unsigned int default_timeout) {
1508         dig_lookup_t *l;
1509         unsigned int local_timeout;
1510         isc_result_t result;
1511
1512         debug("bringup_timer()");
1513         /*
1514          * If the timer already exists, that means we're calling this
1515          * a second time (for a retry).  Don't need to recreate it,
1516          * just reset it.
1517          */
1518         l = query->lookup;
1519         if (ISC_LIST_NEXT(query, link) != NULL)
1520                 local_timeout = SERVER_TIMEOUT;
1521         else {
1522                 if (timeout == 0) {
1523                         local_timeout = default_timeout;
1524                 } else
1525                         local_timeout = timeout;
1526         }
1527         debug("have local timeout of %d", local_timeout);
1528         isc_interval_set(&l->interval, local_timeout, 0);
1529         if (l->timer != NULL)
1530                 isc_timer_detach(&l->timer);
1531         result = isc_timer_create(timermgr,
1532                                   isc_timertype_once,
1533                                   NULL,
1534                                   &l->interval,
1535                                   global_task,
1536                                   connect_timeout,
1537                                   l, &l->timer);
1538         check_result(result, "isc_timer_create");
1539 }       
1540
1541 static void
1542 connect_done(isc_task_t *task, isc_event_t *event);
1543
1544 /*
1545  * Unlike send_udp, this can't be called multiple times with the same
1546  * query.  When we retry TCP, we requeue the whole lookup, which should
1547  * start anew.
1548  */
1549 static void
1550 send_tcp_connect(dig_query_t *query) {
1551         isc_result_t result;
1552         dig_query_t *next;
1553         dig_lookup_t *l;
1554
1555         debug("send_tcp_connect(%p)", query);
1556
1557         l = query->lookup;
1558         query->waiting_connect = ISC_TRUE;
1559         query->lookup->current_query = query;
1560         get_address(query->servname, port, &query->sockaddr);
1561         
1562         if (specified_source &&
1563             (isc_sockaddr_pf(&query->sockaddr) !=
1564              isc_sockaddr_pf(&bind_address))) {
1565                 printf(";; Skipping server %s, incompatible "
1566                        "address family\n", query->servname);
1567                 query->waiting_connect = ISC_FALSE;
1568                 next = ISC_LIST_NEXT(query, link);
1569                 l = query->lookup;
1570                 clear_query(query);
1571                 if (next == NULL) {
1572                         printf(";; No acceptable nameservers\n");
1573                         check_next_lookup(l);
1574                         return;
1575                 }
1576                 send_tcp_connect(next);
1577                 return;
1578         }
1579         INSIST(query->sock == NULL);
1580         result = isc_socket_create(socketmgr,
1581                                    isc_sockaddr_pf(&query->sockaddr),
1582                                    isc_sockettype_tcp, &query->sock) ;
1583         check_result(result, "isc_socket_create");
1584         sockcount++;
1585         debug("sockcount=%d", sockcount);
1586         if (specified_source)
1587                 result = isc_socket_bind(query->sock, &bind_address);
1588         else {
1589                 if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
1590                     have_ipv4)
1591                         isc_sockaddr_any(&bind_any);
1592                 else
1593                         isc_sockaddr_any6(&bind_any);
1594                 result = isc_socket_bind(query->sock, &bind_any);
1595         }
1596         check_result(result, "isc_socket_bind");
1597         bringup_timer(query, TCP_TIMEOUT);
1598         result = isc_socket_connect(query->sock, &query->sockaddr,
1599                                     global_task, connect_done, query);
1600         check_result(result, "isc_socket_connect");
1601         /*
1602          * If we're at the endgame of a nameserver search, we need to
1603          * immediately bring up all the queries.  Do it here.
1604          */
1605         if (l->ns_search_only && !l->trace_root) {
1606                 debug("sending next, since searching");
1607                 next = ISC_LIST_NEXT(query, link);
1608                 if (next != NULL)
1609                         send_tcp_connect(next);
1610         }
1611 }
1612
1613 /*
1614  * Send a UDP packet to the remote nameserver, possible starting the
1615  * recv action as well.  Also make sure that the timer is running and
1616  * is properly reset.
1617  */
1618 static void
1619 send_udp(dig_query_t *query) {
1620         dig_lookup_t *l = NULL;
1621         dig_query_t *next;
1622         isc_result_t result;
1623
1624         debug("send_udp(%p)", query);
1625
1626         l = query->lookup;
1627         bringup_timer(query, UDP_TIMEOUT);
1628         l->current_query = query;
1629         debug("working on lookup %p, query %p",
1630               query->lookup, query);
1631         if (!query->recv_made) {
1632                 /* XXX Check the sense of this, need assertion? */
1633                 query->waiting_connect = ISC_FALSE;
1634                 get_address(query->servname, port, &query->sockaddr);
1635
1636                 result = isc_socket_create(socketmgr,
1637                                            isc_sockaddr_pf(&query->sockaddr),
1638                                            isc_sockettype_udp, &query->sock);
1639                 check_result(result, "isc_socket_create");
1640                 sockcount++;
1641                 debug("sockcount=%d", sockcount);
1642                 if (specified_source) {
1643                         result = isc_socket_bind(query->sock, &bind_address);
1644                 } else {
1645                         isc_sockaddr_anyofpf(&bind_any,
1646                                         isc_sockaddr_pf(&query->sockaddr));
1647                         result = isc_socket_bind(query->sock, &bind_any);
1648                 }
1649                 check_result(result, "isc_socket_bind");
1650
1651                 query->recv_made = ISC_TRUE;
1652                 ISC_LINK_INIT(&query->recvbuf, link);
1653                 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf,
1654                                  link);
1655                 debug("recving with lookup=%p, query=%p, sock=%p",
1656                       query->lookup, query,
1657                       query->sock);
1658                 result = isc_socket_recvv(query->sock,
1659                                           &query->recvlist, 1,
1660                                           global_task, recv_done,
1661                                           query);
1662                 check_result(result, "isc_socket_recvv");
1663                 recvcount++;
1664                 debug("recvcount=%d", recvcount);
1665         }
1666         ISC_LIST_INIT(query->sendlist);
1667         ISC_LINK_INIT(&l->sendbuf, link);
1668         ISC_LIST_ENQUEUE(query->sendlist, &l->sendbuf,
1669                          link);
1670         debug("sending a request");
1671         result = isc_time_now(&query->time_sent);
1672         check_result(result, "isc_time_now");
1673         INSIST(query->sock != NULL);
1674         result = isc_socket_sendtov(query->sock, &query->sendlist,
1675                                     global_task, send_done, query,
1676                                     &query->sockaddr, NULL);
1677         check_result(result, "isc_socket_sendtov");
1678         sendcount++;
1679         /*
1680          * If we're at the endgame of a nameserver search, we need to
1681          * immediately bring up all the queries.  Do it here.
1682          */
1683         if (l->ns_search_only && !l->trace_root) {
1684                 debug("sending next, since searching");
1685                 next = ISC_LIST_NEXT(query, link);
1686                 if (next != NULL)
1687                         send_udp(next);
1688         }
1689 }
1690
1691 /*
1692  * IO timeout handler, used for both connect and recv timeouts.  If
1693  * retries are still allowed, either resend the UDP packet or queue a
1694  * new TCP lookup.  Otherwise, cancel the lookup.
1695  */
1696 static void
1697 connect_timeout(isc_task_t *task, isc_event_t *event) {
1698         dig_lookup_t *l=NULL, *n;
1699         dig_query_t *query=NULL, *cq;
1700
1701         UNUSED(task);
1702         REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE);
1703
1704         debug("connect_timeout()");
1705
1706         LOCK_LOOKUP;
1707         l = event->ev_arg;
1708         query = l->current_query;
1709         isc_event_free(&event);
1710
1711         INSIST(!free_now);
1712
1713         if ((query != NULL) && (query->lookup->current_query != NULL) &&
1714             (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) {
1715                 debug("trying next server...");
1716                 cq = query->lookup->current_query;
1717                 if (!l->tcp_mode)
1718                         send_udp(ISC_LIST_NEXT(cq, link));
1719                 else
1720                         send_tcp_connect(ISC_LIST_NEXT(cq, link));
1721                 UNLOCK_LOOKUP;
1722                 return;
1723         }
1724
1725         if (l->retries > 1) {
1726                 if (!l->tcp_mode) {
1727                         l->retries--;
1728                         debug("resending UDP request to first server");
1729                         send_udp(ISC_LIST_HEAD(l->q));
1730                 } else {
1731                         debug("making new TCP request, %d tries left",
1732                               l->retries);
1733                         l->retries--;
1734                         n = requeue_lookup(l, ISC_TRUE);
1735                         cancel_lookup(l);
1736                         check_next_lookup(l);
1737                 }
1738         } else {
1739                 fputs(l->cmdline, stdout);
1740                 printf(";; connection timed out; no servers could be "
1741                        "reached\n");
1742                 cancel_lookup(l);
1743                 check_next_lookup(l);
1744                 if (exitcode < 9)
1745                         exitcode = 9;
1746         }
1747         UNLOCK_LOOKUP;
1748 }
1749
1750 /*
1751  * Event handler for the TCP recv which gets the length header of TCP
1752  * packets.  Start the next recv of length bytes.
1753  */
1754 static void
1755 tcp_length_done(isc_task_t *task, isc_event_t *event) {
1756         isc_socketevent_t *sevent;
1757         isc_buffer_t *b = NULL;
1758         isc_result_t result;
1759         dig_query_t *query = NULL;
1760         dig_lookup_t *l;
1761         isc_uint16_t length;
1762
1763         REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
1764         INSIST(!free_now);
1765
1766         UNUSED(task);
1767
1768         debug("tcp_length_done()");
1769
1770         LOCK_LOOKUP;
1771         sevent = (isc_socketevent_t *)event;
1772         query = event->ev_arg;
1773
1774         recvcount--;
1775         INSIST(recvcount >= 0);
1776
1777         if (sevent->result == ISC_R_CANCELED) {
1778                 isc_event_free(&event);
1779                 l = query->lookup;
1780                 clear_query(query);
1781                 check_next_lookup(l);
1782                 UNLOCK_LOOKUP;
1783                 return;
1784         }
1785         if (sevent->result != ISC_R_SUCCESS) {
1786                 char sockstr[ISC_SOCKADDR_FORMATSIZE];
1787                 isc_sockaddr_format(&query->sockaddr, sockstr,
1788                                     sizeof(sockstr));
1789                 printf(";; communications error to %s: %s\n",
1790                        sockstr, isc_result_totext(sevent->result));
1791                 l = query->lookup;
1792                 isc_socket_detach(&query->sock);
1793                 sockcount--;
1794                 debug("sockcount=%d", sockcount);
1795                 INSIST(sockcount >= 0);
1796                 isc_event_free(&event);
1797                 clear_query(query);
1798                 check_next_lookup(l);
1799                 UNLOCK_LOOKUP;
1800                 return;
1801         }
1802         b = ISC_LIST_HEAD(sevent->bufferlist);
1803         ISC_LIST_DEQUEUE(sevent->bufferlist, &query->lengthbuf, link);
1804         length = isc_buffer_getuint16(b);
1805         if (length == 0) {
1806                 isc_event_free(&event);
1807                 launch_next_query(query, ISC_FALSE);
1808                 UNLOCK_LOOKUP;
1809                 return;
1810         }
1811
1812         /*
1813          * Even though the buffer was already init'ed, we need
1814          * to redo it now, to force the length we want.
1815          */
1816         isc_buffer_invalidate(&query->recvbuf);
1817         isc_buffer_init(&query->recvbuf, query->recvspace, length);
1818         ENSURE(ISC_LIST_EMPTY(query->recvlist));
1819         ISC_LINK_INIT(&query->recvbuf, link);
1820         ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
1821         debug("recving with lookup=%p, query=%p",
1822                query->lookup, query);
1823         result = isc_socket_recvv(query->sock, &query->recvlist, length, task,
1824                                   recv_done, query);
1825         check_result(result, "isc_socket_recvv");
1826         recvcount++;
1827         debug("resubmitted recv request with length %d, recvcount=%d",
1828               length, recvcount);
1829         isc_event_free(&event);
1830         UNLOCK_LOOKUP;
1831 }
1832
1833 /*
1834  * For transfers that involve multiple recvs (XFR's in particular),
1835  * launch the next recv.
1836  */
1837 static void
1838 launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
1839         isc_result_t result;
1840         dig_lookup_t *l;
1841
1842         INSIST(!free_now);
1843
1844         debug("launch_next_query()");
1845
1846         if (!query->lookup->pending) {
1847                 debug("ignoring launch_next_query because !pending");
1848                 isc_socket_detach(&query->sock);
1849                 sockcount--;
1850                 debug("sockcount=%d", sockcount);
1851                 INSIST(sockcount >= 0);
1852                 query->waiting_connect = ISC_FALSE;
1853                 l = query->lookup;
1854                 clear_query(query);
1855                 check_next_lookup(l);
1856                 return;
1857         }
1858
1859         isc_buffer_clear(&query->slbuf);
1860         isc_buffer_clear(&query->lengthbuf);
1861         isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->lookup->sendbuf.used);
1862         ISC_LIST_INIT(query->sendlist);
1863         ISC_LINK_INIT(&query->slbuf, link);
1864         ISC_LIST_ENQUEUE(query->sendlist, &query->slbuf, link);
1865         if (include_question) {
1866                 ISC_LINK_INIT(&query->lookup->sendbuf, link);
1867                 ISC_LIST_ENQUEUE(query->sendlist, &query->lookup->sendbuf,
1868                                  link);
1869         }
1870         ISC_LINK_INIT(&query->lengthbuf, link);
1871         ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
1872
1873         result = isc_socket_recvv(query->sock, &query->lengthlist, 0,
1874                                   global_task, tcp_length_done, query);
1875         check_result(result, "isc_socket_recvv");
1876         recvcount++;
1877         debug("recvcount=%d",recvcount);
1878         if (!query->first_soa_rcvd) {
1879                 debug("sending a request in launch_next_query");
1880                 result = isc_time_now(&query->time_sent);
1881                 check_result(result, "isc_time_now");
1882                 result = isc_socket_sendv(query->sock, &query->sendlist,
1883                                           global_task, send_done, query);
1884                 check_result(result, "isc_socket_sendv");
1885                 sendcount++;
1886                 debug("sendcount=%d", sendcount);
1887         }
1888         query->waiting_connect = ISC_FALSE;
1889 #if 0
1890         check_next_lookup(query->lookup);
1891 #endif
1892         return;
1893 }
1894
1895 /*
1896  * Event handler for TCP connect complete.  Make sure the connection was
1897  * successful, then pass into launch_next_query to actually send the
1898  * question.
1899  */
1900 static void
1901 connect_done(isc_task_t *task, isc_event_t *event) {
1902         isc_socketevent_t *sevent = NULL;
1903         dig_query_t *query = NULL, *next;
1904         dig_lookup_t *l;
1905
1906         UNUSED(task);
1907
1908         REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
1909         INSIST(!free_now);
1910
1911         debug("connect_done()");
1912
1913         LOCK_LOOKUP;
1914         sevent = (isc_socketevent_t *)event;
1915         query = sevent->ev_arg;
1916
1917         INSIST(query->waiting_connect);
1918
1919         query->waiting_connect = ISC_FALSE;
1920
1921         if (sevent->result == ISC_R_CANCELED) {
1922                 debug("in cancel handler");
1923                 isc_socket_detach(&query->sock);
1924                 sockcount--;
1925                 INSIST(sockcount >= 0);
1926                 debug("sockcount=%d", sockcount);
1927                 query->waiting_connect = ISC_FALSE;
1928                 isc_event_free(&event);
1929                 l = query->lookup;
1930                 clear_query(query);
1931                 check_next_lookup(l);
1932                 UNLOCK_LOOKUP;
1933                 return;
1934         }
1935         if (sevent->result != ISC_R_SUCCESS) {
1936                 char sockstr[ISC_SOCKADDR_FORMATSIZE];
1937
1938                 debug("unsuccessful connection: %s",
1939                       isc_result_totext(sevent->result));
1940                 isc_sockaddr_format(&query->sockaddr, sockstr,
1941                                     sizeof(sockstr));
1942                 if (sevent->result != ISC_R_CANCELED)
1943                         printf(";; Connection to %s(%s) for %s failed: "
1944                                "%s.\n", sockstr,
1945                                query->servname, query->lookup->textname,
1946                                isc_result_totext(sevent->result));
1947                 isc_socket_detach(&query->sock);
1948                 sockcount--;
1949                 INSIST(sockcount >= 0);
1950                 /* XXX Clean up exitcodes */
1951                 if (exitcode < 9)
1952                         exitcode = 9;
1953                 debug("sockcount=%d", sockcount);
1954                 query->waiting_connect = ISC_FALSE;
1955                 isc_event_free(&event);
1956                 l = query->lookup;
1957                 if (l->current_query != NULL)
1958                         next = ISC_LIST_NEXT(l->current_query, link);
1959                 else
1960                         next = NULL;
1961                 clear_query(query);
1962                 if (next != NULL) {
1963                         bringup_timer(next, TCP_TIMEOUT);
1964                         send_tcp_connect(next);
1965                 } else {
1966                         check_next_lookup(l);
1967                 }
1968                 UNLOCK_LOOKUP;
1969                 return;
1970         }
1971         launch_next_query(query, ISC_TRUE);
1972         isc_event_free(&event);
1973         UNLOCK_LOOKUP;
1974 }
1975
1976 /*
1977  * Check if the ongoing XFR needs more data before it's complete, using
1978  * the semantics of IXFR and AXFR protocols.  Much of the complexity of
1979  * this routine comes from determining when an IXFR is complete.
1980  * ISC_FALSE means more data is on the way, and the recv has been issued.
1981  */
1982 static isc_boolean_t
1983 check_for_more_data(dig_query_t *query, dns_message_t *msg,
1984                     isc_socketevent_t *sevent)
1985 {
1986         dns_rdataset_t *rdataset = NULL;
1987         dns_rdata_t rdata = DNS_RDATA_INIT;
1988         dns_rdata_soa_t soa;
1989         isc_uint32_t serial;
1990         isc_result_t result;
1991
1992         debug("check_for_more_data()");
1993
1994         /*
1995          * By the time we're in this routine, we know we're doing
1996          * either an AXFR or IXFR.  If there's no second_rr_type,
1997          * then we don't yet know which kind of answer we got back
1998          * from the server.  Here, we're going to walk through the
1999          * rr's in the message, acting as necessary whenever we hit
2000          * an SOA rr.
2001          */
2002
2003         result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
2004         if (result != ISC_R_SUCCESS) {
2005                 puts("; Transfer failed.");
2006                 return (ISC_TRUE);
2007         }
2008         do {
2009                 dns_name_t *name;
2010                 name = NULL;
2011                 dns_message_currentname(msg, DNS_SECTION_ANSWER,
2012                                         &name);
2013                 for (rdataset = ISC_LIST_HEAD(name->list);
2014                      rdataset != NULL;
2015                      rdataset = ISC_LIST_NEXT(rdataset, link)) {
2016                         result = dns_rdataset_first(rdataset);
2017                         if (result != ISC_R_SUCCESS)
2018                                 continue;
2019                         do {
2020                                 query->rr_count++;
2021                                 dns_rdata_reset(&rdata);
2022                                 dns_rdataset_current(rdataset, &rdata);
2023                                 /*
2024                                  * If this is the first rr, make sure
2025                                  * it's an SOA
2026                                  */
2027                                 if ((!query->first_soa_rcvd) &&
2028                                     (rdata.type != dns_rdatatype_soa)) {
2029                                         puts("; Transfer failed.  "
2030                                              "Didn't start with "
2031                                              "SOA answer.");
2032                                         return (ISC_TRUE);
2033                                 }
2034                                 if ((!query->second_rr_rcvd) &&
2035                                     (rdata.type != dns_rdatatype_soa)) {
2036                                         query->second_rr_rcvd = ISC_TRUE;
2037                                         query->second_rr_serial = 0;
2038                                         debug("got the second rr as nonsoa");
2039                                         goto next_rdata;
2040                                 }
2041
2042                                 /*
2043                                  * If the record is anything except an SOA
2044                                  * now, just continue on...
2045                                  */
2046                                 if (rdata.type != dns_rdatatype_soa)
2047                                         goto next_rdata;
2048                                 /* Now we have an SOA.  Work with it. */
2049                                 debug("got an SOA");
2050                                 (void)dns_rdata_tostruct(&rdata, &soa, NULL);
2051                                 serial = soa.serial;
2052                                 dns_rdata_freestruct(&soa);
2053                                 if (!query->first_soa_rcvd) {
2054                                         query->first_soa_rcvd = ISC_TRUE;
2055                                         query->first_rr_serial = serial;
2056                                         debug("this is the first %d",
2057                                                query->lookup->ixfr_serial);
2058                                         if (query->lookup->ixfr_serial >=
2059                                             serial)
2060                                                 goto doexit;
2061                                         goto next_rdata;
2062                                 }
2063                                 if (query->lookup->rdtype ==
2064                                     dns_rdatatype_axfr) {
2065                                         debug("doing axfr, got second SOA");
2066                                         goto doexit;
2067                                 }
2068                                 if (!query->second_rr_rcvd) {
2069                                         if (query->first_rr_serial == serial) {
2070                                                 debug("doing ixfr, got "
2071                                                       "empty zone");
2072                                                 goto doexit;
2073                                         }
2074                                         debug("this is the second %d",
2075                                                query->lookup->ixfr_serial);
2076                                         query->second_rr_rcvd = ISC_TRUE;
2077                                         query->second_rr_serial = serial;
2078                                         goto next_rdata;
2079                                 }
2080                                 if (query->second_rr_serial == 0) {
2081                                         /*
2082                                          * If the second RR was a non-SOA
2083                                          * record, and we're getting any
2084                                          * other SOA, then this is an
2085                                          * AXFR, and we're done.
2086                                          */
2087                                         debug("done, since axfr");
2088                                         goto doexit;
2089                                 }
2090                                 /*
2091                                  * If we get to this point, we're doing an
2092                                  * IXFR and have to start really looking
2093                                  * at serial numbers.
2094                                  */
2095                                 if (query->first_rr_serial == serial) {
2096                                         debug("got a match for ixfr");
2097                                         if (!query->first_repeat_rcvd) {
2098                                                 query->first_repeat_rcvd =
2099                                                         ISC_TRUE;
2100                                                 goto next_rdata;
2101                                         }
2102                                         debug("done with ixfr");
2103                                         goto doexit;
2104                                 }
2105                                 debug("meaningless soa %d", serial);
2106                         next_rdata:
2107                                 result = dns_rdataset_next(rdataset);
2108                         } while (result == ISC_R_SUCCESS);
2109                 }
2110                 result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
2111         } while (result == ISC_R_SUCCESS);
2112         launch_next_query(query, ISC_FALSE);
2113         return (ISC_FALSE);
2114  doexit:
2115         received(sevent->n, &sevent->address, query);
2116         return (ISC_TRUE);
2117 }
2118
2119 /*
2120  * Event handler for recv complete.  Perform whatever actions are necessary,
2121  * based on the specifics of the user's request.
2122  */
2123 static void
2124 recv_done(isc_task_t *task, isc_event_t *event) {
2125         isc_socketevent_t *sevent = NULL;
2126         dig_query_t *query = NULL;
2127         isc_buffer_t *b = NULL;
2128         dns_message_t *msg = NULL;
2129         isc_result_t result;
2130         dig_lookup_t *n, *l;
2131         isc_boolean_t docancel = ISC_FALSE;
2132         isc_boolean_t match = ISC_TRUE;
2133         unsigned int parseflags;
2134         dns_messageid_t id;
2135         unsigned int msgflags;
2136
2137         UNUSED(task);
2138         INSIST(!free_now);
2139
2140         debug("recv_done()");
2141
2142         LOCK_LOOKUP;
2143         recvcount--;
2144         debug("recvcount=%d", recvcount);
2145         INSIST(recvcount >= 0);
2146
2147         query = event->ev_arg;
2148         debug("lookup=%p, query=%p", query->lookup, query);
2149
2150         l = query->lookup;
2151
2152         REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
2153         sevent = (isc_socketevent_t *)event;
2154
2155         if ((l->tcp_mode) && (l->timer != NULL))
2156                 isc_timer_touch(l->timer);
2157         if ((!l->pending && !l->ns_search_only) || cancel_now) {
2158                 debug("no longer pending.  Got %s",
2159                         isc_result_totext(sevent->result));
2160                 query->waiting_connect = ISC_FALSE;
2161
2162                 isc_event_free(&event);
2163                 clear_query(query);
2164                 check_next_lookup(l);
2165                 UNLOCK_LOOKUP;
2166                 return;
2167         }
2168
2169         if (sevent->result != ISC_R_SUCCESS) {
2170                 if (sevent->result == ISC_R_CANCELED) {
2171                         debug("in recv cancel handler");
2172                         query->waiting_connect = ISC_FALSE;
2173                 } else {
2174                         printf(";; communications error: %s\n",
2175                                isc_result_totext(sevent->result));
2176                         isc_socket_detach(&query->sock);
2177                         sockcount--;
2178                         debug("sockcount=%d", sockcount);
2179                         INSIST(sockcount >= 0);
2180                 }
2181                 isc_event_free(&event);
2182                 clear_query(query);
2183                 check_next_lookup(l);
2184                 UNLOCK_LOOKUP;
2185                 return;
2186         }
2187
2188         b = ISC_LIST_HEAD(sevent->bufferlist);
2189         ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link);
2190
2191         if (!l->tcp_mode &&
2192             !isc_sockaddr_equal(&sevent->address, &query->sockaddr)) {
2193                 char buf1[ISC_SOCKADDR_FORMATSIZE];
2194                 char buf2[ISC_SOCKADDR_FORMATSIZE];
2195                 isc_sockaddr_t any;
2196
2197                 if (isc_sockaddr_pf(&query->sockaddr) == AF_INET) 
2198                         isc_sockaddr_any(&any);
2199                 else
2200                         isc_sockaddr_any6(&any);
2201
2202                 /*
2203                 * We don't expect a match when the packet is 
2204                 * sent to 0.0.0.0, :: or to a multicast addresses.
2205                 * XXXMPA broadcast needs to be handled here as well.
2206                 */
2207                 if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) &&
2208                      !isc_sockaddr_ismulticast(&query->sockaddr)) ||
2209                     isc_sockaddr_getport(&query->sockaddr) !=
2210                     isc_sockaddr_getport(&sevent->address)) {
2211                         isc_sockaddr_format(&sevent->address, buf1,
2212                         sizeof(buf1));
2213                         isc_sockaddr_format(&query->sockaddr, buf2,
2214                         sizeof(buf2));
2215                         printf(";; reply from unexpected source: %s,"
2216                         " expected %s\n", buf1, buf2);
2217                         match = ISC_FALSE;
2218                 }
2219         }
2220
2221         result = dns_message_peekheader(b, &id, &msgflags);
2222         if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
2223                 match = ISC_FALSE;
2224                 if (l->tcp_mode) {
2225                         isc_boolean_t fail = ISC_TRUE;
2226                         if (result == ISC_R_SUCCESS) {
2227                                 if (!query->first_soa_rcvd ||
2228                                      query->warn_id)
2229                                         printf(";; %s: ID mismatch: "
2230                                                "expected ID %u, got %u\n",
2231                                                query->first_soa_rcvd ?
2232                                                "WARNING" : "ERROR",
2233                                                l->sendmsg->id, id);
2234                                 if (query->first_soa_rcvd)
2235                                         fail = ISC_FALSE;
2236                                 query->warn_id = ISC_FALSE;
2237                         } else
2238                                 printf(";; ERROR: short (< header size) message\n");
2239                         if (fail) {
2240                                 isc_event_free(&event);
2241                                 clear_query(query);
2242                                 check_next_lookup(l);
2243                                 UNLOCK_LOOKUP;
2244                                 return;
2245                         }
2246                         match = ISC_TRUE;
2247                 } else if (result == ISC_R_SUCCESS)
2248                         printf(";; Warning: ID mismatch: "
2249                                "expected ID %u, got %u\n", l->sendmsg->id, id);
2250                 else
2251                         printf(";; Warning: short (< header size) message received\n");
2252         }
2253
2254         if (!match) {
2255                 isc_buffer_invalidate(&query->recvbuf);
2256                 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
2257                 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
2258                 result = isc_socket_recvv(query->sock, &query->recvlist, 1,
2259                                           global_task, recv_done, query);
2260                 check_result(result, "isc_socket_recvv");
2261                 recvcount++;
2262                 isc_event_free(&event);
2263                 UNLOCK_LOOKUP;
2264                 return;
2265         }
2266
2267         result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
2268         check_result(result, "dns_message_create");
2269
2270         if (key != NULL) {
2271                 if (l->querysig == NULL) {
2272                         debug("getting initial querysig");
2273                         result = dns_message_getquerytsig(l->sendmsg, mctx,
2274                                                           &l->querysig);
2275                         check_result(result, "dns_message_getquerytsig");
2276                 }
2277                 result = dns_message_setquerytsig(msg, l->querysig);
2278                 check_result(result, "dns_message_setquerytsig");
2279                 result = dns_message_settsigkey(msg, key);
2280                 check_result(result, "dns_message_settsigkey");
2281                 msg->tsigctx = l->tsigctx;
2282                 l->tsigctx = NULL;
2283                 if (l->msgcounter != 0)
2284                         msg->tcp_continuation = 1;
2285                 l->msgcounter++;
2286         }
2287
2288         debug("before parse starts");
2289         parseflags = DNS_MESSAGEPARSE_PRESERVEORDER;
2290         if (l->besteffort) {
2291                 parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
2292                 parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
2293         }
2294         result = dns_message_parse(msg, b, parseflags);
2295         if (result == DNS_R_RECOVERABLE) {
2296                 printf(";; Warning: Message parser reports malformed "
2297                        "message packet.\n");
2298                 result = ISC_R_SUCCESS;
2299         }
2300         if (result != ISC_R_SUCCESS) {
2301                 printf(";; Got bad packet: %s\n", isc_result_totext(result));
2302                 hex_dump(b);
2303                 query->waiting_connect = ISC_FALSE;
2304                 dns_message_destroy(&msg);
2305                 isc_event_free(&event);
2306                 clear_query(query);
2307                 cancel_lookup(l);
2308                 check_next_lookup(l);
2309                 UNLOCK_LOOKUP;
2310                 return;
2311         }
2312         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0
2313             && !l->ignore && !l->tcp_mode)
2314         {
2315                 printf(";; Truncated, retrying in TCP mode.\n");
2316                 n = requeue_lookup(l, ISC_TRUE);
2317                 n->tcp_mode = ISC_TRUE;
2318                 n->origin = query->lookup->origin;
2319                 dns_message_destroy(&msg);
2320                 isc_event_free(&event);
2321                 clear_query(query);
2322                 cancel_lookup(l);
2323                 check_next_lookup(l);
2324                 UNLOCK_LOOKUP;
2325                 return;
2326         }                       
2327         if (msg->rcode == dns_rcode_servfail && !l->servfail_stops) {
2328                 dig_query_t *next = ISC_LIST_NEXT(query, link);
2329                 if (l->current_query == query)
2330                         l->current_query = NULL;
2331                 if (next != NULL) {
2332                         debug("sending query %p\n", next);
2333                         if (l->tcp_mode)
2334                                 send_tcp_connect(next);
2335                         else
2336                                 send_udp(next);
2337                 }
2338                 /*
2339                  * If our query is at the head of the list and there
2340                  * is no next, we're the only one left, so fall
2341                  * through to print the message.
2342                  */
2343                 if ((ISC_LIST_HEAD(l->q) != query) ||
2344                     (ISC_LIST_NEXT(query, link) != NULL)) {
2345                         printf(";; Got SERVFAIL reply from %s, "
2346                                "trying next server\n",
2347                                query->servname);
2348                         clear_query(query);
2349                         check_next_lookup(l);
2350                         dns_message_destroy(&msg);
2351                         isc_event_free(&event);
2352                         UNLOCK_LOOKUP;
2353                         return;
2354                 }
2355         }
2356
2357         if (key != NULL) {
2358                 result = dns_tsig_verify(&query->recvbuf, msg, NULL, NULL);
2359                 if (result != ISC_R_SUCCESS) {
2360                         printf(";; Couldn't verify signature: %s\n",
2361                                isc_result_totext(result));
2362                         validated = ISC_FALSE;
2363                 }
2364                 l->tsigctx = msg->tsigctx;
2365                 msg->tsigctx = NULL;
2366                 if (l->querysig != NULL) {
2367                         debug("freeing querysig buffer %p", l->querysig);
2368                         isc_buffer_free(&l->querysig);
2369                 }
2370                 result = dns_message_getquerytsig(msg, mctx, &l->querysig);
2371                 check_result(result,"dns_message_getquerytsig");
2372         }
2373
2374         debug("after parse");
2375         if (l->doing_xfr && l->xfr_q == NULL) {
2376                 l->xfr_q = query;
2377                 /*
2378                  * Once we are in the XFR message, increase
2379                  * the timeout to much longer, so brief network
2380                  * outages won't cause the XFR to abort
2381                  */
2382                 if (timeout != INT_MAX && l->timer != NULL) {
2383                         unsigned int local_timeout;
2384
2385                         if (timeout == 0) {
2386                                 if (l->tcp_mode)
2387                                         local_timeout = TCP_TIMEOUT * 4;
2388                                 else
2389                                         local_timeout = UDP_TIMEOUT * 4;
2390                         } else {
2391                                 if (timeout < (INT_MAX / 4))
2392                                         local_timeout = timeout * 4;
2393                                 else
2394                                         local_timeout = INT_MAX;
2395                         }
2396                         debug("have local timeout of %d", local_timeout);
2397                         isc_interval_set(&l->interval, local_timeout, 0);
2398                         result = isc_timer_reset(l->timer,
2399                                                  isc_timertype_once,
2400                                                  NULL,
2401                                                  &l->interval,
2402                                                  ISC_FALSE);
2403                         check_result(result, "isc_timer_reset");
2404                 }
2405         }
2406
2407         if (!l->doing_xfr || l->xfr_q == query) {
2408                 if (msg->rcode != dns_rcode_noerror && l->origin != NULL) {
2409                         if (!next_origin(msg, query)) {
2410                                 printmessage(query, msg, ISC_TRUE);
2411                                 received(b->used, &sevent->address, query);
2412                         }
2413                 } else if (!l->trace && !l->ns_search_only) {
2414                         printmessage(query, msg, ISC_TRUE);
2415                 } else if (l->trace) {
2416                         int n = 0;
2417                         int count = msg->counts[DNS_SECTION_ANSWER];
2418
2419                         debug("in TRACE code");
2420                         if (!l->ns_search_only)
2421                                 printmessage(query, msg, ISC_TRUE);
2422
2423                         l->rdtype = l->qrdtype;
2424                         if (l->trace_root || (l->ns_search_only && count > 0))
2425                         {
2426                                 if (!l->trace_root)
2427                                         l->rdtype = dns_rdatatype_soa;
2428                                 n = followup_lookup(msg, query,
2429                                                     DNS_SECTION_ANSWER);
2430                                 l->trace_root = ISC_FALSE;
2431                         } else if (count == 0)
2432                                 n = followup_lookup(msg, query,
2433                                                     DNS_SECTION_AUTHORITY);
2434                         if (n == 0)
2435                                 docancel = ISC_TRUE;
2436                 } else {
2437                         debug("in NSSEARCH code");
2438
2439                         if (l->trace_root) {
2440                                 /*
2441                                  * This is the initial NS query. 
2442                                  */
2443                                 int n;
2444
2445                                 l->rdtype = dns_rdatatype_soa;
2446                                 n = followup_lookup(msg, query,
2447                                                     DNS_SECTION_ANSWER);
2448                                 if (n == 0)
2449                                         docancel = ISC_TRUE;
2450                                 l->trace_root = ISC_FALSE;
2451                         } else
2452                                 printmessage(query, msg, ISC_TRUE);
2453                 } 
2454         }
2455
2456         if (l->pending)
2457                 debug("still pending.");
2458         if (l->doing_xfr) {
2459                 if (query != l->xfr_q) {
2460                         dns_message_destroy(&msg);
2461                         isc_event_free(&event);
2462                         query->waiting_connect = ISC_FALSE;
2463                         UNLOCK_LOOKUP;
2464                         return;
2465                 }
2466                 if (!docancel)
2467                         docancel = check_for_more_data(query, msg, sevent);
2468                 if (docancel) {
2469                         dns_message_destroy(&msg);
2470                         clear_query(query);
2471                         cancel_lookup(l);
2472                         check_next_lookup(l);
2473                 }
2474         } else {
2475                 if (msg->rcode == dns_rcode_noerror || l->origin == NULL)
2476                         received(b->used, &sevent->address, query);
2477                 if (!query->lookup->ns_search_only)
2478                         query->lookup->pending = ISC_FALSE;
2479                 if (!query->lookup->ns_search_only ||
2480                     query->lookup->trace_root || docancel)
2481                 {
2482                         dns_message_destroy(&msg);
2483                         cancel_lookup(l);
2484                 }
2485                 clear_query(query);
2486                 check_next_lookup(l);
2487         }
2488         if (msg != NULL)
2489                 dns_message_destroy(&msg);
2490         isc_event_free(&event);
2491         UNLOCK_LOOKUP;
2492 }
2493
2494 /*
2495  * Turn a name into an address, using system-supplied routines.  This is
2496  * used in looking up server names, etc... and needs to use system-supplied
2497  * routines, since they may be using a non-DNS system for these lookups.
2498  */
2499 void
2500 get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
2501         struct in_addr in4;
2502         struct in6_addr in6;
2503 #ifdef USE_GETADDRINFO
2504         struct addrinfo *res = NULL, hints;
2505         int result;
2506 #else
2507         struct hostent *he;
2508 #endif
2509
2510         debug("get_address()");
2511
2512         if (inet_pton(AF_INET6, host, &in6) == 1) {
2513                 if (!have_ipv6)
2514                         fatal("Protocol family INET6 not supported '%s'", host);
2515                 isc_sockaddr_fromin6(sockaddr, &in6, port);
2516         } else if (inet_pton(AF_INET, host, &in4) == 1) {
2517                 if (have_ipv4)
2518                         isc_sockaddr_fromin(sockaddr, &in4, port);
2519                 else
2520                         isc_sockaddr_v6fromin(sockaddr, &in4, port);
2521         } else {
2522 #ifdef USE_GETADDRINFO
2523                 memset(&hints, 0, sizeof(hints));
2524                 if (specified_source)
2525                         hints.ai_family = isc_sockaddr_pf(&bind_address);
2526                 else if (!have_ipv6)
2527                         hints.ai_family = PF_INET;
2528                 else if (!have_ipv4)
2529                         hints.ai_family = PF_INET6;
2530                 else {
2531                         hints.ai_family = PF_UNSPEC;
2532 #ifdef AI_ADDRCONFIG
2533                         hints.ai_flags = AI_ADDRCONFIG;
2534 #endif
2535                 }
2536                 debug ("before getaddrinfo()");
2537                 isc_app_block();
2538 #ifdef AI_ADDRCONFIG
2539  again:
2540 #endif
2541                 result = getaddrinfo(host, NULL, &hints, &res);
2542 #ifdef AI_ADDRCONFIG
2543                 if (result == EAI_BADFLAGS &&
2544                     (hints.ai_flags & AI_ADDRCONFIG) != 0) {
2545                         hints.ai_flags &= ~AI_ADDRCONFIG;
2546                         goto again;
2547                 }
2548 #endif
2549                 isc_app_unblock();
2550                 if (result != 0) {
2551                         fatal("Couldn't find server '%s': %s",
2552                               host, gai_strerror(result));
2553                 }
2554                 memcpy(&sockaddr->type.sa, res->ai_addr, res->ai_addrlen);
2555                 sockaddr->length = res->ai_addrlen;
2556                 isc_sockaddr_setport(sockaddr, port);
2557                 freeaddrinfo(res);
2558 #else
2559                 debug ("before gethostbyname()");
2560                 isc_app_block();
2561                 he = gethostbyname(host);
2562                 isc_app_unblock();
2563                 if (he == NULL)
2564                         fatal("Couldn't find server '%s' (h_errno=%d)",
2565                               host, h_errno);
2566                 INSIST(he->h_addrtype == AF_INET);
2567                 isc_sockaddr_fromin(sockaddr,
2568                                     (struct in_addr *)(he->h_addr_list[0]),
2569                                     port);
2570 #endif
2571         }
2572 }
2573
2574 /*
2575  * Initiate either a TCP or UDP lookup
2576  */
2577 void
2578 do_lookup(dig_lookup_t *lookup) {
2579
2580         REQUIRE(lookup != NULL);
2581
2582         debug("do_lookup()");
2583         lookup->pending = ISC_TRUE;
2584         if (lookup->tcp_mode)
2585                 send_tcp_connect(ISC_LIST_HEAD(lookup->q));
2586         else
2587                 send_udp(ISC_LIST_HEAD(lookup->q));
2588 }
2589
2590 /*
2591  * Start everything in action upon task startup.
2592  */
2593 void
2594 onrun_callback(isc_task_t *task, isc_event_t *event) {
2595         UNUSED(task);
2596
2597         isc_event_free(&event);
2598         LOCK_LOOKUP;
2599         start_lookup();
2600         UNLOCK_LOOKUP;
2601 }
2602
2603 /*
2604  * Make everything on the lookup queue go away.  Mainly used by the
2605  * SIGINT handler.
2606  */
2607 void
2608 cancel_all(void) {
2609         dig_lookup_t *l, *n;
2610         dig_query_t *q, *nq;
2611
2612         debug("cancel_all()");
2613
2614         LOCK_LOOKUP;
2615         if (free_now) {
2616                 UNLOCK_LOOKUP;
2617                 return;
2618         }
2619         cancel_now = ISC_TRUE;
2620         if (current_lookup != NULL) {
2621                 if (current_lookup->timer != NULL)
2622                         isc_timer_detach(&current_lookup->timer);
2623                 q = ISC_LIST_HEAD(current_lookup->q);
2624                 while (q != NULL) {
2625                         debug("cancelling query %p, belonging to %p",
2626                               q, current_lookup);
2627                         nq = ISC_LIST_NEXT(q, link);
2628                         if (q->sock != NULL) {
2629                                 isc_socket_cancel(q->sock, NULL,
2630                                                   ISC_SOCKCANCEL_ALL);
2631                         } else {
2632                                 clear_query(q);
2633                         }
2634                         q = nq;
2635                 }
2636         }
2637         l = ISC_LIST_HEAD(lookup_list);
2638         while (l != NULL) {
2639                 n = ISC_LIST_NEXT(l, link);
2640                 ISC_LIST_DEQUEUE(lookup_list, l, link);
2641                 try_clear_lookup(l);
2642                 l = n;
2643         }
2644         UNLOCK_LOOKUP;
2645 }
2646
2647 /*
2648  * Destroy all of the libs we are using, and get everything ready for a
2649  * clean shutdown.
2650  */
2651 void
2652 destroy_libs(void) {
2653         void *ptr;
2654         dig_server_t *s;
2655
2656         debug("destroy_libs()");
2657         if (global_task != NULL) {
2658                 debug("freeing task");
2659                 isc_task_detach(&global_task);
2660         }
2661         /*
2662          * The taskmgr_destroy() call blocks until all events are cleared
2663          * from the task.
2664          */
2665         if (taskmgr != NULL) {
2666                 debug("freeing taskmgr");
2667                 isc_taskmgr_destroy(&taskmgr);
2668         }
2669         LOCK_LOOKUP;
2670         REQUIRE(sockcount == 0);
2671         REQUIRE(recvcount == 0);
2672         REQUIRE(sendcount == 0);
2673
2674         INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
2675         INSIST(current_lookup == NULL);
2676         INSIST(!free_now);
2677
2678         free_now = ISC_TRUE;
2679
2680         s = ISC_LIST_HEAD(server_list);
2681         while (s != NULL) {
2682                 debug("freeing global server %p", s);
2683                 ptr = s;
2684                 s = ISC_LIST_NEXT(s, link);
2685                 isc_mem_free(mctx, ptr);
2686         }
2687         clear_searchlist();
2688         if (commctx != NULL) {
2689                 debug("freeing commctx");
2690                 isc_mempool_destroy(&commctx);
2691         }
2692         if (socketmgr != NULL) {
2693                 debug("freeing socketmgr");
2694                 isc_socketmgr_destroy(&socketmgr);
2695         }
2696         if (timermgr != NULL) {
2697                 debug("freeing timermgr");
2698                 isc_timermgr_destroy(&timermgr);
2699         }
2700         if (key != NULL) {
2701                 debug("freeing key %p", key);
2702                 dns_tsigkey_detach(&key);
2703         }
2704         if (namebuf != NULL)
2705                 isc_buffer_free(&namebuf);
2706
2707         if (is_dst_up) {
2708                 debug("destroy DST lib");
2709                 dst_lib_destroy();
2710                 is_dst_up = ISC_FALSE;
2711         }
2712         if (entp != NULL) {
2713                 debug("detach from entropy");
2714                 isc_entropy_detach(&entp);
2715         }
2716
2717         UNLOCK_LOOKUP;
2718         DESTROYLOCK(&lookup_lock);
2719         if (memdebugging != 0)
2720                 isc_mem_stats(mctx, stderr);
2721         if (mctx != NULL)
2722                 isc_mem_destroy(&mctx);
2723 }