dighost.c revision 1.15 1 /* $NetBSD: dighost.c,v 1.15 2023/06/26 22:02:59 christos Exp $ */
2
3 /*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 *
12 * See the COPYRIGHT file distributed with this work for additional
13 * information regarding copyright ownership.
14 */
15
16 /*! \file
17 * \note
18 * Notice to programmers: Do not use this code as an example of how to
19 * use the ISC library to perform DNS lookups. Dig and Host both operate
20 * on the request level, since they allow fine-tuning of output and are
21 * intended as debugging tools. As a result, they perform many of the
22 * functions which could be better handled using the dns_resolver
23 * functions in most applications.
24 */
25
26 #include <errno.h>
27 #include <inttypes.h>
28 #include <limits.h>
29 #include <stdbool.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33
34 #ifdef HAVE_LOCALE_H
35 #include <locale.h>
36 #endif /* ifdef HAVE_LOCALE_H */
37
38 #ifdef HAVE_LIBIDN2
39 #include <idn2.h>
40 #endif /* HAVE_LIBIDN2 */
41
42 #include <isc/app.h>
43 #include <isc/base64.h>
44 #include <isc/file.h>
45 #include <isc/hex.h>
46 #include <isc/lang.h>
47 #include <isc/log.h>
48 #include <isc/managers.h>
49 #include <isc/netaddr.h>
50 #include <isc/netdb.h>
51 #include <isc/nonce.h>
52 #include <isc/parseint.h>
53 #include <isc/print.h>
54 #include <isc/random.h>
55 #include <isc/result.h>
56 #include <isc/safe.h>
57 #include <isc/serial.h>
58 #include <isc/sockaddr.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 <pk11/site.h>
66
67 #include <dns/byaddr.h>
68 #include <dns/fixedname.h>
69 #include <dns/log.h>
70 #include <dns/message.h>
71 #include <dns/name.h>
72 #include <dns/opcode.h>
73 #include <dns/rcode.h>
74 #include <dns/rdata.h>
75 #include <dns/rdataclass.h>
76 #include <dns/rdatalist.h>
77 #include <dns/rdataset.h>
78 #include <dns/rdatastruct.h>
79 #include <dns/rdatatype.h>
80 #include <dns/result.h>
81 #include <dns/tsig.h>
82
83 #include <dst/dst.h>
84 #include <dst/result.h>
85
86 #include <isccfg/namedconf.h>
87
88 #include <irs/resconf.h>
89
90 #include <bind9/getaddresses.h>
91
92 #include <dig/dig.h>
93
94 #if USE_PKCS11
95 #include <pk11/result.h>
96 #endif /* if USE_PKCS11 */
97
98 #if !defined(NS_INADDRSZ)
99 #define NS_INADDRSZ 4
100 #endif /* if !defined(NS_INADDRSZ) */
101
102 #if !defined(NS_IN6ADDRSZ)
103 #define NS_IN6ADDRSZ 16
104 #endif /* if !defined(NS_IN6ADDRSZ) */
105
106 #if HAVE_SETLOCALE
107 #define systemlocale(l) (void)setlocale(l, "")
108 #define resetlocale(l) (void)setlocale(l, "C")
109 #else
110 #define systemlocale(l)
111 #define resetlocale(l)
112 #endif /* HAVE_SETLOCALE */
113
114 dig_lookuplist_t lookup_list;
115 dig_serverlist_t server_list;
116 dig_searchlistlist_t search_list;
117
118 bool check_ra = false, have_ipv4 = false, have_ipv6 = false,
119 specified_source = false, free_now = false, cancel_now = false,
120 usesearch = false, showsearch = false, is_dst_up = false,
121 keep_open = false, verbose = false, yaml = false;
122 in_port_t port = 53;
123 unsigned int timeout = 0;
124 unsigned int extrabytes;
125 isc_mem_t *mctx = NULL;
126 isc_log_t *lctx = NULL;
127 isc_nm_t *netmgr = NULL;
128 isc_taskmgr_t *taskmgr = NULL;
129 isc_task_t *global_task = NULL;
130 isc_timermgr_t *timermgr = NULL;
131 isc_socketmgr_t *socketmgr = NULL;
132 isc_sockaddr_t bind_address;
133 isc_sockaddr_t bind_any;
134 int sendcount = 0;
135 int recvcount = 0;
136 int sockcount = 0;
137 int ndots = -1;
138 int tries = 3;
139 int lookup_counter = 0;
140
141 static char servercookie[256];
142
143 #ifdef HAVE_LIBIDN2
144 static void
145 idn_locale_to_ace(const char *src, char *dst, size_t dstlen);
146 static void
147 idn_ace_to_locale(const char *src, char **dst);
148 static isc_result_t
149 idn_output_filter(isc_buffer_t *buffer, unsigned int used_org);
150 #endif /* HAVE_LIBIDN2 */
151
152 isc_socket_t *keep = NULL;
153 isc_sockaddr_t keepaddr;
154
155 /*%
156 * Exit Codes:
157 *
158 *\li 0 Everything went well, including things like NXDOMAIN
159 *\li 1 Usage error
160 *\li 7 Got too many RR's or Names
161 *\li 8 Couldn't open batch file
162 *\li 9 No reply from server
163 *\li 10 Internal error
164 */
165 int exitcode = 0;
166 int fatalexit = 0;
167 char keynametext[MXNAME];
168 char keyfile[MXNAME] = "";
169 char keysecret[MXNAME] = "";
170 unsigned char cookie_secret[33];
171 unsigned char cookie[8];
172 const dns_name_t *hmacname = NULL;
173 unsigned int digestbits = 0;
174 isc_buffer_t *namebuf = NULL;
175 dns_tsigkey_t *tsigkey = NULL;
176 bool validated = true;
177 bool debugging = false;
178 bool debugtiming = false;
179 bool memdebugging = false;
180 const char *progname = NULL;
181 isc_mutex_t lookup_lock;
182 dig_lookup_t *current_lookup = NULL;
183
184 #define DIG_MAX_ADDRESSES 20
185
186 /*%
187 * Apply and clear locks at the event level in global task.
188 * Can I get rid of these using shutdown events? XXX
189 */
190 #define LOCK_LOOKUP \
191 { \
192 debug("lock_lookup %s:%d", __FILE__, __LINE__); \
193 check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_" \
194 "lock"); \
195 debug("success"); \
196 }
197 #define UNLOCK_LOOKUP \
198 { \
199 debug("unlock_lookup %s:%d", __FILE__, __LINE__); \
200 check_result(isc_mutex_unlock((&lookup_lock)), "isc_mutex_" \
201 "unlock"); \
202 }
203
204 static void
205 default_warnerr(const char *format, ...) {
206 va_list args;
207
208 printf(";; ");
209 va_start(args, format);
210 vprintf(format, args);
211 va_end(args);
212 printf("\n");
213 }
214
215 static void
216 default_comments(dig_lookup_t *lookup, const char *format, ...) {
217 va_list args;
218
219 if (lookup->comments) {
220 printf(";; ");
221 va_start(args, format);
222 vprintf(format, args);
223 va_end(args);
224 printf("\n");
225 }
226 }
227
228 /* dynamic callbacks */
229
230 isc_result_t (*dighost_printmessage)(dig_query_t *query,
231 const isc_buffer_t *msgbuf,
232 dns_message_t *msg, bool headers);
233
234 void (*dighost_error)(const char *format, ...) = default_warnerr;
235
236 void (*dighost_warning)(const char *format, ...) = default_warnerr;
237
238 void (*dighost_comments)(dig_lookup_t *lookup, const char *format,
239 ...) = default_comments;
240
241 void (*dighost_received)(unsigned int bytes, isc_sockaddr_t *from,
242 dig_query_t *query);
243
244 void (*dighost_trying)(char *frm, dig_lookup_t *lookup);
245
246 void (*dighost_shutdown)(void);
247
248 /* forward declarations */
249
250 static void
251 cancel_lookup(dig_lookup_t *lookup);
252
253 static void
254 recv_done(isc_task_t *task, isc_event_t *event);
255
256 static void
257 send_udp(dig_query_t *query);
258
259 static void
260 connect_timeout(isc_task_t *task, isc_event_t *event);
261
262 static void
263 launch_next_query(dig_query_t *query, bool include_question);
264
265 static void
266 check_next_lookup(dig_lookup_t *lookup);
267
268 static bool
269 next_origin(dig_lookup_t *oldlookup);
270
271 static int
272 count_dots(char *string) {
273 char *s;
274 int i = 0;
275
276 s = string;
277 while (*s != '\0') {
278 if (*s == '.') {
279 i++;
280 }
281 s++;
282 }
283 return (i);
284 }
285
286 static void
287 hex_dump(isc_buffer_t *b) {
288 unsigned int len, i;
289 isc_region_t r;
290
291 isc_buffer_usedregion(b, &r);
292
293 printf("%u bytes\n", r.length);
294 for (len = 0; len < r.length; len++) {
295 printf("%02x ", r.base[len]);
296 if (len % 16 == 15) {
297 fputs(" ", stdout);
298 for (i = len - 15; i <= len; i++) {
299 if (r.base[i] >= '!' && r.base[i] <= '}') {
300 putchar(r.base[i]);
301 } else {
302 putchar('.');
303 }
304 }
305 printf("\n");
306 }
307 }
308 if (len % 16 != 0) {
309 for (i = len; (i % 16) != 0; i++) {
310 fputs(" ", stdout);
311 }
312 fputs(" ", stdout);
313 for (i = ((len >> 4) << 4); i < len; i++) {
314 if (r.base[i] >= '!' && r.base[i] <= '}') {
315 putchar(r.base[i]);
316 } else {
317 putchar('.');
318 }
319 }
320 printf("\n");
321 }
322 }
323
324 /*%
325 * Append 'len' bytes of 'text' at '*p', failing with
326 * ISC_R_NOSPACE if that would advance p past 'end'.
327 */
328 static isc_result_t
329 append(const char *text, size_t len, char **p, char *end) {
330 if (*p + len > end) {
331 return (ISC_R_NOSPACE);
332 }
333 memmove(*p, text, len);
334 *p += len;
335 return (ISC_R_SUCCESS);
336 }
337
338 static isc_result_t
339 reverse_octets(const char *in, char **p, char *end) {
340 const char *dot = strchr(in, '.');
341 size_t len;
342 if (dot != NULL) {
343 isc_result_t result;
344 result = reverse_octets(dot + 1, p, end);
345 if (result != ISC_R_SUCCESS) {
346 return (result);
347 }
348 result = append(".", 1, p, end);
349 if (result != ISC_R_SUCCESS) {
350 return (result);
351 }
352 len = (int)(dot - in);
353 } else {
354 len = (int)strlen(in);
355 }
356 return (append(in, len, p, end));
357 }
358
359 isc_result_t
360 get_reverse(char *reverse, size_t len, char *value, bool strict) {
361 int r;
362 isc_result_t result;
363 isc_netaddr_t addr;
364
365 addr.family = AF_INET6;
366 r = inet_pton(AF_INET6, value, &addr.type.in6);
367 if (r > 0) {
368 /* This is a valid IPv6 address. */
369 dns_fixedname_t fname;
370 dns_name_t *name;
371 unsigned int options = 0;
372
373 name = dns_fixedname_initname(&fname);
374 result = dns_byaddr_createptrname(&addr, options, name);
375 if (result != ISC_R_SUCCESS) {
376 return (result);
377 }
378 dns_name_format(name, reverse, (unsigned int)len);
379 return (ISC_R_SUCCESS);
380 } else {
381 /*
382 * Not a valid IPv6 address. Assume IPv4.
383 * If 'strict' is not set, construct the
384 * in-addr.arpa name by blindly reversing
385 * octets whether or not they look like integers,
386 * so that this can be used for RFC2317 names
387 * and such.
388 */
389 char *p = reverse;
390 char *end = reverse + len;
391 if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1) {
392 return (DNS_R_BADDOTTEDQUAD);
393 }
394 result = reverse_octets(value, &p, end);
395 if (result != ISC_R_SUCCESS) {
396 return (result);
397 }
398 /* Append .in-addr.arpa. and a terminating NUL. */
399 result = append(".in-addr.arpa.", 15, &p, end);
400 if (result != ISC_R_SUCCESS) {
401 return (result);
402 }
403 return (ISC_R_SUCCESS);
404 }
405 }
406
407 void (*dighost_pre_exit_hook)(void) = NULL;
408
409 #if TARGET_OS_IPHONE
410 void
411 warn(const char *format, ...) {
412 va_list args;
413
414 fflush(stdout);
415 fprintf(stderr, ";; Warning: ");
416 va_start(args, format);
417 vfprintf(stderr, format, args);
418 va_end(args);
419 fprintf(stderr, "\n");
420 }
421 #else /* if TARGET_OS_IPHONE */
422 void
423 warn(const char *format, ...) {
424 va_list args;
425
426 fflush(stdout);
427 fprintf(stderr, "%s: ", progname);
428 va_start(args, format);
429 vfprintf(stderr, format, args);
430 va_end(args);
431 fprintf(stderr, "\n");
432 }
433 #endif /* if TARGET_OS_IPHONE */
434
435 void
436 digexit(void) {
437 if (exitcode < 10) {
438 exitcode = 10;
439 }
440 if (fatalexit != 0) {
441 exitcode = fatalexit;
442 }
443 if (dighost_pre_exit_hook != NULL) {
444 dighost_pre_exit_hook();
445 }
446 exit(exitcode);
447 }
448
449 void
450 fatal(const char *format, ...) {
451 va_list args;
452
453 fflush(stdout);
454 fprintf(stderr, "%s: ", progname);
455 va_start(args, format);
456 vfprintf(stderr, format, args);
457 va_end(args);
458 fprintf(stderr, "\n");
459 digexit();
460 }
461
462 void
463 debug(const char *format, ...) {
464 va_list args;
465 isc_time_t t;
466
467 if (debugging) {
468 fflush(stdout);
469 if (debugtiming) {
470 TIME_NOW(&t);
471 fprintf(stderr, "%u.%06u: ", isc_time_seconds(&t),
472 isc_time_nanoseconds(&t) / 1000);
473 }
474 va_start(args, format);
475 vfprintf(stderr, format, args);
476 va_end(args);
477 fprintf(stderr, "\n");
478 }
479 }
480
481 void
482 check_result(isc_result_t result, const char *msg) {
483 if (result != ISC_R_SUCCESS) {
484 fatal("%s: %s", msg, isc_result_totext(result));
485 }
486 }
487
488 /*%
489 * Create a server structure, which is part of the lookup structure.
490 * This is little more than a linked list of servers to query in hopes
491 * of finding the answer the user is looking for
492 */
493 dig_server_t *
494 make_server(const char *servname, const char *userarg) {
495 dig_server_t *srv;
496
497 REQUIRE(servname != NULL);
498
499 debug("make_server(%s)", servname);
500 srv = isc_mem_allocate(mctx, sizeof(struct dig_server));
501 strlcpy(srv->servername, servname, MXNAME);
502 strlcpy(srv->userarg, userarg, MXNAME);
503 ISC_LINK_INIT(srv, link);
504 return (srv);
505 }
506
507 /*%
508 * Create a copy of the server list from the resolver configuration structure.
509 * The dest list must have already had ISC_LIST_INIT applied.
510 */
511 static void
512 get_server_list(irs_resconf_t *resconf) {
513 isc_sockaddrlist_t *servers;
514 isc_sockaddr_t *sa;
515 dig_server_t *newsrv;
516 char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") +
517 sizeof("%4000000000")];
518 debug("get_server_list()");
519 servers = irs_resconf_getnameservers(resconf);
520 for (sa = ISC_LIST_HEAD(*servers); sa != NULL;
521 sa = ISC_LIST_NEXT(sa, link))
522 {
523 int pf = isc_sockaddr_pf(sa);
524 isc_netaddr_t na;
525 isc_result_t result;
526 isc_buffer_t b;
527
528 if (pf == AF_INET && !have_ipv4) {
529 continue;
530 }
531 if (pf == AF_INET6 && !have_ipv6) {
532 continue;
533 }
534
535 isc_buffer_init(&b, tmp, sizeof(tmp));
536 isc_netaddr_fromsockaddr(&na, sa);
537 result = isc_netaddr_totext(&na, &b);
538 if (result != ISC_R_SUCCESS) {
539 continue;
540 }
541 isc_buffer_putuint8(&b, 0);
542 if (pf == AF_INET6 && na.zone != 0) {
543 char buf[sizeof("%4000000000")];
544 snprintf(buf, sizeof(buf), "%%%u", na.zone);
545 strlcat(tmp, buf, sizeof(tmp));
546 }
547 newsrv = make_server(tmp, tmp);
548 ISC_LINK_INIT(newsrv, link);
549 ISC_LIST_APPEND(server_list, newsrv, link);
550 }
551 }
552
553 void
554 flush_server_list(void) {
555 dig_server_t *s, *ps;
556
557 debug("flush_server_list()");
558 s = ISC_LIST_HEAD(server_list);
559 while (s != NULL) {
560 ps = s;
561 s = ISC_LIST_NEXT(s, link);
562 ISC_LIST_DEQUEUE(server_list, ps, link);
563 isc_mem_free(mctx, ps);
564 }
565 }
566
567 void
568 set_nameserver(char *opt) {
569 isc_result_t result;
570 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
571 isc_netaddr_t netaddr;
572 int count, i;
573 dig_server_t *srv;
574 char tmp[ISC_NETADDR_FORMATSIZE];
575
576 if (opt == NULL) {
577 return;
578 }
579
580 result = bind9_getaddresses(opt, 0, sockaddrs, DIG_MAX_ADDRESSES,
581 &count);
582 if (result != ISC_R_SUCCESS) {
583 fatal("couldn't get address for '%s': %s", opt,
584 isc_result_totext(result));
585 }
586
587 flush_server_list();
588
589 for (i = 0; i < count; i++) {
590 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
591 isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
592 srv = make_server(tmp, opt);
593 if (srv == NULL) {
594 fatal("memory allocation failure");
595 }
596 ISC_LIST_APPEND(server_list, srv, link);
597 }
598 }
599
600 /*%
601 * Produce a cloned server list. The dest list must have already had
602 * ISC_LIST_INIT applied.
603 */
604 void
605 clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
606 dig_server_t *srv, *newsrv;
607
608 debug("clone_server_list()");
609 srv = ISC_LIST_HEAD(src);
610 while (srv != NULL) {
611 newsrv = make_server(srv->servername, srv->userarg);
612 ISC_LINK_INIT(newsrv, link);
613 ISC_LIST_ENQUEUE(*dest, newsrv, link);
614 srv = ISC_LIST_NEXT(srv, link);
615 }
616 }
617
618 /*%
619 * Create an empty lookup structure, which holds all the information needed
620 * to get an answer to a user's question. This structure contains two
621 * linked lists: the server list (servers to query) and the query list
622 * (outstanding queries which have been made to the listed servers).
623 */
624 dig_lookup_t *
625 make_empty_lookup(void) {
626 dig_lookup_t *looknew;
627
628 debug("make_empty_lookup()");
629
630 INSIST(!free_now);
631
632 looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
633 looknew->pending = true;
634 looknew->textname[0] = 0;
635 looknew->cmdline[0] = 0;
636 looknew->rdtype = dns_rdatatype_a;
637 looknew->qrdtype = dns_rdatatype_a;
638 looknew->rdclass = dns_rdataclass_in;
639 looknew->rdtypeset = false;
640 looknew->rdclassset = false;
641 looknew->sendspace = NULL;
642 looknew->sendmsg = NULL;
643 looknew->name = NULL;
644 looknew->oname = NULL;
645 looknew->xfr_q = NULL;
646 looknew->current_query = NULL;
647 looknew->doing_xfr = false;
648 looknew->ixfr_serial = 0;
649 looknew->trace = false;
650 looknew->trace_root = false;
651 looknew->identify = false;
652 looknew->identify_previous_line = false;
653 looknew->ignore = false;
654 looknew->servfail_stops = true;
655 looknew->besteffort = true;
656 looknew->dnssec = false;
657 looknew->ednsflags = 0;
658 looknew->opcode = dns_opcode_query;
659 looknew->expire = false;
660 looknew->nsid = false;
661 looknew->tcp_keepalive = false;
662 looknew->padding = 0;
663 looknew->header_only = false;
664 looknew->sendcookie = false;
665 looknew->seenbadcookie = false;
666 looknew->badcookie = true;
667 looknew->multiline = false;
668 looknew->nottl = false;
669 looknew->noclass = false;
670 looknew->onesoa = false;
671 looknew->use_usec = false;
672 looknew->nocrypto = false;
673 looknew->ttlunits = false;
674 looknew->expandaaaa = false;
675 looknew->qr = false;
676 looknew->accept_reply_unexpected_src = false;
677 #ifdef HAVE_LIBIDN2
678 looknew->idnin = isatty(1) ? (getenv("IDN_DISABLE") == NULL) : false;
679 looknew->idnout = looknew->idnin;
680 #else /* ifdef HAVE_LIBIDN2 */
681 looknew->idnin = false;
682 looknew->idnout = false;
683 #endif /* HAVE_LIBIDN2 */
684 looknew->udpsize = -1;
685 looknew->edns = -1;
686 looknew->recurse = true;
687 looknew->aaonly = false;
688 looknew->adflag = false;
689 looknew->cdflag = false;
690 looknew->raflag = false;
691 looknew->tcflag = false;
692 looknew->print_unknown_format = false;
693 looknew->zflag = false;
694 looknew->ns_search_only = false;
695 looknew->origin = NULL;
696 looknew->tsigctx = NULL;
697 looknew->querysig = NULL;
698 looknew->retries = tries;
699 looknew->nsfound = 0;
700 looknew->tcp_mode = false;
701 looknew->tcp_mode_set = false;
702 looknew->comments = true;
703 looknew->stats = true;
704 looknew->section_question = true;
705 looknew->section_answer = true;
706 looknew->section_authority = true;
707 looknew->section_additional = true;
708 looknew->new_search = false;
709 looknew->done_as_is = false;
710 looknew->need_search = false;
711 looknew->ecs_addr = NULL;
712 looknew->cookie = NULL;
713 looknew->ednsopts = NULL;
714 looknew->ednsoptscnt = 0;
715 looknew->ednsneg = true;
716 looknew->mapped = true;
717 looknew->dscp = -1;
718 looknew->rrcomments = 0;
719 looknew->eoferr = 0;
720 dns_fixedname_init(&looknew->fdomain);
721 ISC_LINK_INIT(looknew, link);
722 ISC_LIST_INIT(looknew->q);
723 ISC_LIST_INIT(looknew->connecting);
724 ISC_LIST_INIT(looknew->my_server_list);
725 return (looknew);
726 }
727
728 #define EDNSOPT_OPTIONS 100U
729
730 static void
731 cloneopts(dig_lookup_t *looknew, dig_lookup_t *lookold) {
732 size_t len = sizeof(looknew->ednsopts[0]) * EDNSOPT_OPTIONS;
733 size_t i;
734 looknew->ednsopts = isc_mem_allocate(mctx, len);
735 for (i = 0; i < EDNSOPT_OPTIONS; i++) {
736 looknew->ednsopts[i].code = 0;
737 looknew->ednsopts[i].length = 0;
738 looknew->ednsopts[i].value = NULL;
739 }
740 looknew->ednsoptscnt = 0;
741 if (lookold == NULL || lookold->ednsopts == NULL) {
742 return;
743 }
744
745 for (i = 0; i < lookold->ednsoptscnt; i++) {
746 len = lookold->ednsopts[i].length;
747 if (len != 0) {
748 INSIST(lookold->ednsopts[i].value != NULL);
749 looknew->ednsopts[i].value = isc_mem_allocate(mctx,
750 len);
751 memmove(looknew->ednsopts[i].value,
752 lookold->ednsopts[i].value, len);
753 }
754 looknew->ednsopts[i].code = lookold->ednsopts[i].code;
755 looknew->ednsopts[i].length = len;
756 }
757 looknew->ednsoptscnt = lookold->ednsoptscnt;
758 }
759
760 /*%
761 * Clone a lookup, perhaps copying the server list. This does not clone
762 * the query list, since it will be regenerated by the setup_lookup()
763 * function, nor does it queue up the new lookup for processing.
764 * Caution: If you don't clone the servers, you MUST clone the server
765 * list separately from somewhere else, or construct it by hand.
766 */
767 dig_lookup_t *
768 clone_lookup(dig_lookup_t *lookold, bool servers) {
769 dig_lookup_t *looknew;
770
771 debug("clone_lookup(%p)", lookold);
772
773 INSIST(!free_now);
774
775 looknew = make_empty_lookup();
776 INSIST(looknew != NULL);
777 strlcpy(looknew->textname, lookold->textname, MXNAME);
778 strlcpy(looknew->cmdline, lookold->cmdline, MXNAME);
779 looknew->textname[MXNAME - 1] = 0;
780 looknew->rdtype = lookold->rdtype;
781 looknew->qrdtype = lookold->qrdtype;
782 looknew->rdclass = lookold->rdclass;
783 looknew->rdtypeset = lookold->rdtypeset;
784 looknew->rdclassset = lookold->rdclassset;
785 looknew->doing_xfr = lookold->doing_xfr;
786 looknew->ixfr_serial = lookold->ixfr_serial;
787 looknew->trace = lookold->trace;
788 looknew->trace_root = lookold->trace_root;
789 looknew->identify = lookold->identify;
790 looknew->identify_previous_line = lookold->identify_previous_line;
791 looknew->ignore = lookold->ignore;
792 looknew->servfail_stops = lookold->servfail_stops;
793 looknew->besteffort = lookold->besteffort;
794 looknew->dnssec = lookold->dnssec;
795 looknew->ednsflags = lookold->ednsflags;
796 looknew->opcode = lookold->opcode;
797 looknew->expire = lookold->expire;
798 looknew->nsid = lookold->nsid;
799 looknew->tcp_keepalive = lookold->tcp_keepalive;
800 looknew->header_only = lookold->header_only;
801 looknew->sendcookie = lookold->sendcookie;
802 looknew->seenbadcookie = lookold->seenbadcookie;
803 looknew->badcookie = lookold->badcookie;
804 looknew->cookie = lookold->cookie;
805 if (lookold->ednsopts != NULL) {
806 cloneopts(looknew, lookold);
807 } else {
808 looknew->ednsopts = NULL;
809 looknew->ednsoptscnt = 0;
810 }
811 looknew->ednsneg = lookold->ednsneg;
812 looknew->padding = lookold->padding;
813 looknew->mapped = lookold->mapped;
814 looknew->multiline = lookold->multiline;
815 looknew->nottl = lookold->nottl;
816 looknew->noclass = lookold->noclass;
817 looknew->onesoa = lookold->onesoa;
818 looknew->use_usec = lookold->use_usec;
819 looknew->nocrypto = lookold->nocrypto;
820 looknew->ttlunits = lookold->ttlunits;
821 looknew->expandaaaa = lookold->expandaaaa;
822 looknew->qr = lookold->qr;
823 looknew->accept_reply_unexpected_src =
824 lookold->accept_reply_unexpected_src;
825 looknew->idnin = lookold->idnin;
826 looknew->idnout = lookold->idnout;
827 looknew->udpsize = lookold->udpsize;
828 looknew->edns = lookold->edns;
829 looknew->recurse = lookold->recurse;
830 looknew->aaonly = lookold->aaonly;
831 looknew->adflag = lookold->adflag;
832 looknew->cdflag = lookold->cdflag;
833 looknew->raflag = lookold->raflag;
834 looknew->tcflag = lookold->tcflag;
835 looknew->print_unknown_format = lookold->print_unknown_format;
836 looknew->zflag = lookold->zflag;
837 looknew->ns_search_only = lookold->ns_search_only;
838 looknew->tcp_mode = lookold->tcp_mode;
839 looknew->tcp_mode_set = lookold->tcp_mode_set;
840 looknew->comments = lookold->comments;
841 looknew->stats = lookold->stats;
842 looknew->section_question = lookold->section_question;
843 looknew->section_answer = lookold->section_answer;
844 looknew->section_authority = lookold->section_authority;
845 looknew->section_additional = lookold->section_additional;
846 looknew->origin = lookold->origin;
847 looknew->retries = lookold->retries;
848 looknew->tsigctx = NULL;
849 looknew->need_search = lookold->need_search;
850 looknew->done_as_is = lookold->done_as_is;
851 looknew->dscp = lookold->dscp;
852 looknew->rrcomments = lookold->rrcomments;
853 looknew->eoferr = lookold->eoferr;
854
855 if (lookold->ecs_addr != NULL) {
856 size_t len = sizeof(isc_sockaddr_t);
857 looknew->ecs_addr = isc_mem_allocate(mctx, len);
858 memmove(looknew->ecs_addr, lookold->ecs_addr, len);
859 }
860
861 dns_name_copynf(dns_fixedname_name(&lookold->fdomain),
862 dns_fixedname_name(&looknew->fdomain));
863
864 if (servers) {
865 clone_server_list(lookold->my_server_list,
866 &looknew->my_server_list);
867 }
868 return (looknew);
869 }
870
871 /*%
872 * Requeue a lookup for further processing, perhaps copying the server
873 * list. The new lookup structure is returned to the caller, and is
874 * queued for processing. If servers are not cloned in the requeue, they
875 * must be added before allowing the current event to complete, since the
876 * completion of the event may result in the next entry on the lookup
877 * queue getting run.
878 */
879 dig_lookup_t *
880 requeue_lookup(dig_lookup_t *lookold, bool servers) {
881 dig_lookup_t *looknew;
882
883 debug("requeue_lookup(%p)", lookold);
884
885 lookup_counter++;
886 if (lookup_counter > LOOKUP_LIMIT) {
887 fatal("too many lookups");
888 }
889
890 looknew = clone_lookup(lookold, servers);
891 INSIST(looknew != NULL);
892
893 debug("before insertion, init@%p -> %p, new@%p -> %p", lookold,
894 lookold->link.next, looknew, looknew->link.next);
895 ISC_LIST_PREPEND(lookup_list, looknew, link);
896 debug("after insertion, init -> %p, new = %p, new -> %p", lookold,
897 looknew, looknew->link.next);
898 return (looknew);
899 }
900
901 void
902 setup_text_key(void) {
903 isc_result_t result;
904 dns_name_t keyname;
905 isc_buffer_t secretbuf;
906 unsigned int secretsize;
907 unsigned char *secretstore;
908
909 debug("setup_text_key()");
910 isc_buffer_allocate(mctx, &namebuf, MXNAME);
911 dns_name_init(&keyname, NULL);
912 isc_buffer_putstr(namebuf, keynametext);
913 secretsize = (unsigned int)strlen(keysecret) * 3 / 4;
914 secretstore = isc_mem_allocate(mctx, secretsize);
915 isc_buffer_init(&secretbuf, secretstore, secretsize);
916 result = isc_base64_decodestring(keysecret, &secretbuf);
917 if (result != ISC_R_SUCCESS) {
918 goto failure;
919 }
920
921 secretsize = isc_buffer_usedlength(&secretbuf);
922
923 if (hmacname == NULL) {
924 result = DST_R_UNSUPPORTEDALG;
925 goto failure;
926 }
927
928 result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf);
929 if (result != ISC_R_SUCCESS) {
930 goto failure;
931 }
932
933 result = dns_tsigkey_create(&keyname, hmacname, secretstore,
934 (int)secretsize, false, NULL, 0, 0, mctx,
935 NULL, &tsigkey);
936 failure:
937 if (result != ISC_R_SUCCESS) {
938 printf(";; Couldn't create key %s: %s\n", keynametext,
939 isc_result_totext(result));
940 } else {
941 dst_key_setbits(tsigkey->key, digestbits);
942 }
943
944 isc_mem_free(mctx, secretstore);
945 dns_name_invalidate(&keyname);
946 isc_buffer_free(&namebuf);
947 }
948
949 static isc_result_t
950 parse_uint_helper(uint32_t *uip, const char *value, uint32_t max,
951 const char *desc, int base) {
952 uint32_t n;
953 isc_result_t result = isc_parse_uint32(&n, value, base);
954 if (result == ISC_R_SUCCESS && n > max) {
955 result = ISC_R_RANGE;
956 }
957 if (result != ISC_R_SUCCESS) {
958 printf("invalid %s '%s': %s\n", desc, value,
959 isc_result_totext(result));
960 return (result);
961 }
962 *uip = n;
963 return (ISC_R_SUCCESS);
964 }
965
966 isc_result_t
967 parse_uint(uint32_t *uip, const char *value, uint32_t max, const char *desc) {
968 return (parse_uint_helper(uip, value, max, desc, 10));
969 }
970
971 isc_result_t
972 parse_xint(uint32_t *uip, const char *value, uint32_t max, const char *desc) {
973 return (parse_uint_helper(uip, value, max, desc, 0));
974 }
975
976 static uint32_t
977 parse_bits(char *arg, const char *desc, uint32_t max) {
978 isc_result_t result;
979 uint32_t tmp;
980
981 result = parse_uint(&tmp, arg, max, desc);
982 if (result != ISC_R_SUCCESS) {
983 fatal("couldn't parse digest bits");
984 }
985 tmp = (tmp + 7) & ~0x7U;
986 return (tmp);
987 }
988
989 isc_result_t
990 parse_netprefix(isc_sockaddr_t **sap, const char *value) {
991 isc_result_t result = ISC_R_SUCCESS;
992 isc_sockaddr_t *sa = NULL;
993 struct in_addr in4;
994 struct in6_addr in6;
995 uint32_t prefix_length = 0xffffffff;
996 char *slash = NULL;
997 bool parsed = false;
998 bool prefix_parsed = false;
999 char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:XXX.XXX.XXX.XXX/128")];
1000
1001 REQUIRE(sap != NULL && *sap == NULL);
1002
1003 if (strlcpy(buf, value, sizeof(buf)) >= sizeof(buf)) {
1004 fatal("invalid prefix '%s'\n", value);
1005 }
1006
1007 sa = isc_mem_allocate(mctx, sizeof(*sa));
1008 memset(sa, 0, sizeof(*sa));
1009
1010 if (strcmp(buf, "0") == 0) {
1011 sa->type.sa.sa_family = AF_UNSPEC;
1012 prefix_length = 0;
1013 goto done;
1014 }
1015
1016 slash = strchr(buf, '/');
1017 if (slash != NULL) {
1018 *slash = '\0';
1019 result = isc_parse_uint32(&prefix_length, slash + 1, 10);
1020 if (result != ISC_R_SUCCESS) {
1021 fatal("invalid prefix length in '%s': %s\n", value,
1022 isc_result_totext(result));
1023 }
1024 prefix_parsed = true;
1025 }
1026
1027 if (inet_pton(AF_INET6, buf, &in6) == 1) {
1028 parsed = true;
1029 isc_sockaddr_fromin6(sa, &in6, 0);
1030 if (prefix_length > 128) {
1031 prefix_length = 128;
1032 }
1033 } else if (inet_pton(AF_INET, buf, &in4) == 1) {
1034 parsed = true;
1035 isc_sockaddr_fromin(sa, &in4, 0);
1036 if (prefix_length > 32) {
1037 prefix_length = 32;
1038 }
1039 } else if (prefix_parsed) {
1040 int i;
1041
1042 for (i = 0; i < 3 && strlen(buf) < sizeof(buf) - 2; i++) {
1043 strlcat(buf, ".0", sizeof(buf));
1044 if (inet_pton(AF_INET, buf, &in4) == 1) {
1045 parsed = true;
1046 isc_sockaddr_fromin(sa, &in4, 0);
1047 break;
1048 }
1049 }
1050
1051 if (prefix_length > 32) {
1052 prefix_length = 32;
1053 }
1054 }
1055
1056 if (!parsed) {
1057 fatal("invalid address '%s'", value);
1058 }
1059
1060 done:
1061 sa->length = prefix_length;
1062 *sap = sa;
1063
1064 return (ISC_R_SUCCESS);
1065 }
1066
1067 /*
1068 * Parse HMAC algorithm specification
1069 */
1070 void
1071 parse_hmac(const char *hmac) {
1072 char buf[20];
1073 size_t len;
1074
1075 REQUIRE(hmac != NULL);
1076
1077 len = strlen(hmac);
1078 if (len >= sizeof(buf)) {
1079 fatal("unknown key type '%.*s'", (int)len, hmac);
1080 }
1081 strlcpy(buf, hmac, sizeof(buf));
1082
1083 digestbits = 0;
1084
1085 if (strcasecmp(buf, "hmac-md5") == 0) {
1086 hmacname = DNS_TSIG_HMACMD5_NAME;
1087 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
1088 hmacname = DNS_TSIG_HMACMD5_NAME;
1089 digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128);
1090 } else if (strcasecmp(buf, "hmac-sha1") == 0) {
1091 hmacname = DNS_TSIG_HMACSHA1_NAME;
1092 digestbits = 0;
1093 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
1094 hmacname = DNS_TSIG_HMACSHA1_NAME;
1095 digestbits = parse_bits(&buf[10], "digest-bits [0..160]", 160);
1096 } else if (strcasecmp(buf, "hmac-sha224") == 0) {
1097 hmacname = DNS_TSIG_HMACSHA224_NAME;
1098 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
1099 hmacname = DNS_TSIG_HMACSHA224_NAME;
1100 digestbits = parse_bits(&buf[12], "digest-bits [0..224]", 224);
1101 } else if (strcasecmp(buf, "hmac-sha256") == 0) {
1102 hmacname = DNS_TSIG_HMACSHA256_NAME;
1103 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
1104 hmacname = DNS_TSIG_HMACSHA256_NAME;
1105 digestbits = parse_bits(&buf[12], "digest-bits [0..256]", 256);
1106 } else if (strcasecmp(buf, "hmac-sha384") == 0) {
1107 hmacname = DNS_TSIG_HMACSHA384_NAME;
1108 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
1109 hmacname = DNS_TSIG_HMACSHA384_NAME;
1110 digestbits = parse_bits(&buf[12], "digest-bits [0..384]", 384);
1111 } else if (strcasecmp(buf, "hmac-sha512") == 0) {
1112 hmacname = DNS_TSIG_HMACSHA512_NAME;
1113 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
1114 hmacname = DNS_TSIG_HMACSHA512_NAME;
1115 digestbits = parse_bits(&buf[12], "digest-bits [0..512]", 512);
1116 } else {
1117 fprintf(stderr,
1118 ";; Warning, ignoring "
1119 "invalid TSIG algorithm %s\n",
1120 buf);
1121 }
1122 }
1123
1124 /*
1125 * Get a key from a named.conf format keyfile
1126 */
1127 static isc_result_t
1128 read_confkey(void) {
1129 cfg_parser_t *pctx = NULL;
1130 cfg_obj_t *file = NULL;
1131 const cfg_obj_t *keyobj = NULL;
1132 const cfg_obj_t *secretobj = NULL;
1133 const cfg_obj_t *algorithmobj = NULL;
1134 const char *keyname;
1135 const char *secretstr;
1136 const char *algorithm;
1137 isc_result_t result;
1138
1139 if (!isc_file_exists(keyfile)) {
1140 return (ISC_R_FILENOTFOUND);
1141 }
1142
1143 result = cfg_parser_create(mctx, NULL, &pctx);
1144 if (result != ISC_R_SUCCESS) {
1145 goto cleanup;
1146 }
1147
1148 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey, &file);
1149 if (result != ISC_R_SUCCESS) {
1150 goto cleanup;
1151 }
1152
1153 result = cfg_map_get(file, "key", &keyobj);
1154 if (result != ISC_R_SUCCESS) {
1155 goto cleanup;
1156 }
1157
1158 (void)cfg_map_get(keyobj, "secret", &secretobj);
1159 (void)cfg_map_get(keyobj, "algorithm", &algorithmobj);
1160 if (secretobj == NULL || algorithmobj == NULL) {
1161 fatal("key must have algorithm and secret");
1162 }
1163
1164 keyname = cfg_obj_asstring(cfg_map_getname(keyobj));
1165 secretstr = cfg_obj_asstring(secretobj);
1166 algorithm = cfg_obj_asstring(algorithmobj);
1167
1168 strlcpy(keynametext, keyname, sizeof(keynametext));
1169 strlcpy(keysecret, secretstr, sizeof(keysecret));
1170 parse_hmac(algorithm);
1171 setup_text_key();
1172
1173 cleanup:
1174 if (pctx != NULL) {
1175 if (file != NULL) {
1176 cfg_obj_destroy(pctx, &file);
1177 }
1178 cfg_parser_destroy(&pctx);
1179 }
1180
1181 return (result);
1182 }
1183
1184 void
1185 setup_file_key(void) {
1186 isc_result_t result;
1187 dst_key_t *dstkey = NULL;
1188
1189 debug("setup_file_key()");
1190
1191 /* Try reading the key from a K* pair */
1192 result = dst_key_fromnamedfile(
1193 keyfile, NULL, DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, &dstkey);
1194
1195 /* If that didn't work, try reading it as a session.key keyfile */
1196 if (result != ISC_R_SUCCESS) {
1197 result = read_confkey();
1198 if (result == ISC_R_SUCCESS) {
1199 return;
1200 }
1201 }
1202
1203 if (result != ISC_R_SUCCESS) {
1204 fprintf(stderr, "Couldn't read key from %s: %s\n", keyfile,
1205 isc_result_totext(result));
1206 goto failure;
1207 }
1208
1209 switch (dst_key_alg(dstkey)) {
1210 case DST_ALG_HMACMD5:
1211 hmacname = DNS_TSIG_HMACMD5_NAME;
1212 break;
1213 case DST_ALG_HMACSHA1:
1214 hmacname = DNS_TSIG_HMACSHA1_NAME;
1215 break;
1216 case DST_ALG_HMACSHA224:
1217 hmacname = DNS_TSIG_HMACSHA224_NAME;
1218 break;
1219 case DST_ALG_HMACSHA256:
1220 hmacname = DNS_TSIG_HMACSHA256_NAME;
1221 break;
1222 case DST_ALG_HMACSHA384:
1223 hmacname = DNS_TSIG_HMACSHA384_NAME;
1224 break;
1225 case DST_ALG_HMACSHA512:
1226 hmacname = DNS_TSIG_HMACSHA512_NAME;
1227 break;
1228 default:
1229 printf(";; Couldn't create key %s: bad algorithm\n",
1230 keynametext);
1231 goto failure;
1232 }
1233 result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmacname,
1234 dstkey, false, NULL, 0, 0, mctx,
1235 NULL, &tsigkey);
1236 if (result != ISC_R_SUCCESS) {
1237 printf(";; Couldn't create key %s: %s\n", keynametext,
1238 isc_result_totext(result));
1239 goto failure;
1240 }
1241 failure:
1242 if (dstkey != NULL) {
1243 dst_key_free(&dstkey);
1244 }
1245 }
1246
1247 static dig_searchlist_t *
1248 make_searchlist_entry(char *domain) {
1249 dig_searchlist_t *search;
1250 search = isc_mem_allocate(mctx, sizeof(*search));
1251 strlcpy(search->origin, domain, MXNAME);
1252 search->origin[MXNAME - 1] = 0;
1253 ISC_LINK_INIT(search, link);
1254 return (search);
1255 }
1256
1257 static void
1258 clear_searchlist(void) {
1259 dig_searchlist_t *search;
1260 while ((search = ISC_LIST_HEAD(search_list)) != NULL) {
1261 ISC_LIST_UNLINK(search_list, search, link);
1262 isc_mem_free(mctx, search);
1263 }
1264 }
1265
1266 static void
1267 create_search_list(irs_resconf_t *resconf) {
1268 irs_resconf_searchlist_t *list;
1269 irs_resconf_search_t *entry;
1270 dig_searchlist_t *search;
1271
1272 debug("create_search_list()");
1273 clear_searchlist();
1274
1275 list = irs_resconf_getsearchlist(resconf);
1276 for (entry = ISC_LIST_HEAD(*list); entry != NULL;
1277 entry = ISC_LIST_NEXT(entry, link))
1278 {
1279 search = make_searchlist_entry(entry->domain);
1280 ISC_LIST_APPEND(search_list, search, link);
1281 }
1282 }
1283
1284 /*%
1285 * Append 'addr' to the list of servers to be queried. This function is only
1286 * called when no server addresses are explicitly specified and either libirs
1287 * returns an empty list of servers to use or none of the addresses returned by
1288 * libirs are usable due to the specified address family restrictions.
1289 */
1290 static void
1291 add_fallback_nameserver(const char *addr) {
1292 dig_server_t *server = make_server(addr, addr);
1293 ISC_LINK_INIT(server, link);
1294 ISC_LIST_APPEND(server_list, server, link);
1295 }
1296
1297 /*%
1298 * Setup the system as a whole, reading key information and resolv.conf
1299 * settings.
1300 */
1301 void
1302 setup_system(bool ipv4only, bool ipv6only) {
1303 irs_resconf_t *resconf = NULL;
1304 isc_result_t result;
1305
1306 debug("setup_system()");
1307
1308 if (ipv4only) {
1309 if (have_ipv4) {
1310 isc_net_disableipv6();
1311 have_ipv6 = false;
1312 } else {
1313 fatal("can't find IPv4 networking");
1314 }
1315 }
1316
1317 if (ipv6only) {
1318 if (have_ipv6) {
1319 isc_net_disableipv4();
1320 have_ipv4 = false;
1321 } else {
1322 fatal("can't find IPv6 networking");
1323 }
1324 }
1325
1326 result = irs_resconf_load(mctx, RESOLV_CONF, &resconf);
1327 if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
1328 fatal("parse of %s failed", RESOLV_CONF);
1329 }
1330
1331 create_search_list(resconf);
1332 if (ndots == -1) {
1333 ndots = irs_resconf_getndots(resconf);
1334 debug("ndots is %d.", ndots);
1335 }
1336
1337 /* If user doesn't specify server use nameservers from resolv.conf. */
1338 if (ISC_LIST_EMPTY(server_list)) {
1339 get_server_list(resconf);
1340 }
1341
1342 /* If we don't find a nameserver fall back to localhost */
1343 if (ISC_LIST_EMPTY(server_list)) {
1344 if (have_ipv6) {
1345 add_fallback_nameserver("::1");
1346 }
1347 if (have_ipv4) {
1348 add_fallback_nameserver("127.0.0.1");
1349 }
1350 }
1351
1352 irs_resconf_destroy(&resconf);
1353
1354 if (keyfile[0] != 0) {
1355 setup_file_key();
1356 } else if (keysecret[0] != 0) {
1357 setup_text_key();
1358 }
1359
1360 isc_nonce_buf(cookie_secret, sizeof(cookie_secret));
1361 }
1362
1363 /*%
1364 * Override the search list derived from resolv.conf by 'domain'.
1365 */
1366 void
1367 set_search_domain(char *domain) {
1368 dig_searchlist_t *search;
1369
1370 clear_searchlist();
1371 search = make_searchlist_entry(domain);
1372 ISC_LIST_APPEND(search_list, search, link);
1373 }
1374
1375 /*%
1376 * Setup the ISC and DNS libraries for use by the system.
1377 */
1378 void
1379 setup_libs(void) {
1380 isc_result_t result;
1381 isc_logconfig_t *logconfig = NULL;
1382
1383 debug("setup_libs()");
1384
1385 #if USE_PKCS11
1386 pk11_result_register();
1387 #endif /* if USE_PKCS11 */
1388 dns_result_register();
1389
1390 result = isc_net_probeipv4();
1391 if (result == ISC_R_SUCCESS) {
1392 have_ipv4 = true;
1393 }
1394
1395 result = isc_net_probeipv6();
1396 if (result == ISC_R_SUCCESS) {
1397 have_ipv6 = true;
1398 }
1399 if (!have_ipv6 && !have_ipv4) {
1400 fatal("can't find either v4 or v6 networking");
1401 }
1402
1403 isc_mem_create(&mctx);
1404 isc_mem_setname(mctx, "dig", NULL);
1405
1406 isc_log_create(mctx, &lctx, &logconfig);
1407 isc_log_setcontext(lctx);
1408 dns_log_init(lctx);
1409 dns_log_setcontext(lctx);
1410
1411 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
1412 check_result(result, "isc_log_usechannel");
1413
1414 isc_log_setdebuglevel(lctx, 0);
1415
1416 result = isc_managers_create(mctx, 1, 0, &netmgr, &taskmgr);
1417 check_result(result, "isc_managers_create");
1418
1419 result = isc_task_create(taskmgr, 0, &global_task);
1420 check_result(result, "isc_task_create");
1421 isc_task_setname(global_task, "dig", NULL);
1422
1423 result = isc_timermgr_create(mctx, &timermgr);
1424 check_result(result, "isc_timermgr_create");
1425
1426 result = isc_socketmgr_create(mctx, &socketmgr);
1427 check_result(result, "isc_socketmgr_create");
1428
1429 result = dst_lib_init(mctx, NULL);
1430 check_result(result, "dst_lib_init");
1431 is_dst_up = true;
1432
1433 isc_mutex_init(&lookup_lock);
1434 }
1435
1436 typedef struct dig_ednsoptname {
1437 uint32_t code;
1438 const char *name;
1439 } dig_ednsoptname_t;
1440
1441 dig_ednsoptname_t optnames[] = {
1442 { 1, "LLQ" }, /* draft-sekar-dns-llq */
1443 { 3, "NSID" }, /* RFC 5001 */
1444 { 5, "DAU" }, /* RFC 6975 */
1445 { 6, "DHU" }, /* RFC 6975 */
1446 { 7, "N3U" }, /* RFC 6975 */
1447 { 8, "ECS" }, /* RFC 7871 */
1448 { 9, "EXPIRE" }, /* RFC 7314 */
1449 { 10, "COOKIE" }, /* RFC 7873 */
1450 { 11, "KEEPALIVE" }, /* RFC 7828 */
1451 { 12, "PADDING" }, /* RFC 7830 */
1452 { 12, "PAD" }, /* shorthand */
1453 { 13, "CHAIN" }, /* RFC 7901 */
1454 { 14, "KEY-TAG" }, /* RFC 8145 */
1455 { 15, "EDE" }, /* ietf-dnsop-extended-error-16 */
1456 { 16, "CLIENT-TAG" }, /* draft-bellis-dnsop-edns-tags */
1457 { 17, "SERVER-TAG" }, /* draft-bellis-dnsop-edns-tags */
1458 { 26946, "DEVICEID" }, /* Brian Hartvigsen */
1459 };
1460
1461 #define N_EDNS_OPTNAMES (sizeof(optnames) / sizeof(optnames[0]))
1462
1463 void
1464 save_opt(dig_lookup_t *lookup, char *code, char *value) {
1465 isc_result_t result;
1466 uint32_t num = 0;
1467 isc_buffer_t b;
1468 bool found = false;
1469 unsigned int i;
1470
1471 if (lookup->ednsoptscnt >= EDNSOPT_OPTIONS) {
1472 fatal("too many ednsopts");
1473 }
1474
1475 for (i = 0; i < N_EDNS_OPTNAMES; i++) {
1476 if (strcasecmp(code, optnames[i].name) == 0) {
1477 num = optnames[i].code;
1478 found = true;
1479 break;
1480 }
1481 }
1482
1483 if (!found) {
1484 result = parse_uint(&num, code, 65535, "ednsopt");
1485 if (result != ISC_R_SUCCESS) {
1486 fatal("bad edns code point: %s", code);
1487 }
1488 }
1489
1490 if (lookup->ednsopts == NULL) {
1491 cloneopts(lookup, NULL);
1492 }
1493
1494 if (lookup->ednsopts[lookup->ednsoptscnt].value != NULL) {
1495 isc_mem_free(mctx, lookup->ednsopts[lookup->ednsoptscnt].value);
1496 }
1497
1498 lookup->ednsopts[lookup->ednsoptscnt].code = num;
1499 lookup->ednsopts[lookup->ednsoptscnt].length = 0;
1500 lookup->ednsopts[lookup->ednsoptscnt].value = NULL;
1501
1502 if (value != NULL) {
1503 char *buf;
1504 buf = isc_mem_allocate(mctx, strlen(value) / 2 + 1);
1505 isc_buffer_init(&b, buf, (unsigned int)strlen(value) / 2 + 1);
1506 result = isc_hex_decodestring(value, &b);
1507 check_result(result, "isc_hex_decodestring");
1508 lookup->ednsopts[lookup->ednsoptscnt].value =
1509 isc_buffer_base(&b);
1510 lookup->ednsopts[lookup->ednsoptscnt].length =
1511 isc_buffer_usedlength(&b);
1512 }
1513
1514 lookup->ednsoptscnt++;
1515 }
1516
1517 /*%
1518 * Add EDNS0 option record to a message. Currently, the only supported
1519 * options are UDP buffer size, the DO bit, and EDNS options
1520 * (e.g., NSID, COOKIE, client-subnet)
1521 */
1522 static void
1523 add_opt(dns_message_t *msg, uint16_t udpsize, uint16_t edns, unsigned int flags,
1524 dns_ednsopt_t *opts, size_t count) {
1525 dns_rdataset_t *rdataset = NULL;
1526 isc_result_t result;
1527
1528 debug("add_opt()");
1529 result = dns_message_buildopt(msg, &rdataset, edns, udpsize, flags,
1530 opts, count);
1531 check_result(result, "dns_message_buildopt");
1532 result = dns_message_setopt(msg, rdataset);
1533 check_result(result, "dns_message_setopt");
1534 }
1535
1536 /*%
1537 * Add a question section to a message, asking for the specified name,
1538 * type, and class.
1539 */
1540 static void
1541 add_question(dns_message_t *message, dns_name_t *name, dns_rdataclass_t rdclass,
1542 dns_rdatatype_t rdtype) {
1543 dns_rdataset_t *rdataset;
1544 isc_result_t result;
1545
1546 debug("add_question()");
1547 rdataset = NULL;
1548 result = dns_message_gettemprdataset(message, &rdataset);
1549 check_result(result, "dns_message_gettemprdataset()");
1550 dns_rdataset_makequestion(rdataset, rdclass, rdtype);
1551 ISC_LIST_APPEND(name->list, rdataset, link);
1552 }
1553
1554 /*%
1555 * Check if we're done with all the queued lookups, which is true iff
1556 * all sockets, sends, and recvs are accounted for (counters == 0),
1557 * and the lookup list is empty.
1558 * If we are done, pass control back out to dighost_shutdown() (which is
1559 * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
1560 * a whole or reseed the lookup list.
1561 */
1562 static void
1563 check_if_done(void) {
1564 debug("check_if_done()");
1565 debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
1566 if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
1567 sendcount == 0)
1568 {
1569 INSIST(sockcount == 0);
1570 INSIST(recvcount == 0);
1571 debug("shutting down");
1572 dighost_shutdown();
1573 }
1574 }
1575
1576 /*%
1577 * Clear out a query when we're done with it. WARNING: This routine
1578 * WILL invalidate the query pointer.
1579 */
1580 static void
1581 clear_query(dig_query_t *query) {
1582 dig_lookup_t *lookup;
1583
1584 REQUIRE(query != NULL);
1585
1586 debug("clear_query(%p)", query);
1587
1588 if (query->timer != NULL) {
1589 isc_timer_destroy(&query->timer);
1590 }
1591 lookup = query->lookup;
1592
1593 if (lookup->current_query == query) {
1594 lookup->current_query = NULL;
1595 }
1596
1597 if (ISC_LINK_LINKED(query, link)) {
1598 query->saved_next = ISC_LIST_NEXT(query, link);
1599 ISC_LIST_UNLINK(lookup->q, query, link);
1600 }
1601 if (ISC_LINK_LINKED(query, clink)) {
1602 ISC_LIST_UNLINK(lookup->connecting, query, clink);
1603 }
1604 INSIST(query->recvspace != NULL);
1605
1606 if (query->sock != NULL) {
1607 isc_socket_detach(&query->sock);
1608 sockcount--;
1609 debug("sockcount=%d", sockcount);
1610 }
1611 isc_mem_put(mctx, query->recvspace, COMMSIZE);
1612 isc_mem_put(mctx, query->tmpsendspace, COMMSIZE);
1613 isc_buffer_invalidate(&query->recvbuf);
1614 isc_buffer_invalidate(&query->lengthbuf);
1615
1616 if (query->waiting_senddone) {
1617 debug("waiting senddone, delay freeing query");
1618 query->pending_free = true;
1619 } else {
1620 query->magic = 0;
1621 isc_mem_free(mctx, query);
1622 }
1623 }
1624
1625 /*%
1626 * Try and clear out a lookup if we're done with it. Return true if
1627 * the lookup was successfully cleared. If true is returned, the
1628 * lookup pointer has been invalidated.
1629 */
1630 static bool
1631 try_clear_lookup(dig_lookup_t *lookup) {
1632 dig_query_t *q;
1633
1634 REQUIRE(lookup != NULL);
1635
1636 debug("try_clear_lookup(%p)", lookup);
1637
1638 if (ISC_LIST_HEAD(lookup->q) != NULL ||
1639 ISC_LIST_HEAD(lookup->connecting) != NULL)
1640 {
1641 if (debugging) {
1642 q = ISC_LIST_HEAD(lookup->q);
1643 while (q != NULL) {
1644 debug("query to %s still pending", q->servname);
1645 q = ISC_LIST_NEXT(q, link);
1646 }
1647
1648 q = ISC_LIST_HEAD(lookup->connecting);
1649 while (q != NULL) {
1650 debug("query to %s still connecting",
1651 q->servname);
1652 q = ISC_LIST_NEXT(q, clink);
1653 }
1654 }
1655 return (false);
1656 }
1657
1658 /*
1659 * At this point, we know there are no queries on the lookup,
1660 * so can make it go away also.
1661 */
1662 destroy_lookup(lookup);
1663 return (true);
1664 }
1665
1666 void
1667 destroy_lookup(dig_lookup_t *lookup) {
1668 dig_server_t *s;
1669 void *ptr;
1670
1671 debug("destroy");
1672 s = ISC_LIST_HEAD(lookup->my_server_list);
1673 while (s != NULL) {
1674 debug("freeing server %p belonging to %p", s, lookup);
1675 ptr = s;
1676 s = ISC_LIST_NEXT(s, link);
1677 ISC_LIST_DEQUEUE(lookup->my_server_list, (dig_server_t *)ptr,
1678 link);
1679 isc_mem_free(mctx, ptr);
1680 }
1681 if (lookup->sendmsg != NULL) {
1682 dns_message_detach(&lookup->sendmsg);
1683 }
1684 if (lookup->querysig != NULL) {
1685 debug("freeing buffer %p", lookup->querysig);
1686 isc_buffer_free(&lookup->querysig);
1687 }
1688 if (lookup->sendspace != NULL) {
1689 isc_mem_put(mctx, lookup->sendspace, COMMSIZE);
1690 }
1691
1692 if (lookup->tsigctx != NULL) {
1693 dst_context_destroy(&lookup->tsigctx);
1694 }
1695
1696 if (lookup->ecs_addr != NULL) {
1697 isc_mem_free(mctx, lookup->ecs_addr);
1698 }
1699
1700 if (lookup->ednsopts != NULL) {
1701 size_t i;
1702 for (i = 0; i < EDNSOPT_OPTIONS; i++) {
1703 if (lookup->ednsopts[i].value != NULL) {
1704 isc_mem_free(mctx, lookup->ednsopts[i].value);
1705 }
1706 }
1707 isc_mem_free(mctx, lookup->ednsopts);
1708 }
1709
1710 isc_mem_free(mctx, lookup);
1711 }
1712
1713 /*%
1714 * If we can, start the next lookup in the queue running.
1715 * This assumes that the lookup on the head of the queue hasn't been
1716 * started yet. It also removes the lookup from the head of the queue,
1717 * setting the current_lookup pointer pointing to it.
1718 */
1719 void
1720 start_lookup(void) {
1721 debug("start_lookup()");
1722 if (cancel_now) {
1723 return;
1724 }
1725
1726 /*
1727 * If there's a current lookup running, we really shouldn't get
1728 * here.
1729 */
1730 INSIST(current_lookup == NULL);
1731
1732 current_lookup = ISC_LIST_HEAD(lookup_list);
1733 /*
1734 * Put the current lookup somewhere so cancel_all can find it
1735 */
1736 if (current_lookup != NULL) {
1737 ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
1738 if (setup_lookup(current_lookup)) {
1739 do_lookup(current_lookup);
1740 } else if (next_origin(current_lookup)) {
1741 check_next_lookup(current_lookup);
1742 }
1743 } else {
1744 check_if_done();
1745 }
1746 }
1747
1748 /*%
1749 * If we can, clear the current lookup and start the next one running.
1750 * This calls try_clear_lookup, so may invalidate the lookup pointer.
1751 */
1752 static void
1753 check_next_lookup(dig_lookup_t *lookup) {
1754 INSIST(!free_now);
1755
1756 debug("check_next_lookup(%p)", lookup);
1757
1758 if (ISC_LIST_HEAD(lookup->q) != NULL) {
1759 debug("still have a worker");
1760 return;
1761 }
1762 if (try_clear_lookup(lookup)) {
1763 current_lookup = NULL;
1764 start_lookup();
1765 }
1766 }
1767
1768 /*%
1769 * Create and queue a new lookup as a followup to the current lookup,
1770 * based on the supplied message and section. This is used in trace and
1771 * name server search modes to start a new lookup using servers from
1772 * NS records in a reply. Returns the number of followup lookups made.
1773 */
1774 static int
1775 followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section) {
1776 dig_lookup_t *lookup = NULL;
1777 dig_server_t *srv = NULL;
1778 dns_rdataset_t *rdataset = NULL;
1779 dns_rdata_t rdata = DNS_RDATA_INIT;
1780 dns_name_t *name = NULL;
1781 isc_result_t result;
1782 bool success = false;
1783 int numLookups = 0;
1784 int num;
1785 isc_result_t lresult, addresses_result;
1786 char bad_namestr[DNS_NAME_FORMATSIZE];
1787 dns_name_t *domain;
1788 bool horizontal = false, bad = false;
1789
1790 INSIST(!free_now);
1791
1792 debug("following up %s", query->lookup->textname);
1793
1794 addresses_result = ISC_R_SUCCESS;
1795 bad_namestr[0] = '\0';
1796 for (result = dns_message_firstname(msg, section);
1797 result == ISC_R_SUCCESS;
1798 result = dns_message_nextname(msg, section))
1799 {
1800 name = NULL;
1801 dns_message_currentname(msg, section, &name);
1802
1803 if (section == DNS_SECTION_AUTHORITY) {
1804 rdataset = NULL;
1805 result = dns_message_findtype(name, dns_rdatatype_soa,
1806 0, &rdataset);
1807 if (result == ISC_R_SUCCESS) {
1808 return (0);
1809 }
1810 }
1811 rdataset = NULL;
1812 result = dns_message_findtype(name, dns_rdatatype_ns, 0,
1813 &rdataset);
1814 if (result != ISC_R_SUCCESS) {
1815 continue;
1816 }
1817
1818 debug("found NS set");
1819
1820 if (query->lookup->trace && !query->lookup->trace_root) {
1821 dns_namereln_t namereln;
1822 unsigned int nlabels;
1823 int order;
1824
1825 domain = dns_fixedname_name(&query->lookup->fdomain);
1826 namereln = dns_name_fullcompare(name, domain, &order,
1827 &nlabels);
1828 if (namereln == dns_namereln_equal) {
1829 if (!horizontal) {
1830 dighost_warning("BAD (HORIZONTAL) "
1831 "REFERRAL");
1832 }
1833 horizontal = true;
1834 } else if (namereln != dns_namereln_subdomain) {
1835 if (!bad) {
1836 dighost_warning("BAD REFERRAL");
1837 }
1838 bad = true;
1839 continue;
1840 }
1841 }
1842
1843 for (result = dns_rdataset_first(rdataset);
1844 result == ISC_R_SUCCESS;
1845 result = dns_rdataset_next(rdataset))
1846 {
1847 char namestr[DNS_NAME_FORMATSIZE];
1848 dns_rdata_ns_t ns;
1849
1850 if (query->lookup->trace_root &&
1851 query->lookup->nsfound >= MXSERV)
1852 {
1853 break;
1854 }
1855
1856 dns_rdataset_current(rdataset, &rdata);
1857
1858 query->lookup->nsfound++;
1859 result = dns_rdata_tostruct(&rdata, &ns, NULL);
1860 check_result(result, "dns_rdata_tostruct");
1861 dns_name_format(&ns.name, namestr, sizeof(namestr));
1862 dns_rdata_freestruct(&ns);
1863
1864 /* Initialize lookup if we've not yet */
1865 debug("found NS %s", namestr);
1866 if (!success) {
1867 success = true;
1868 lookup_counter++;
1869 lookup = requeue_lookup(query->lookup, false);
1870 cancel_lookup(query->lookup);
1871 lookup->doing_xfr = false;
1872 if (!lookup->trace_root &&
1873 section == DNS_SECTION_ANSWER)
1874 {
1875 lookup->trace = false;
1876 } else {
1877 lookup->trace = query->lookup->trace;
1878 }
1879 lookup->ns_search_only =
1880 query->lookup->ns_search_only;
1881 lookup->trace_root = false;
1882 if (lookup->ns_search_only) {
1883 lookup->recurse = false;
1884 }
1885 domain = dns_fixedname_name(&lookup->fdomain);
1886 dns_name_copynf(name, domain);
1887 }
1888 debug("adding server %s", namestr);
1889 num = getaddresses(lookup, namestr, &lresult);
1890 if (lresult != ISC_R_SUCCESS) {
1891 printf("couldn't get address for '%s': %s\n",
1892 namestr, isc_result_totext(lresult));
1893 if (addresses_result == ISC_R_SUCCESS) {
1894 addresses_result = lresult;
1895 strlcpy(bad_namestr, namestr,
1896 sizeof(bad_namestr));
1897 }
1898 }
1899 numLookups += num;
1900 dns_rdata_reset(&rdata);
1901 }
1902 }
1903 if (numLookups == 0 && addresses_result != ISC_R_SUCCESS) {
1904 fatal("couldn't get address for '%s': %s", bad_namestr,
1905 isc_result_totext(result));
1906 }
1907
1908 if (lookup == NULL && section == DNS_SECTION_ANSWER &&
1909 (query->lookup->trace || query->lookup->ns_search_only))
1910 {
1911 return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY));
1912 }
1913
1914 /*
1915 * Randomize the order the nameserver will be tried.
1916 */
1917 if (numLookups > 1) {
1918 uint32_t i, j;
1919 dig_serverlist_t my_server_list;
1920 dig_server_t *next;
1921
1922 ISC_LIST_INIT(my_server_list);
1923
1924 i = numLookups;
1925 for (srv = ISC_LIST_HEAD(lookup->my_server_list); srv != NULL;
1926 srv = ISC_LIST_HEAD(lookup->my_server_list))
1927 {
1928 INSIST(i > 0);
1929 j = isc_random_uniform(i);
1930 next = ISC_LIST_NEXT(srv, link);
1931 while (j-- > 0 && next != NULL) {
1932 srv = next;
1933 next = ISC_LIST_NEXT(srv, link);
1934 }
1935 ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link);
1936 ISC_LIST_APPEND(my_server_list, srv, link);
1937 i--;
1938 }
1939 ISC_LIST_APPENDLIST(lookup->my_server_list, my_server_list,
1940 link);
1941 }
1942
1943 return (numLookups);
1944 }
1945
1946 /*%
1947 * Create and queue a new lookup using the next origin from the search
1948 * list, read in setup_system().
1949 *
1950 * Return true iff there was another searchlist entry.
1951 */
1952 static bool
1953 next_origin(dig_lookup_t *oldlookup) {
1954 dig_lookup_t *newlookup;
1955 dig_searchlist_t *search;
1956 dns_fixedname_t fixed;
1957 dns_name_t *name;
1958 isc_result_t result;
1959
1960 INSIST(!free_now);
1961
1962 debug("next_origin(%p)", oldlookup);
1963 debug("following up %s", oldlookup->textname);
1964
1965 if (!usesearch) {
1966 /*
1967 * We're not using a search list, so don't even think
1968 * about finding the next entry.
1969 */
1970 return (false);
1971 }
1972
1973 /*
1974 * Check for a absolute name or ndots being met.
1975 */
1976 name = dns_fixedname_initname(&fixed);
1977 result = dns_name_fromstring2(name, oldlookup->textname, NULL, 0, NULL);
1978 if (result == ISC_R_SUCCESS &&
1979 (dns_name_isabsolute(name) ||
1980 (int)dns_name_countlabels(name) > ndots))
1981 {
1982 return (false);
1983 }
1984
1985 if (oldlookup->origin == NULL && !oldlookup->need_search) {
1986 /*
1987 * Then we just did rootorg; there's nothing left.
1988 */
1989 return (false);
1990 }
1991 if (oldlookup->origin == NULL && oldlookup->need_search) {
1992 newlookup = requeue_lookup(oldlookup, true);
1993 newlookup->origin = ISC_LIST_HEAD(search_list);
1994 newlookup->need_search = false;
1995 } else {
1996 search = ISC_LIST_NEXT(oldlookup->origin, link);
1997 if (search == NULL && oldlookup->done_as_is) {
1998 return (false);
1999 }
2000 newlookup = requeue_lookup(oldlookup, true);
2001 newlookup->origin = search;
2002 }
2003 cancel_lookup(oldlookup);
2004 return (true);
2005 }
2006
2007 /*%
2008 * Insert an SOA record into the sendmessage in a lookup. Used for
2009 * creating IXFR queries.
2010 */
2011 static void
2012 insert_soa(dig_lookup_t *lookup) {
2013 isc_result_t result;
2014 dns_rdata_soa_t soa;
2015 dns_rdata_t *rdata = NULL;
2016 dns_rdatalist_t *rdatalist = NULL;
2017 dns_rdataset_t *rdataset = NULL;
2018 dns_name_t *soaname = NULL;
2019
2020 debug("insert_soa(%p)", lookup);
2021 soa.mctx = mctx;
2022 soa.serial = lookup->ixfr_serial;
2023 soa.refresh = 0;
2024 soa.retry = 0;
2025 soa.expire = 0;
2026 soa.minimum = 0;
2027 soa.common.rdclass = lookup->rdclass;
2028 soa.common.rdtype = dns_rdatatype_soa;
2029
2030 dns_name_init(&soa.origin, NULL);
2031 dns_name_init(&soa.contact, NULL);
2032
2033 dns_name_clone(dns_rootname, &soa.origin);
2034 dns_name_clone(dns_rootname, &soa.contact);
2035
2036 isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
2037 sizeof(lookup->rdatastore));
2038
2039 result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
2040 check_result(result, "dns_message_gettemprdata");
2041
2042 result = dns_rdata_fromstruct(rdata, lookup->rdclass, dns_rdatatype_soa,
2043 &soa, &lookup->rdatabuf);
2044 check_result(result, "isc_rdata_fromstruct");
2045
2046 result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
2047 check_result(result, "dns_message_gettemprdatalist");
2048
2049 result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
2050 check_result(result, "dns_message_gettemprdataset");
2051
2052 dns_rdatalist_init(rdatalist);
2053 rdatalist->type = dns_rdatatype_soa;
2054 rdatalist->rdclass = lookup->rdclass;
2055 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
2056
2057 dns_rdatalist_tordataset(rdatalist, rdataset);
2058
2059 result = dns_message_gettempname(lookup->sendmsg, &soaname);
2060 check_result(result, "dns_message_gettempname");
2061 dns_name_clone(lookup->name, soaname);
2062 ISC_LIST_INIT(soaname->list);
2063 ISC_LIST_APPEND(soaname->list, rdataset, link);
2064 dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
2065 }
2066
2067 static void
2068 compute_cookie(unsigned char *clientcookie, size_t len) {
2069 /* XXXMPA need to fix, should be per server. */
2070 INSIST(len >= 8U);
2071 memmove(clientcookie, cookie_secret, 8);
2072 }
2073
2074 /*%
2075 * Setup the supplied lookup structure, making it ready to start sending
2076 * queries to servers. Create and initialize the message to be sent as
2077 * well as the query structures and buffer space for the replies. If the
2078 * server list is empty, clone it from the system default list.
2079 */
2080 bool
2081 setup_lookup(dig_lookup_t *lookup) {
2082 isc_result_t result;
2083 unsigned int len;
2084 dig_server_t *serv;
2085 dig_query_t *query;
2086 isc_buffer_t b;
2087 dns_compress_t cctx;
2088 char store[MXNAME];
2089 char ecsbuf[20];
2090 char cookiebuf[256];
2091 char *origin = NULL;
2092 char *textname = NULL;
2093
2094 REQUIRE(lookup != NULL);
2095
2096 #ifdef HAVE_LIBIDN2
2097 char idn_origin[MXNAME], idn_textname[MXNAME];
2098
2099 result = dns_name_settotextfilter(lookup->idnout ? idn_output_filter
2100 : NULL);
2101 check_result(result, "dns_name_settotextfilter");
2102 #endif /* HAVE_LIBIDN2 */
2103
2104 INSIST(!free_now);
2105
2106 debug("setup_lookup(%p)", lookup);
2107
2108 dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &lookup->sendmsg);
2109
2110 if (lookup->new_search) {
2111 debug("resetting lookup counter.");
2112 lookup_counter = 0;
2113 }
2114
2115 if (ISC_LIST_EMPTY(lookup->my_server_list)) {
2116 debug("cloning server list");
2117 clone_server_list(server_list, &lookup->my_server_list);
2118 }
2119 result = dns_message_gettempname(lookup->sendmsg, &lookup->name);
2120 check_result(result, "dns_message_gettempname");
2121
2122 isc_buffer_init(&lookup->namebuf, lookup->name_space,
2123 sizeof(lookup->name_space));
2124 isc_buffer_init(&lookup->onamebuf, lookup->oname_space,
2125 sizeof(lookup->oname_space));
2126
2127 /*
2128 * We cannot convert `textname' and `origin' separately.
2129 * `textname' doesn't contain TLD, but local mapping needs
2130 * TLD.
2131 */
2132 textname = lookup->textname;
2133 #ifdef HAVE_LIBIDN2
2134 if (lookup->idnin) {
2135 idn_locale_to_ace(textname, idn_textname, sizeof(idn_textname));
2136 debug("idn_textname: %s", idn_textname);
2137 textname = idn_textname;
2138 }
2139 #endif /* HAVE_LIBIDN2 */
2140
2141 /*
2142 * If the name has too many dots, force the origin to be NULL
2143 * (which produces an absolute lookup). Otherwise, take the origin
2144 * we have if there's one in the struct already. If it's NULL,
2145 * take the first entry in the searchlist iff either usesearch
2146 * is TRUE or we got a domain line in the resolv.conf file.
2147 */
2148 if (lookup->new_search) {
2149 if ((count_dots(textname) >= ndots) || !usesearch) {
2150 lookup->origin = NULL; /* Force abs lookup */
2151 lookup->done_as_is = true;
2152 lookup->need_search = usesearch;
2153 } else if (lookup->origin == NULL && usesearch) {
2154 lookup->origin = ISC_LIST_HEAD(search_list);
2155 lookup->need_search = false;
2156 }
2157 }
2158
2159 if (lookup->origin != NULL) {
2160 debug("trying origin %s", lookup->origin->origin);
2161 result = dns_message_gettempname(lookup->sendmsg,
2162 &lookup->oname);
2163 check_result(result, "dns_message_gettempname");
2164 /* XXX Helper funct to conv char* to name? */
2165 origin = lookup->origin->origin;
2166 #ifdef HAVE_LIBIDN2
2167 if (lookup->idnin) {
2168 idn_locale_to_ace(origin, idn_origin,
2169 sizeof(idn_origin));
2170 debug("trying idn origin %s", idn_origin);
2171 origin = idn_origin;
2172 }
2173 #endif /* HAVE_LIBIDN2 */
2174 len = (unsigned int)strlen(origin);
2175 isc_buffer_init(&b, origin, len);
2176 isc_buffer_add(&b, len);
2177 result = dns_name_fromtext(lookup->oname, &b, dns_rootname, 0,
2178 &lookup->onamebuf);
2179 if (result != ISC_R_SUCCESS) {
2180 dns_message_puttempname(lookup->sendmsg, &lookup->name);
2181 dns_message_puttempname(lookup->sendmsg,
2182 &lookup->oname);
2183 fatal("'%s' is not in legal name syntax (%s)", origin,
2184 isc_result_totext(result));
2185 }
2186 if (lookup->trace && lookup->trace_root) {
2187 dns_name_clone(dns_rootname, lookup->name);
2188 } else {
2189 dns_fixedname_t fixed;
2190 dns_name_t *name;
2191
2192 name = dns_fixedname_initname(&fixed);
2193 len = (unsigned int)strlen(textname);
2194 isc_buffer_init(&b, textname, len);
2195 isc_buffer_add(&b, len);
2196 result = dns_name_fromtext(name, &b, NULL, 0, NULL);
2197 if (result == ISC_R_SUCCESS) {
2198 if (!dns_name_isabsolute(name)) {
2199 result = dns_name_concatenate(
2200 name, lookup->oname,
2201 lookup->name, &lookup->namebuf);
2202 } else {
2203 result = dns_name_copy(
2204 name, lookup->name,
2205 &lookup->namebuf);
2206 }
2207 }
2208 if (result != ISC_R_SUCCESS) {
2209 dns_message_puttempname(lookup->sendmsg,
2210 &lookup->name);
2211 dns_message_puttempname(lookup->sendmsg,
2212 &lookup->oname);
2213 if (result == DNS_R_NAMETOOLONG) {
2214 return (false);
2215 }
2216 fatal("'%s' is not in legal name syntax (%s)",
2217 lookup->textname,
2218 isc_result_totext(result));
2219 }
2220 }
2221 dns_message_puttempname(lookup->sendmsg, &lookup->oname);
2222 } else {
2223 debug("using root origin");
2224 if (lookup->trace && lookup->trace_root) {
2225 dns_name_clone(dns_rootname, lookup->name);
2226 } else {
2227 len = (unsigned int)strlen(textname);
2228 isc_buffer_init(&b, textname, len);
2229 isc_buffer_add(&b, len);
2230 result = dns_name_fromtext(lookup->name, &b,
2231 dns_rootname, 0,
2232 &lookup->namebuf);
2233 }
2234 if (result != ISC_R_SUCCESS) {
2235 dns_message_puttempname(lookup->sendmsg, &lookup->name);
2236 warn("'%s' is not a legal name "
2237 "(%s)",
2238 lookup->textname, isc_result_totext(result));
2239 #if TARGET_OS_IPHONE
2240 check_next_lookup(current_lookup);
2241 return (false);
2242 #else /* if TARGET_OS_IPHONE */
2243 digexit();
2244 #endif /* if TARGET_OS_IPHONE */
2245 }
2246 }
2247 dns_name_format(lookup->name, store, sizeof(store));
2248 dighost_trying(store, lookup);
2249 INSIST(dns_name_isabsolute(lookup->name));
2250
2251 lookup->sendmsg->id = (dns_messageid_t)isc_random16();
2252 lookup->sendmsg->opcode = lookup->opcode;
2253 lookup->msgcounter = 0;
2254
2255 /*
2256 * If this is a trace request, completely disallow recursion after
2257 * looking up the root name servers, since it's meaningless for traces.
2258 */
2259 if ((lookup->trace || lookup->ns_search_only) && !lookup->trace_root) {
2260 lookup->recurse = false;
2261 }
2262
2263 if (lookup->recurse && lookup->rdtype != dns_rdatatype_axfr &&
2264 lookup->rdtype != dns_rdatatype_ixfr)
2265 {
2266 debug("recursive query");
2267 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD;
2268 }
2269
2270 /* XXX aaflag */
2271 if (lookup->aaonly) {
2272 debug("AA query");
2273 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA;
2274 }
2275
2276 if (lookup->adflag) {
2277 debug("AD query");
2278 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD;
2279 }
2280
2281 if (lookup->cdflag) {
2282 debug("CD query");
2283 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD;
2284 }
2285
2286 if (lookup->raflag) {
2287 debug("RA query");
2288 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RA;
2289 }
2290
2291 if (lookup->tcflag) {
2292 debug("TC query");
2293 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_TC;
2294 }
2295
2296 if (lookup->zflag) {
2297 debug("Z query");
2298 lookup->sendmsg->flags |= 0x0040U;
2299 }
2300
2301 dns_message_addname(lookup->sendmsg, lookup->name,
2302 DNS_SECTION_QUESTION);
2303
2304 if (lookup->trace && lookup->trace_root) {
2305 lookup->qrdtype = lookup->rdtype;
2306 lookup->rdtype = dns_rdatatype_ns;
2307 }
2308
2309 if ((lookup->rdtype == dns_rdatatype_axfr) ||
2310 (lookup->rdtype == dns_rdatatype_ixfr))
2311 {
2312 /*
2313 * Force TCP mode if we're doing an axfr.
2314 */
2315 if (lookup->rdtype == dns_rdatatype_axfr) {
2316 lookup->doing_xfr = true;
2317 lookup->tcp_mode = true;
2318 } else if (lookup->tcp_mode) {
2319 lookup->doing_xfr = true;
2320 }
2321 }
2322
2323 if (!lookup->header_only) {
2324 add_question(lookup->sendmsg, lookup->name, lookup->rdclass,
2325 lookup->rdtype);
2326 }
2327
2328 /* add_soa */
2329 if (lookup->rdtype == dns_rdatatype_ixfr) {
2330 insert_soa(lookup);
2331 }
2332
2333 /* XXX Insist this? */
2334 lookup->tsigctx = NULL;
2335 lookup->querysig = NULL;
2336 if (tsigkey != NULL) {
2337 debug("initializing keys");
2338 result = dns_message_settsigkey(lookup->sendmsg, tsigkey);
2339 check_result(result, "dns_message_settsigkey");
2340 }
2341
2342 lookup->sendspace = isc_mem_get(mctx, COMMSIZE);
2343
2344 result = dns_compress_init(&cctx, -1, mctx);
2345 check_result(result, "dns_compress_init");
2346
2347 debug("starting to render the message");
2348 isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE);
2349 result = dns_message_renderbegin(lookup->sendmsg, &cctx,
2350 &lookup->renderbuf);
2351 check_result(result, "dns_message_renderbegin");
2352 if (lookup->udpsize > 0 || lookup->dnssec || lookup->edns > -1 ||
2353 lookup->ecs_addr != NULL)
2354 {
2355 #define MAXOPTS (EDNSOPT_OPTIONS + DNS_EDNSOPTIONS)
2356 dns_ednsopt_t opts[MAXOPTS];
2357 unsigned int flags;
2358 unsigned int i = 0;
2359
2360 /*
2361 * There can't be more than MAXOPTS options to send:
2362 * a maximum of EDNSOPT_OPTIONS set by +ednsopt
2363 * and DNS_EDNSOPTIONS set by other arguments
2364 * (+nsid, +cookie, etc).
2365 */
2366 if (lookup->udpsize < 0) {
2367 lookup->udpsize = DEFAULT_EDNS_BUFSIZE;
2368 }
2369 if (lookup->edns < 0) {
2370 lookup->edns = DEFAULT_EDNS_VERSION;
2371 }
2372
2373 if (lookup->nsid) {
2374 INSIST(i < MAXOPTS);
2375 opts[i].code = DNS_OPT_NSID;
2376 opts[i].length = 0;
2377 opts[i].value = NULL;
2378 i++;
2379 }
2380
2381 if (lookup->ecs_addr != NULL) {
2382 uint8_t addr[16];
2383 uint16_t family = 0;
2384 uint32_t plen;
2385 struct sockaddr *sa;
2386 struct sockaddr_in *sin;
2387 struct sockaddr_in6 *sin6;
2388 size_t addrl;
2389
2390 sa = &lookup->ecs_addr->type.sa;
2391 plen = lookup->ecs_addr->length;
2392
2393 /* Round up prefix len to a multiple of 8 */
2394 addrl = (plen + 7) / 8;
2395
2396 INSIST(i < MAXOPTS);
2397 opts[i].code = DNS_OPT_CLIENT_SUBNET;
2398 opts[i].length = (uint16_t)addrl + 4;
2399 check_result(result, "isc_buffer_allocate");
2400
2401 /*
2402 * XXXMUKS: According to RFC7871, "If there is
2403 * no ADDRESS set, i.e., SOURCE PREFIX-LENGTH is
2404 * set to 0, then FAMILY SHOULD be set to the
2405 * transport over which the query is sent."
2406 *
2407 * However, at this point we don't know what
2408 * transport(s) we'll be using, so we can't
2409 * set the value now. For now, we're using
2410 * IPv4 as the default the +subnet option
2411 * used an IPv4 prefix, or for +subnet=0,
2412 * and IPv6 if the +subnet option used an
2413 * IPv6 prefix.
2414 *
2415 * (For future work: preserve the offset into
2416 * the buffer where the family field is;
2417 * that way we can update it in send_udp()
2418 * or send_tcp_connect() once we know
2419 * what it outght to be.)
2420 */
2421 switch (sa->sa_family) {
2422 case AF_UNSPEC:
2423 INSIST(plen == 0);
2424 family = 1;
2425 break;
2426 case AF_INET:
2427 INSIST(plen <= 32);
2428 family = 1;
2429 sin = (struct sockaddr_in *)sa;
2430 memmove(addr, &sin->sin_addr, addrl);
2431 break;
2432 case AF_INET6:
2433 INSIST(plen <= 128);
2434 family = 2;
2435 sin6 = (struct sockaddr_in6 *)sa;
2436 memmove(addr, &sin6->sin6_addr, addrl);
2437 break;
2438 default:
2439 UNREACHABLE();
2440 }
2441
2442 isc_buffer_init(&b, ecsbuf, sizeof(ecsbuf));
2443 /* family */
2444 isc_buffer_putuint16(&b, family);
2445 /* source prefix-length */
2446 isc_buffer_putuint8(&b, plen);
2447 /* scope prefix-length */
2448 isc_buffer_putuint8(&b, 0);
2449
2450 /* address */
2451 if (addrl > 0) {
2452 /* Mask off last address byte */
2453 if ((plen % 8) != 0) {
2454 addr[addrl - 1] &= ~0U
2455 << (8 - (plen % 8));
2456 }
2457 isc_buffer_putmem(&b, addr, (unsigned)addrl);
2458 }
2459
2460 opts[i].value = (uint8_t *)ecsbuf;
2461 i++;
2462 }
2463
2464 if (lookup->sendcookie) {
2465 INSIST(i < MAXOPTS);
2466 opts[i].code = DNS_OPT_COOKIE;
2467 if (lookup->cookie != NULL) {
2468 isc_buffer_init(&b, cookiebuf,
2469 sizeof(cookiebuf));
2470 result = isc_hex_decodestring(lookup->cookie,
2471 &b);
2472 check_result(result, "isc_hex_decodestring");
2473 opts[i].value = isc_buffer_base(&b);
2474 opts[i].length = isc_buffer_usedlength(&b);
2475 } else {
2476 compute_cookie(cookie, sizeof(cookie));
2477 opts[i].length = 8;
2478 opts[i].value = cookie;
2479 }
2480 i++;
2481 }
2482
2483 if (lookup->expire) {
2484 INSIST(i < MAXOPTS);
2485 opts[i].code = DNS_OPT_EXPIRE;
2486 opts[i].length = 0;
2487 opts[i].value = NULL;
2488 i++;
2489 }
2490
2491 if (lookup->tcp_keepalive) {
2492 INSIST(i < MAXOPTS);
2493 opts[i].code = DNS_OPT_TCP_KEEPALIVE;
2494 opts[i].length = 0;
2495 opts[i].value = NULL;
2496 i++;
2497 }
2498
2499 if (lookup->ednsoptscnt != 0) {
2500 INSIST(i + lookup->ednsoptscnt <= MAXOPTS);
2501 memmove(&opts[i], lookup->ednsopts,
2502 sizeof(dns_ednsopt_t) * lookup->ednsoptscnt);
2503 i += lookup->ednsoptscnt;
2504 }
2505
2506 if (lookup->padding != 0 && (i >= MAXOPTS)) {
2507 debug("turned off padding because of EDNS overflow");
2508 lookup->padding = 0;
2509 }
2510
2511 if (lookup->padding != 0) {
2512 INSIST(i < MAXOPTS);
2513 opts[i].code = DNS_OPT_PAD;
2514 opts[i].length = 0;
2515 opts[i].value = NULL;
2516 i++;
2517 dns_message_setpadding(lookup->sendmsg,
2518 lookup->padding);
2519 }
2520
2521 flags = lookup->ednsflags;
2522 flags &= ~DNS_MESSAGEEXTFLAG_DO;
2523 if (lookup->dnssec) {
2524 flags |= DNS_MESSAGEEXTFLAG_DO;
2525 }
2526 add_opt(lookup->sendmsg, lookup->udpsize, lookup->edns, flags,
2527 opts, i);
2528 }
2529
2530 result = dns_message_rendersection(lookup->sendmsg,
2531 DNS_SECTION_QUESTION, 0);
2532 check_result(result, "dns_message_rendersection");
2533 result = dns_message_rendersection(lookup->sendmsg,
2534 DNS_SECTION_AUTHORITY, 0);
2535 check_result(result, "dns_message_rendersection");
2536 result = dns_message_renderend(lookup->sendmsg);
2537 check_result(result, "dns_message_renderend");
2538 debug("done rendering");
2539
2540 dns_compress_invalidate(&cctx);
2541
2542 /*
2543 * Force TCP mode if the request is larger than 512 bytes.
2544 */
2545 if (isc_buffer_usedlength(&lookup->renderbuf) > 512) {
2546 lookup->tcp_mode = true;
2547 }
2548
2549 lookup->pending = false;
2550
2551 for (serv = ISC_LIST_HEAD(lookup->my_server_list); serv != NULL;
2552 serv = ISC_LIST_NEXT(serv, link))
2553 {
2554 query = isc_mem_allocate(mctx, sizeof(dig_query_t));
2555 debug("create query %p linked to lookup %p", query, lookup);
2556 query->lookup = lookup;
2557 query->timer = NULL;
2558 query->waiting_connect = false;
2559 query->waiting_senddone = false;
2560 query->pending_free = false;
2561 query->recv_made = false;
2562 query->first_pass = true;
2563 query->first_soa_rcvd = false;
2564 query->second_rr_rcvd = false;
2565 query->first_repeat_rcvd = false;
2566 query->warn_id = true;
2567 query->timedout = false;
2568 query->first_rr_serial = 0;
2569 query->second_rr_serial = 0;
2570 query->servname = serv->servername;
2571 query->userarg = serv->userarg;
2572 query->rr_count = 0;
2573 query->msg_count = 0;
2574 query->byte_count = 0;
2575 query->ixfr_axfr = false;
2576 query->sock = NULL;
2577 query->recvspace = isc_mem_get(mctx, COMMSIZE);
2578 query->tmpsendspace = isc_mem_get(mctx, COMMSIZE);
2579 if (query->recvspace == NULL) {
2580 fatal("memory allocation failure");
2581 }
2582
2583 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
2584 isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
2585 isc_buffer_init(&query->tmpsendbuf, query->tmpsendspace,
2586 COMMSIZE);
2587 query->sendbuf = lookup->renderbuf;
2588
2589 isc_time_settoepoch(&query->time_sent);
2590 isc_time_settoepoch(&query->time_recv);
2591
2592 ISC_LINK_INIT(query, clink);
2593 ISC_LINK_INIT(query, link);
2594 query->saved_next = NULL;
2595
2596 query->magic = DIG_QUERY_MAGIC;
2597
2598 ISC_LIST_ENQUEUE(lookup->q, query, link);
2599 }
2600
2601 return (true);
2602 }
2603
2604 /*%
2605 * Event handler for send completion. Track send counter, and clear out
2606 * the query if the send was canceled.
2607 */
2608 static void
2609 send_done(isc_task_t *_task, isc_event_t *event) {
2610 dig_query_t *query, *next;
2611 dig_lookup_t *l;
2612
2613 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
2614
2615 UNUSED(_task);
2616
2617 LOCK_LOOKUP;
2618
2619 debug("send_done(%p)", event->ev_arg);
2620 sendcount--;
2621 debug("sendcount=%d", sendcount);
2622 INSIST(sendcount >= 0);
2623
2624 query = event->ev_arg;
2625 REQUIRE(DIG_VALID_QUERY(query));
2626 query->waiting_senddone = false;
2627 l = query->lookup;
2628
2629 if (l == current_lookup && l->ns_search_only && !l->trace_root &&
2630 !l->tcp_mode)
2631 {
2632 debug("sending next, since searching");
2633 next = query->pending_free ? query->saved_next
2634 : ISC_LIST_NEXT(query, link);
2635 if (next != NULL) {
2636 send_udp(next);
2637 }
2638 }
2639
2640 isc_event_free(&event);
2641
2642 if (query->pending_free) {
2643 query->magic = 0;
2644 isc_mem_free(mctx, query);
2645 }
2646
2647 check_if_done();
2648 UNLOCK_LOOKUP;
2649 }
2650
2651 /*%
2652 * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
2653 * IO sockets. The cancel handlers should take care of cleaning up the
2654 * query and lookup structures
2655 */
2656 static void
2657 cancel_lookup(dig_lookup_t *lookup) {
2658 dig_query_t *query, *next;
2659
2660 debug("cancel_lookup(%p)", lookup);
2661 query = ISC_LIST_HEAD(lookup->q);
2662 while (query != NULL) {
2663 REQUIRE(DIG_VALID_QUERY(query));
2664 next = ISC_LIST_NEXT(query, link);
2665 if (query->sock != NULL) {
2666 isc_socket_cancel(query->sock, global_task,
2667 ISC_SOCKCANCEL_ALL);
2668 check_if_done();
2669 } else {
2670 clear_query(query);
2671 }
2672 query = next;
2673 }
2674 lookup->pending = false;
2675 lookup->retries = 0;
2676 }
2677
2678 static void
2679 bringup_timer(dig_query_t *query, unsigned int default_timeout) {
2680 dig_lookup_t *l;
2681 unsigned int local_timeout;
2682 isc_result_t result;
2683 REQUIRE(DIG_VALID_QUERY(query));
2684
2685 debug("bringup_timer(%p)", query);
2686 /*
2687 * If the timer already exists, that means we're calling this
2688 * a second time (for a retry). Don't need to recreate it,
2689 * just reset it.
2690 */
2691 l = query->lookup;
2692 if (ISC_LINK_LINKED(query, link) && ISC_LIST_NEXT(query, link) != NULL)
2693 {
2694 local_timeout = SERVER_TIMEOUT;
2695 } else {
2696 if (timeout == 0) {
2697 local_timeout = default_timeout;
2698 } else {
2699 local_timeout = timeout;
2700 }
2701 }
2702 debug("have local timeout of %d", local_timeout);
2703 isc_interval_set(&l->interval, local_timeout, 0);
2704 if (query->timer != NULL) {
2705 isc_timer_destroy(&query->timer);
2706 }
2707 result = isc_timer_create(timermgr, isc_timertype_once, NULL,
2708 &l->interval, global_task, connect_timeout,
2709 query, &query->timer);
2710 check_result(result, "isc_timer_create");
2711 }
2712
2713 static void
2714 force_timeout(dig_query_t *query) {
2715 isc_event_t *event;
2716
2717 debug("force_timeout(%p)", query);
2718 event = isc_event_allocate(mctx, query, ISC_TIMEREVENT_IDLE,
2719 connect_timeout, query, sizeof(isc_event_t));
2720 isc_task_send(global_task, &event);
2721
2722 /*
2723 * The timer may have expired if, for example, get_address() takes
2724 * long time and the timer was running on a different thread.
2725 * We need to cancel the possible timeout event not to confuse
2726 * ourselves due to the duplicate events.
2727 */
2728 if (query->timer != NULL) {
2729 isc_timer_destroy(&query->timer);
2730 }
2731 }
2732
2733 static void
2734 connect_done(isc_task_t *task, isc_event_t *event);
2735
2736 /*%
2737 * Unlike send_udp, this can't be called multiple times with the same
2738 * query. When we retry TCP, we requeue the whole lookup, which should
2739 * start anew.
2740 */
2741 static void
2742 send_tcp_connect(dig_query_t *query) {
2743 isc_result_t result;
2744 dig_query_t *next;
2745 dig_lookup_t *l;
2746 REQUIRE(DIG_VALID_QUERY(query));
2747
2748 debug("send_tcp_connect(%p)", query);
2749
2750 l = query->lookup;
2751 query->waiting_connect = true;
2752 query->lookup->current_query = query;
2753 result = get_address(query->servname, port, &query->sockaddr);
2754 if (result != ISC_R_SUCCESS) {
2755 /*
2756 * This servname doesn't have an address. Try the next server
2757 * by triggering an immediate 'timeout' (we lie, but the effect
2758 * is the same).
2759 */
2760 force_timeout(query);
2761 return;
2762 }
2763
2764 if (!l->mapped && isc_sockaddr_pf(&query->sockaddr) == AF_INET6 &&
2765 IN6_IS_ADDR_V4MAPPED(&query->sockaddr.type.sin6.sin6_addr))
2766 {
2767 isc_netaddr_t netaddr;
2768 char buf[ISC_NETADDR_FORMATSIZE];
2769
2770 isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr);
2771 isc_netaddr_format(&netaddr, buf, sizeof(buf));
2772 dighost_warning("Skipping mapped address '%s'", buf);
2773
2774 query->waiting_connect = false;
2775 if (ISC_LINK_LINKED(query, link)) {
2776 next = ISC_LIST_NEXT(query, link);
2777 } else {
2778 next = NULL;
2779 }
2780 l = query->lookup;
2781 clear_query(query);
2782 if (next == NULL) {
2783 dighost_warning("No acceptable nameservers");
2784 check_next_lookup(l);
2785 return;
2786 }
2787 send_tcp_connect(next);
2788 return;
2789 }
2790
2791 INSIST(query->sock == NULL);
2792
2793 if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) {
2794 sockcount++;
2795 isc_socket_attach(keep, &query->sock);
2796 query->waiting_connect = false;
2797 launch_next_query(query, true);
2798 goto search;
2799 }
2800
2801 result = isc_socket_create(socketmgr, isc_sockaddr_pf(&query->sockaddr),
2802 isc_sockettype_tcp, &query->sock);
2803 check_result(result, "isc_socket_create");
2804 sockcount++;
2805 debug("sockcount=%d", sockcount);
2806 if (query->lookup->dscp != -1) {
2807 isc_socket_dscp(query->sock, query->lookup->dscp);
2808 }
2809 isc_socket_ipv6only(query->sock, !query->lookup->mapped);
2810 if (specified_source) {
2811 result = isc_socket_bind(query->sock, &bind_address,
2812 ISC_SOCKET_REUSEADDRESS);
2813 } else {
2814 if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) && have_ipv4)
2815 {
2816 isc_sockaddr_any(&bind_any);
2817 } else {
2818 isc_sockaddr_any6(&bind_any);
2819 }
2820 result = isc_socket_bind(query->sock, &bind_any, 0);
2821 }
2822 check_result(result, "isc_socket_bind");
2823 bringup_timer(query, TCP_TIMEOUT);
2824 result = isc_socket_connect(query->sock, &query->sockaddr, global_task,
2825 connect_done, query);
2826 check_result(result, "isc_socket_connect");
2827 search:
2828 /*
2829 * If we're at the endgame of a nameserver search, we need to
2830 * immediately bring up all the queries. Do it here.
2831 */
2832 if (l->ns_search_only && !l->trace_root) {
2833 debug("sending next, since searching");
2834 if (ISC_LINK_LINKED(query, link)) {
2835 next = ISC_LIST_NEXT(query, link);
2836 ISC_LIST_DEQUEUE(l->q, query, link);
2837 } else {
2838 next = NULL;
2839 }
2840 ISC_LIST_ENQUEUE(l->connecting, query, clink);
2841 if (next != NULL) {
2842 send_tcp_connect(next);
2843 }
2844 }
2845 }
2846
2847 static void
2848 print_query_size(dig_query_t *query) {
2849 if (!yaml) {
2850 printf(";; QUERY SIZE: %u\n\n",
2851 isc_buffer_usedlength(&query->lookup->renderbuf));
2852 }
2853 }
2854
2855 /*%
2856 * Send a UDP packet to the remote nameserver, possible starting the
2857 * recv action as well. Also make sure that the timer is running and
2858 * is properly reset.
2859 */
2860 static void
2861 send_udp(dig_query_t *query) {
2862 dig_lookup_t *l = NULL;
2863 isc_result_t result;
2864 dig_query_t *next;
2865 isc_region_t r;
2866 isc_socketevent_t *sevent;
2867 REQUIRE(DIG_VALID_QUERY(query));
2868
2869 debug("send_udp(%p)", query);
2870
2871 l = query->lookup;
2872 bringup_timer(query, UDP_TIMEOUT);
2873 l->current_query = query;
2874 debug("working on lookup %p, query %p", query->lookup, query);
2875 if (!query->recv_made) {
2876 /* XXX Check the sense of this, need assertion? */
2877 query->waiting_connect = false;
2878 result = get_address(query->servname, port, &query->sockaddr);
2879 if (result != ISC_R_SUCCESS) {
2880 /* This servname doesn't have an address. */
2881 force_timeout(query);
2882 return;
2883 }
2884
2885 if (!l->mapped &&
2886 isc_sockaddr_pf(&query->sockaddr) == AF_INET6 &&
2887 IN6_IS_ADDR_V4MAPPED(&query->sockaddr.type.sin6.sin6_addr))
2888 {
2889 isc_netaddr_t netaddr;
2890 char buf[ISC_NETADDR_FORMATSIZE];
2891
2892 isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr);
2893 isc_netaddr_format(&netaddr, buf, sizeof(buf));
2894 dighost_warning("Skipping mapped address '%s'", buf);
2895 next = ISC_LIST_NEXT(query, link);
2896 l = query->lookup;
2897 clear_query(query);
2898 if (next == NULL) {
2899 dighost_warning("No acceptable nameservers");
2900 check_next_lookup(l);
2901 } else {
2902 send_udp(next);
2903 }
2904 return;
2905 }
2906
2907 result = isc_socket_create(socketmgr,
2908 isc_sockaddr_pf(&query->sockaddr),
2909 isc_sockettype_udp, &query->sock);
2910 check_result(result, "isc_socket_create");
2911 sockcount++;
2912 debug("sockcount=%d", sockcount);
2913 if (query->lookup->dscp != -1) {
2914 isc_socket_dscp(query->sock, query->lookup->dscp);
2915 }
2916 isc_socket_ipv6only(query->sock, !query->lookup->mapped);
2917 if (specified_source) {
2918 result = isc_socket_bind(query->sock, &bind_address,
2919 ISC_SOCKET_REUSEADDRESS);
2920 } else {
2921 isc_sockaddr_anyofpf(&bind_any,
2922 isc_sockaddr_pf(&query->sockaddr));
2923 result = isc_socket_bind(query->sock, &bind_any, 0);
2924 }
2925 check_result(result, "isc_socket_bind");
2926
2927 query->recv_made = true;
2928 isc_buffer_availableregion(&query->recvbuf, &r);
2929 debug("recving with lookup=%p, query=%p, sock=%p",
2930 query->lookup, query, query->sock);
2931 result = isc_socket_recv(query->sock, &r, 1, global_task,
2932 recv_done, query);
2933 check_result(result, "isc_socket_recv");
2934 recvcount++;
2935 debug("recvcount=%d", recvcount);
2936 }
2937 isc_buffer_usedregion(&query->sendbuf, &r);
2938 debug("sending a request");
2939 if (query->lookup->use_usec) {
2940 TIME_NOW_HIRES(&query->time_sent);
2941 } else {
2942 TIME_NOW(&query->time_sent);
2943 }
2944 INSIST(query->sock != NULL);
2945 query->waiting_senddone = true;
2946 sevent = isc_socket_socketevent(
2947 mctx, query->sock, ISC_SOCKEVENT_SENDDONE, send_done, query);
2948 result = isc_socket_sendto2(query->sock, &r, global_task,
2949 &query->sockaddr, NULL, sevent,
2950 ISC_SOCKFLAG_NORETRY);
2951 check_result(result, "isc_socket_sendto2");
2952 sendcount++;
2953
2954 /* XXX qrflag, print_query, etc... */
2955 if (!ISC_LIST_EMPTY(query->lookup->q) && query->lookup->qr) {
2956 extrabytes = 0;
2957 dighost_printmessage(ISC_LIST_HEAD(query->lookup->q),
2958 &query->lookup->renderbuf,
2959 query->lookup->sendmsg, true);
2960 if (query->lookup->stats) {
2961 print_query_size(query);
2962 }
2963 }
2964 }
2965
2966 /*%
2967 * If there are more servers available for querying within 'lookup', initiate a
2968 * TCP or UDP query to the next available server and return true; otherwise,
2969 * return false.
2970 */
2971 static bool
2972 try_next_server(dig_lookup_t *lookup) {
2973 dig_query_t *current_query, *next_query;
2974
2975 current_query = lookup->current_query;
2976 if (current_query == NULL || !ISC_LINK_LINKED(current_query, link)) {
2977 return (false);
2978 }
2979
2980 next_query = ISC_LIST_NEXT(current_query, link);
2981 if (next_query == NULL) {
2982 return (false);
2983 }
2984
2985 debug("trying next server...");
2986
2987 if (lookup->tcp_mode) {
2988 send_tcp_connect(next_query);
2989 } else {
2990 send_udp(next_query);
2991 }
2992
2993 return (true);
2994 }
2995
2996 /*%
2997 * IO timeout handler, used for both connect and recv timeouts. If
2998 * retries are still allowed, either resend the UDP packet or queue a
2999 * new TCP lookup. Otherwise, cancel the lookup.
3000 */
3001 static void
3002 connect_timeout(isc_task_t *task, isc_event_t *event) {
3003 dig_lookup_t *l = NULL;
3004 dig_query_t *query = NULL;
3005
3006 UNUSED(task);
3007 REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE);
3008
3009 debug("connect_timeout(%p)", event->ev_arg);
3010
3011 LOCK_LOOKUP;
3012 query = event->ev_arg;
3013 REQUIRE(DIG_VALID_QUERY(query));
3014 l = query->lookup;
3015 isc_event_free(&event);
3016
3017 INSIST(!free_now);
3018
3019 if (cancel_now) {
3020 UNLOCK_LOOKUP;
3021 return;
3022 }
3023
3024 if (try_next_server(l)) {
3025 if (l->tcp_mode) {
3026 if (query->sock != NULL) {
3027 isc_socket_cancel(query->sock, NULL,
3028 ISC_SOCKCANCEL_ALL);
3029 } else {
3030 clear_query(query);
3031 }
3032 }
3033 UNLOCK_LOOKUP;
3034 return;
3035 }
3036
3037 if (l->tcp_mode && query->sock != NULL) {
3038 query->timedout = true;
3039 isc_socket_cancel(query->sock, NULL, ISC_SOCKCANCEL_ALL);
3040 }
3041
3042 if (l->retries > 1) {
3043 if (!l->tcp_mode) {
3044 l->retries--;
3045 debug("resending UDP request to first server");
3046 send_udp(ISC_LIST_HEAD(l->q));
3047 } else {
3048 debug("making new TCP request, %d tries left",
3049 l->retries);
3050 l->retries--;
3051 requeue_lookup(l, true);
3052 cancel_lookup(l);
3053 check_next_lookup(l);
3054 }
3055 } else {
3056 if (l->ns_search_only) {
3057 isc_netaddr_t netaddr;
3058 char buf[ISC_NETADDR_FORMATSIZE];
3059
3060 isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr);
3061 isc_netaddr_format(&netaddr, buf, sizeof(buf));
3062
3063 dighost_error("no response from %s\n", buf);
3064 } else {
3065 fputs(l->cmdline, stdout);
3066 dighost_error("connection timed out; "
3067 "no servers could be reached\n");
3068 }
3069 cancel_lookup(l);
3070 check_next_lookup(l);
3071 if (exitcode < 9) {
3072 exitcode = 9;
3073 }
3074 }
3075 UNLOCK_LOOKUP;
3076 }
3077
3078 /*%
3079 * Called when a peer closes a TCP socket prematurely.
3080 */
3081 static void
3082 requeue_or_update_exitcode(dig_lookup_t *lookup) {
3083 if (lookup->eoferr == 0U && lookup->retries > 1) {
3084 --lookup->retries;
3085 /*
3086 * Peer closed the connection prematurely for the first time
3087 * for this lookup. Try again, keeping track of this failure.
3088 */
3089 dig_lookup_t *requeued_lookup = requeue_lookup(lookup, true);
3090 requeued_lookup->eoferr++;
3091 } else {
3092 /*
3093 * Peer closed the connection prematurely and it happened
3094 * previously for this lookup. Indicate an error.
3095 */
3096 exitcode = 9;
3097 }
3098 }
3099
3100 /*%
3101 * Event handler for the TCP recv which gets the length header of TCP
3102 * packets. Start the next recv of length bytes.
3103 */
3104 static void
3105 tcp_length_done(isc_task_t *task, isc_event_t *event) {
3106 isc_socketevent_t *sevent;
3107 isc_buffer_t b;
3108 isc_region_t r;
3109 isc_result_t result;
3110 dig_query_t *query = NULL;
3111 dig_lookup_t *l;
3112 uint16_t length;
3113
3114 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
3115 INSIST(!free_now);
3116
3117 UNUSED(task);
3118
3119 debug("tcp_length_done(%p)", event->ev_arg);
3120
3121 LOCK_LOOKUP;
3122 sevent = (isc_socketevent_t *)event;
3123 query = event->ev_arg;
3124 REQUIRE(DIG_VALID_QUERY(query));
3125
3126 recvcount--;
3127 INSIST(recvcount >= 0);
3128
3129 if (sevent->result == ISC_R_CANCELED) {
3130 isc_event_free(&event);
3131 l = query->lookup;
3132 clear_query(query);
3133 check_next_lookup(l);
3134 UNLOCK_LOOKUP;
3135 return;
3136 }
3137 if (sevent->result != ISC_R_SUCCESS) {
3138 char sockstr[ISC_SOCKADDR_FORMATSIZE];
3139 isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
3140 dighost_error("communications error to %s: %s\n", sockstr,
3141 isc_result_totext(sevent->result));
3142 if (keep != NULL) {
3143 isc_socket_detach(&keep);
3144 }
3145 l = query->lookup;
3146 isc_socket_detach(&query->sock);
3147 sockcount--;
3148 debug("sockcount=%d", sockcount);
3149 INSIST(sockcount >= 0);
3150 if (sevent->result == ISC_R_EOF) {
3151 requeue_or_update_exitcode(l);
3152 }
3153 isc_event_free(&event);
3154 clear_query(query);
3155 cancel_lookup(l);
3156 check_next_lookup(l);
3157 UNLOCK_LOOKUP;
3158 return;
3159 }
3160 isc_buffer_init(&b, sevent->region.base, sevent->n);
3161 isc_buffer_add(&b, sevent->n);
3162 length = isc_buffer_getuint16(&b);
3163
3164 if (length == 0) {
3165 isc_event_free(&event);
3166 launch_next_query(query, false);
3167 UNLOCK_LOOKUP;
3168 return;
3169 }
3170
3171 /*
3172 * Even though the buffer was already init'ed, we need
3173 * to redo it now, to force the length we want.
3174 */
3175 isc_buffer_invalidate(&query->recvbuf);
3176 isc_buffer_init(&query->recvbuf, query->recvspace, length);
3177 isc_buffer_availableregion(&query->recvbuf, &r);
3178 debug("recving with lookup=%p, query=%p", query->lookup, query);
3179 result = isc_socket_recv(query->sock, &r, length, task, recv_done,
3180 query);
3181 check_result(result, "isc_socket_recv");
3182 recvcount++;
3183 debug("resubmitted recv request with length %d, recvcount=%d", length,
3184 recvcount);
3185 isc_event_free(&event);
3186 UNLOCK_LOOKUP;
3187 }
3188
3189 /*%
3190 * For transfers that involve multiple recvs (XFR's in particular),
3191 * launch the next recv.
3192 */
3193 static void
3194 launch_next_query(dig_query_t *query, bool include_question) {
3195 isc_result_t result;
3196 dig_lookup_t *l;
3197 isc_region_t r;
3198 REQUIRE(DIG_VALID_QUERY(query));
3199
3200 INSIST(!free_now);
3201
3202 debug("launch_next_query(%p)", query);
3203
3204 if (!query->lookup->pending) {
3205 debug("ignoring launch_next_query because !pending");
3206 isc_socket_detach(&query->sock);
3207 sockcount--;
3208 debug("sockcount=%d", sockcount);
3209 INSIST(sockcount >= 0);
3210 query->waiting_connect = false;
3211 l = query->lookup;
3212 clear_query(query);
3213 check_next_lookup(l);
3214 return;
3215 }
3216
3217 isc_buffer_clear(&query->lengthbuf);
3218 isc_buffer_availableregion(&query->lengthbuf, &r);
3219 result = isc_socket_recv(query->sock, &r, 0, global_task,
3220 tcp_length_done, query);
3221 check_result(result, "isc_socket_recv");
3222 recvcount++;
3223 debug("recvcount=%d", recvcount);
3224 if (!query->first_soa_rcvd) {
3225 debug("sending a request in launch_next_query");
3226 if (query->lookup->use_usec) {
3227 TIME_NOW_HIRES(&query->time_sent);
3228 } else {
3229 TIME_NOW(&query->time_sent);
3230 }
3231 query->waiting_senddone = true;
3232 isc_buffer_clear(&query->tmpsendbuf);
3233 isc_buffer_putuint16(&query->tmpsendbuf,
3234 isc_buffer_usedlength(&query->sendbuf));
3235 if (include_question) {
3236 isc_buffer_usedregion(&query->sendbuf, &r);
3237 isc_buffer_copyregion(&query->tmpsendbuf, &r);
3238 }
3239 isc_buffer_usedregion(&query->tmpsendbuf, &r);
3240 result = isc_socket_send(query->sock, &r, global_task,
3241 send_done, query);
3242 check_result(result, "isc_socket_send");
3243 sendcount++;
3244 debug("sendcount=%d", sendcount);
3245
3246 /* XXX qrflag, print_query, etc... */
3247 if (!ISC_LIST_EMPTY(query->lookup->q) && query->lookup->qr) {
3248 extrabytes = 0;
3249 dighost_printmessage(ISC_LIST_HEAD(query->lookup->q),
3250 &query->lookup->renderbuf,
3251 query->lookup->sendmsg, true);
3252 if (query->lookup->stats) {
3253 print_query_size(query);
3254 }
3255 }
3256 }
3257 query->waiting_connect = false;
3258 #if 0
3259 check_next_lookup(query->lookup);
3260 #endif /* if 0 */
3261 return;
3262 }
3263
3264 /*%
3265 * Event handler for TCP connect complete. Make sure the connection was
3266 * successful, then pass into launch_next_query to actually send the
3267 * question.
3268 */
3269 static void
3270 connect_done(isc_task_t *task, isc_event_t *event) {
3271 char sockstr[ISC_SOCKADDR_FORMATSIZE];
3272 isc_socketevent_t *sevent = NULL;
3273 dig_query_t *query = NULL, *next;
3274 dig_lookup_t *l;
3275
3276 UNUSED(task);
3277
3278 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
3279 INSIST(!free_now);
3280
3281 debug("connect_done(%p)", event->ev_arg);
3282
3283 LOCK_LOOKUP;
3284 sevent = (isc_socketevent_t *)event;
3285 query = sevent->ev_arg;
3286 REQUIRE(DIG_VALID_QUERY(query));
3287
3288 INSIST(query->waiting_connect);
3289
3290 query->waiting_connect = false;
3291
3292 if (sevent->result == ISC_R_CANCELED) {
3293 debug("in cancel handler");
3294 isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
3295 if (query->timedout) {
3296 dighost_warning("Connection to %s(%s) for %s failed: "
3297 "%s.",
3298 sockstr, query->servname,
3299 query->lookup->textname,
3300 isc_result_totext(ISC_R_TIMEDOUT));
3301 }
3302 isc_socket_detach(&query->sock);
3303 INSIST(sockcount > 0);
3304 sockcount--;
3305 debug("sockcount=%d", sockcount);
3306 query->waiting_connect = false;
3307 isc_event_free(&event);
3308 l = query->lookup;
3309 clear_query(query);
3310 check_next_lookup(l);
3311 UNLOCK_LOOKUP;
3312 return;
3313 }
3314 if (sevent->result != ISC_R_SUCCESS) {
3315 debug("unsuccessful connection: %s",
3316 isc_result_totext(sevent->result));
3317 isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
3318 if (sevent->result != ISC_R_CANCELED) {
3319 dighost_warning("Connection to %s(%s) for %s failed: "
3320 "%s.",
3321 sockstr, query->servname,
3322 query->lookup->textname,
3323 isc_result_totext(sevent->result));
3324 }
3325 isc_socket_detach(&query->sock);
3326 INSIST(sockcount > 0);
3327 sockcount--;
3328 /* XXX Clean up exitcodes */
3329 if (exitcode < 9) {
3330 exitcode = 9;
3331 }
3332 debug("sockcount=%d", sockcount);
3333 query->waiting_connect = false;
3334 isc_event_free(&event);
3335 l = query->lookup;
3336 if ((l->current_query != NULL) &&
3337 (ISC_LINK_LINKED(l->current_query, link)))
3338 {
3339 next = ISC_LIST_NEXT(l->current_query, link);
3340 } else {
3341 next = NULL;
3342 }
3343 clear_query(query);
3344 if (next != NULL) {
3345 bringup_timer(next, TCP_TIMEOUT);
3346 send_tcp_connect(next);
3347 } else {
3348 check_next_lookup(l);
3349 }
3350 UNLOCK_LOOKUP;
3351 return;
3352 }
3353 exitcode = 0;
3354 if (keep_open) {
3355 if (keep != NULL) {
3356 isc_socket_detach(&keep);
3357 }
3358 isc_socket_attach(query->sock, &keep);
3359 keepaddr = query->sockaddr;
3360 }
3361 launch_next_query(query, true);
3362 isc_event_free(&event);
3363 UNLOCK_LOOKUP;
3364 }
3365
3366 /*%
3367 * Check if the ongoing XFR needs more data before it's complete, using
3368 * the semantics of IXFR and AXFR protocols. Much of the complexity of
3369 * this routine comes from determining when an IXFR is complete.
3370 * false means more data is on the way, and the recv has been issued.
3371 */
3372 static bool
3373 check_for_more_data(dig_query_t *query, dns_message_t *msg,
3374 isc_socketevent_t *sevent) {
3375 dns_rdataset_t *rdataset = NULL;
3376 dns_rdata_t rdata = DNS_RDATA_INIT;
3377 dns_rdata_soa_t soa;
3378 uint32_t ixfr_serial = query->lookup->ixfr_serial, serial;
3379 isc_result_t result;
3380 bool ixfr = query->lookup->rdtype == dns_rdatatype_ixfr;
3381 bool axfr = query->lookup->rdtype == dns_rdatatype_axfr;
3382
3383 if (ixfr) {
3384 axfr = query->ixfr_axfr;
3385 }
3386
3387 debug("check_for_more_data(%p)", query);
3388
3389 /*
3390 * By the time we're in this routine, we know we're doing
3391 * either an AXFR or IXFR. If there's no second_rr_type,
3392 * then we don't yet know which kind of answer we got back
3393 * from the server. Here, we're going to walk through the
3394 * rr's in the message, acting as necessary whenever we hit
3395 * an SOA rr.
3396 */
3397
3398 query->msg_count++;
3399 query->byte_count += sevent->n;
3400 result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
3401 if (result != ISC_R_SUCCESS) {
3402 puts("; Transfer failed.");
3403 return (true);
3404 }
3405 do {
3406 dns_name_t *name;
3407 name = NULL;
3408 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
3409 for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
3410 rdataset = ISC_LIST_NEXT(rdataset, link))
3411 {
3412 result = dns_rdataset_first(rdataset);
3413 if (result != ISC_R_SUCCESS) {
3414 continue;
3415 }
3416 do {
3417 query->rr_count++;
3418 dns_rdata_reset(&rdata);
3419 dns_rdataset_current(rdataset, &rdata);
3420 /*
3421 * If this is the first rr, make sure
3422 * it's an SOA
3423 */
3424 if ((!query->first_soa_rcvd) &&
3425 (rdata.type != dns_rdatatype_soa))
3426 {
3427 puts("; Transfer failed. "
3428 "Didn't start with SOA answer.");
3429 return (true);
3430 }
3431 if ((!query->second_rr_rcvd) &&
3432 (rdata.type != dns_rdatatype_soa))
3433 {
3434 query->second_rr_rcvd = true;
3435 query->second_rr_serial = 0;
3436 debug("got the second rr as nonsoa");
3437 axfr = query->ixfr_axfr = true;
3438 goto next_rdata;
3439 }
3440
3441 /*
3442 * If the record is anything except an SOA
3443 * now, just continue on...
3444 */
3445 if (rdata.type != dns_rdatatype_soa) {
3446 goto next_rdata;
3447 }
3448
3449 /* Now we have an SOA. Work with it. */
3450 debug("got an SOA");
3451 result = dns_rdata_tostruct(&rdata, &soa, NULL);
3452 check_result(result, "dns_rdata_tostruct");
3453 serial = soa.serial;
3454 dns_rdata_freestruct(&soa);
3455 if (!query->first_soa_rcvd) {
3456 query->first_soa_rcvd = true;
3457 query->first_rr_serial = serial;
3458 debug("this is the first serial %u",
3459 serial);
3460 if (ixfr &&
3461 isc_serial_ge(ixfr_serial, serial))
3462 {
3463 debug("got up to date "
3464 "response");
3465 goto doexit;
3466 }
3467 goto next_rdata;
3468 }
3469 if (axfr) {
3470 debug("doing axfr, got second SOA");
3471 goto doexit;
3472 }
3473 if (!query->second_rr_rcvd) {
3474 if (query->first_rr_serial == serial) {
3475 debug("doing ixfr, got "
3476 "empty zone");
3477 goto doexit;
3478 }
3479 debug("this is the second serial %u",
3480 serial);
3481 query->second_rr_rcvd = true;
3482 query->second_rr_serial = serial;
3483 goto next_rdata;
3484 }
3485 /*
3486 * If we get to this point, we're doing an
3487 * IXFR and have to start really looking
3488 * at serial numbers.
3489 */
3490 if (query->first_rr_serial == serial) {
3491 debug("got a match for ixfr");
3492 if (!query->first_repeat_rcvd) {
3493 query->first_repeat_rcvd = true;
3494 goto next_rdata;
3495 }
3496 debug("done with ixfr");
3497 goto doexit;
3498 }
3499 debug("meaningless soa %u", serial);
3500 next_rdata:
3501 result = dns_rdataset_next(rdataset);
3502 } while (result == ISC_R_SUCCESS);
3503 }
3504 result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
3505 } while (result == ISC_R_SUCCESS);
3506 launch_next_query(query, false);
3507 return (false);
3508 doexit:
3509 dighost_received(sevent->n, &sevent->address, query);
3510 return (true);
3511 }
3512
3513 static void
3514 process_cookie(dig_lookup_t *l, dns_message_t *msg, isc_buffer_t *optbuf,
3515 size_t optlen) {
3516 char bb[256];
3517 isc_buffer_t hexbuf;
3518 size_t len;
3519 const unsigned char *sent;
3520 bool copy = true;
3521 isc_result_t result;
3522
3523 if (l->cookie != NULL) {
3524 isc_buffer_init(&hexbuf, bb, sizeof(bb));
3525 result = isc_hex_decodestring(l->cookie, &hexbuf);
3526 check_result(result, "isc_hex_decodestring");
3527 sent = isc_buffer_base(&hexbuf);
3528 len = isc_buffer_usedlength(&hexbuf);
3529 } else {
3530 sent = cookie;
3531 len = sizeof(cookie);
3532 }
3533
3534 INSIST(msg->cc_ok == 0 && msg->cc_bad == 0);
3535 if (len >= 8 && optlen >= 8U) {
3536 if (isc_safe_memequal(isc_buffer_current(optbuf), sent, 8)) {
3537 msg->cc_ok = 1;
3538 } else {
3539 dighost_warning("Warning: Client COOKIE mismatch");
3540 msg->cc_bad = 1;
3541 copy = false;
3542 }
3543 } else {
3544 dighost_warning("Warning: COOKIE bad token (too short)");
3545 msg->cc_bad = 1;
3546 copy = false;
3547 }
3548 if (copy) {
3549 isc_region_t r;
3550
3551 r.base = isc_buffer_current(optbuf);
3552 r.length = (unsigned int)optlen;
3553 isc_buffer_init(&hexbuf, servercookie, sizeof(servercookie));
3554 result = isc_hex_totext(&r, 2, "", &hexbuf);
3555 check_result(result, "isc_hex_totext");
3556 if (isc_buffer_availablelength(&hexbuf) > 0) {
3557 isc_buffer_putuint8(&hexbuf, 0);
3558 l->cookie = servercookie;
3559 }
3560 }
3561 isc_buffer_forward(optbuf, (unsigned int)optlen);
3562 }
3563
3564 static void
3565 process_opt(dig_lookup_t *l, dns_message_t *msg) {
3566 dns_rdata_t rdata;
3567 isc_result_t result;
3568 isc_buffer_t optbuf;
3569 uint16_t optcode, optlen;
3570 dns_rdataset_t *opt = msg->opt;
3571 bool seen_cookie = false;
3572
3573 result = dns_rdataset_first(opt);
3574 if (result == ISC_R_SUCCESS) {
3575 dns_rdata_init(&rdata);
3576 dns_rdataset_current(opt, &rdata);
3577 isc_buffer_init(&optbuf, rdata.data, rdata.length);
3578 isc_buffer_add(&optbuf, rdata.length);
3579 while (isc_buffer_remaininglength(&optbuf) >= 4) {
3580 optcode = isc_buffer_getuint16(&optbuf);
3581 optlen = isc_buffer_getuint16(&optbuf);
3582 switch (optcode) {
3583 case DNS_OPT_COOKIE:
3584 /*
3585 * Only process the first cookie option.
3586 */
3587 if (seen_cookie) {
3588 isc_buffer_forward(&optbuf, optlen);
3589 break;
3590 }
3591 process_cookie(l, msg, &optbuf, optlen);
3592 seen_cookie = true;
3593 break;
3594 default:
3595 isc_buffer_forward(&optbuf, optlen);
3596 break;
3597 }
3598 }
3599 }
3600 }
3601
3602 static int
3603 ednsvers(dns_rdataset_t *opt) {
3604 return ((opt->ttl >> 16) & 0xff);
3605 }
3606
3607 /*%
3608 * Event handler for recv complete. Perform whatever actions are necessary,
3609 * based on the specifics of the user's request.
3610 */
3611 static void
3612 recv_done(isc_task_t *task, isc_event_t *event) {
3613 isc_socketevent_t *sevent = NULL;
3614 isc_region_t r;
3615 dig_query_t *query = NULL;
3616 isc_buffer_t b;
3617 dns_message_t *msg = NULL;
3618 isc_result_t result;
3619 dig_lookup_t *n, *l;
3620 bool docancel = false;
3621 bool match = true;
3622 bool done_process_opt = false;
3623 unsigned int parseflags;
3624 dns_messageid_t id;
3625 unsigned int msgflags;
3626 int newedns;
3627
3628 UNUSED(task);
3629 INSIST(!free_now);
3630
3631 debug("recv_done(%p)", event->ev_arg);
3632
3633 LOCK_LOOKUP;
3634 recvcount--;
3635 debug("recvcount=%d", recvcount);
3636 INSIST(recvcount >= 0);
3637
3638 query = event->ev_arg;
3639 if (query->lookup->use_usec) {
3640 TIME_NOW_HIRES(&query->time_recv);
3641 } else {
3642 TIME_NOW(&query->time_recv);
3643 }
3644
3645 l = query->lookup;
3646
3647 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
3648 sevent = (isc_socketevent_t *)event;
3649
3650 isc_buffer_init(&b, sevent->region.base, sevent->n);
3651 isc_buffer_add(&b, sevent->n);
3652
3653 if ((l->tcp_mode) && (query->timer != NULL)) {
3654 isc_timer_touch(query->timer);
3655 }
3656 if ((!l->pending && !l->ns_search_only) || cancel_now) {
3657 debug("no longer pending. Got %s",
3658 isc_result_totext(sevent->result));
3659 query->waiting_connect = false;
3660
3661 isc_event_free(&event);
3662 clear_query(query);
3663 check_next_lookup(l);
3664 UNLOCK_LOOKUP;
3665 return;
3666 }
3667
3668 if (sevent->result != ISC_R_SUCCESS) {
3669 if (sevent->result == ISC_R_CANCELED) {
3670 debug("in recv cancel handler");
3671 query->waiting_connect = false;
3672 } else {
3673 dighost_error("communications error: %s\n",
3674 isc_result_totext(sevent->result));
3675 if (keep != NULL) {
3676 isc_socket_detach(&keep);
3677 }
3678 isc_socket_detach(&query->sock);
3679 sockcount--;
3680 debug("sockcount=%d", sockcount);
3681 INSIST(sockcount >= 0);
3682 }
3683 if (sevent->result == ISC_R_EOF) {
3684 requeue_or_update_exitcode(l);
3685 }
3686 isc_event_free(&event);
3687 clear_query(query);
3688 cancel_lookup(l);
3689 check_next_lookup(l);
3690 UNLOCK_LOOKUP;
3691 return;
3692 }
3693
3694 if (!l->tcp_mode &&
3695 !isc_sockaddr_compare(&sevent->address, &query->sockaddr,
3696 ISC_SOCKADDR_CMPADDR | ISC_SOCKADDR_CMPPORT |
3697 ISC_SOCKADDR_CMPSCOPE |
3698 ISC_SOCKADDR_CMPSCOPEZERO))
3699 {
3700 char buf1[ISC_SOCKADDR_FORMATSIZE];
3701 char buf2[ISC_SOCKADDR_FORMATSIZE];
3702 isc_sockaddr_t any;
3703
3704 if (isc_sockaddr_pf(&query->sockaddr) == AF_INET) {
3705 isc_sockaddr_any(&any);
3706 } else {
3707 isc_sockaddr_any6(&any);
3708 }
3709
3710 /*
3711 * We don't expect a match when the packet is
3712 * sent to 0.0.0.0, :: or to a multicast addresses.
3713 * XXXMPA broadcast needs to be handled here as well.
3714 */
3715 if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) &&
3716 !isc_sockaddr_ismulticast(&query->sockaddr)) ||
3717 isc_sockaddr_getport(&query->sockaddr) !=
3718 isc_sockaddr_getport(&sevent->address))
3719 {
3720 isc_sockaddr_format(&sevent->address, buf1,
3721 sizeof(buf1));
3722 isc_sockaddr_format(&query->sockaddr, buf2,
3723 sizeof(buf2));
3724 dighost_warning("reply from unexpected source: %s,"
3725 " expected %s\n",
3726 buf1, buf2);
3727 if (!l->accept_reply_unexpected_src) {
3728 match = false;
3729 }
3730 }
3731 }
3732
3733 result = dns_message_peekheader(&b, &id, &msgflags);
3734 if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
3735 match = false;
3736 if (l->tcp_mode) {
3737 bool fail = true;
3738 if (result == ISC_R_SUCCESS) {
3739 if ((!query->first_soa_rcvd || query->warn_id))
3740 {
3741 dighost_warning("%s: ID mismatch: "
3742 "expected ID %u, got "
3743 "%u",
3744 query->first_soa_rcvd
3745 ? "WARNING"
3746 : "ERROR",
3747 l->sendmsg->id, id);
3748 }
3749 if (query->first_soa_rcvd) {
3750 fail = false;
3751 }
3752 query->warn_id = false;
3753 } else {
3754 dighost_warning("ERROR: short (< header size) "
3755 "message");
3756 }
3757 if (fail) {
3758 isc_event_free(&event);
3759 clear_query(query);
3760 cancel_lookup(l);
3761 check_next_lookup(l);
3762 UNLOCK_LOOKUP;
3763 return;
3764 }
3765 match = true;
3766 } else if (result == ISC_R_SUCCESS) {
3767 dighost_warning("Warning: ID mismatch: expected ID %u,"
3768 " got %u",
3769 l->sendmsg->id, id);
3770 } else {
3771 dighost_warning("Warning: short (< header size) "
3772 "message received");
3773 }
3774 }
3775
3776 if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0) {
3777 dighost_warning("Warning: query response not set");
3778 }
3779
3780 if (!match) {
3781 goto udp_mismatch;
3782 }
3783
3784 dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
3785
3786 if (tsigkey != NULL) {
3787 if (l->querysig == NULL) {
3788 debug("getting initial querysig");
3789 result = dns_message_getquerytsig(l->sendmsg, mctx,
3790 &l->querysig);
3791 check_result(result, "dns_message_getquerytsig");
3792 }
3793 result = dns_message_setquerytsig(msg, l->querysig);
3794 check_result(result, "dns_message_setquerytsig");
3795 result = dns_message_settsigkey(msg, tsigkey);
3796 check_result(result, "dns_message_settsigkey");
3797 msg->tsigctx = l->tsigctx;
3798 l->tsigctx = NULL;
3799 if (l->msgcounter != 0) {
3800 msg->tcp_continuation = 1;
3801 }
3802 l->msgcounter++;
3803 }
3804
3805 debug("before parse starts");
3806 parseflags = DNS_MESSAGEPARSE_PRESERVEORDER;
3807 if (l->besteffort) {
3808 parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
3809 parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
3810 }
3811 result = dns_message_parse(msg, &b, parseflags);
3812 if (result == DNS_R_RECOVERABLE) {
3813 dighost_warning("Warning: Message parser reports malformed "
3814 "message packet.");
3815 result = ISC_R_SUCCESS;
3816 }
3817 if (result != ISC_R_SUCCESS) {
3818 if (!yaml) {
3819 printf(";; Got bad packet: %s\n",
3820 isc_result_totext(result));
3821 hex_dump(&b);
3822 }
3823 query->waiting_connect = false;
3824 dns_message_detach(&msg);
3825 isc_event_free(&event);
3826 clear_query(query);
3827 cancel_lookup(l);
3828 check_next_lookup(l);
3829 UNLOCK_LOOKUP;
3830 return;
3831 }
3832 if (msg->opcode != l->opcode) {
3833 char expect[20] = { 0 }, got[20] = { 0 };
3834
3835 isc_buffer_init(&b, &expect, sizeof(expect));
3836 result = dns_opcode_totext(l->opcode, &b);
3837 check_result(result, "dns_opcode_totext");
3838
3839 isc_buffer_init(&b, &got, sizeof(got));
3840 result = dns_opcode_totext(msg->opcode, &b);
3841 check_result(result, "dns_opcode_totext");
3842
3843 dighost_warning("Warning: Opcode mismatch: expected %s, got %s",
3844 expect, got);
3845
3846 dns_message_detach(&msg);
3847 if (l->tcp_mode) {
3848 isc_event_free(&event);
3849 clear_query(query);
3850 cancel_lookup(l);
3851 check_next_lookup(l);
3852 UNLOCK_LOOKUP;
3853 return;
3854 } else {
3855 goto udp_mismatch;
3856 }
3857 }
3858 if (msg->counts[DNS_SECTION_QUESTION] != 0) {
3859 match = true;
3860 for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
3861 result == ISC_R_SUCCESS && match;
3862 result = dns_message_nextname(msg, DNS_SECTION_QUESTION))
3863 {
3864 dns_name_t *name = NULL;
3865 dns_rdataset_t *rdataset;
3866
3867 dns_message_currentname(msg, DNS_SECTION_QUESTION,
3868 &name);
3869 for (rdataset = ISC_LIST_HEAD(name->list);
3870 rdataset != NULL;
3871 rdataset = ISC_LIST_NEXT(rdataset, link))
3872 {
3873 if (l->rdtype != rdataset->type ||
3874 l->rdclass != rdataset->rdclass ||
3875 !dns_name_equal(l->name, name))
3876 {
3877 char namestr[DNS_NAME_FORMATSIZE];
3878 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3879 char classbuf[DNS_RDATACLASS_FORMATSIZE];
3880 dns_name_format(name, namestr,
3881 sizeof(namestr));
3882 dns_rdatatype_format(rdataset->type,
3883 typebuf,
3884 sizeof(typebuf));
3885 dns_rdataclass_format(rdataset->rdclass,
3886 classbuf,
3887 sizeof(classbuf));
3888 dighost_warning(";; Question section "
3889 "mismatch: got "
3890 "%s/%s/%s",
3891 namestr, typebuf,
3892 classbuf);
3893 match = false;
3894 }
3895 }
3896 }
3897 if (!match) {
3898 dns_message_detach(&msg);
3899 if (l->tcp_mode) {
3900 isc_event_free(&event);
3901 clear_query(query);
3902 cancel_lookup(l);
3903 check_next_lookup(l);
3904 UNLOCK_LOOKUP;
3905 return;
3906 } else {
3907 goto udp_mismatch;
3908 }
3909 }
3910 }
3911 if (msg->rcode == dns_rcode_badvers && msg->opt != NULL &&
3912 (newedns = ednsvers(msg->opt)) < l->edns && l->ednsneg)
3913 {
3914 /*
3915 * Add minimum EDNS version required checks here if needed.
3916 */
3917 dighost_comments(l, "BADVERS, retrying with EDNS version %u.",
3918 (unsigned int)newedns);
3919 l->edns = newedns;
3920 n = requeue_lookup(l, true);
3921 if (l->trace && l->trace_root) {
3922 n->rdtype = l->qrdtype;
3923 }
3924 dns_message_detach(&msg);
3925 isc_event_free(&event);
3926 clear_query(query);
3927 cancel_lookup(l);
3928 check_next_lookup(l);
3929 UNLOCK_LOOKUP;
3930 return;
3931 }
3932 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 && !l->ignore &&
3933 !l->tcp_mode)
3934 {
3935 if (l->cookie == NULL && l->sendcookie && msg->opt != NULL) {
3936 process_opt(l, msg);
3937 }
3938 dighost_comments(l, "Truncated, retrying in TCP mode.");
3939 n = requeue_lookup(l, true);
3940 n->tcp_mode = true;
3941 if (l->trace && l->trace_root) {
3942 n->rdtype = l->qrdtype;
3943 }
3944 dns_message_detach(&msg);
3945 isc_event_free(&event);
3946 clear_query(query);
3947 cancel_lookup(l);
3948 check_next_lookup(l);
3949 UNLOCK_LOOKUP;
3950 return;
3951 }
3952 if (msg->rcode == dns_rcode_badcookie && !l->tcp_mode &&
3953 l->sendcookie && l->badcookie)
3954 {
3955 process_opt(l, msg);
3956 if (msg->cc_ok) {
3957 dighost_comments(l, "BADCOOKIE, retrying%s.",
3958 l->seenbadcookie ? " in TCP mode"
3959 : "");
3960 n = requeue_lookup(l, true);
3961 if (l->seenbadcookie) {
3962 n->tcp_mode = true;
3963 }
3964 n->seenbadcookie = true;
3965 if (l->trace && l->trace_root) {
3966 n->rdtype = l->qrdtype;
3967 }
3968 dns_message_detach(&msg);
3969 isc_event_free(&event);
3970 clear_query(query);
3971 cancel_lookup(l);
3972 check_next_lookup(l);
3973 UNLOCK_LOOKUP;
3974 return;
3975 }
3976 done_process_opt = true;
3977 }
3978 if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) ||
3979 (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse))
3980 {
3981 dig_query_t *next = ISC_LIST_NEXT(query, link);
3982 if (l->current_query == query) {
3983 l->current_query = NULL;
3984 }
3985 if (next != NULL) {
3986 debug("sending query %p\n", next);
3987 if (l->tcp_mode) {
3988 send_tcp_connect(next);
3989 } else {
3990 send_udp(next);
3991 }
3992 }
3993 /*
3994 * If our query is at the head of the list and there
3995 * is no next, we're the only one left, so fall
3996 * through to print the message.
3997 */
3998 if ((ISC_LIST_HEAD(l->q) != query) ||
3999 (ISC_LIST_NEXT(query, link) != NULL))
4000 {
4001 dighost_comments(l,
4002 "Got %s from %s, trying next "
4003 "server",
4004 msg->rcode == dns_rcode_servfail
4005 ? "SERVFAIL reply"
4006 : "recursion not available",
4007 query->servname);
4008 clear_query(query);
4009 check_next_lookup(l);
4010 dns_message_detach(&msg);
4011 isc_event_free(&event);
4012 UNLOCK_LOOKUP;
4013 return;
4014 }
4015 }
4016
4017 if (tsigkey != NULL) {
4018 result = dns_tsig_verify(&b, msg, NULL, NULL);
4019 if (result != ISC_R_SUCCESS) {
4020 dighost_warning("Couldn't verify signature: %s",
4021 isc_result_totext(result));
4022 validated = false;
4023 }
4024 l->tsigctx = msg->tsigctx;
4025 msg->tsigctx = NULL;
4026 if (l->querysig != NULL) {
4027 debug("freeing querysig buffer %p", l->querysig);
4028 isc_buffer_free(&l->querysig);
4029 }
4030 result = dns_message_getquerytsig(msg, mctx, &l->querysig);
4031 check_result(result, "dns_message_getquerytsig");
4032 }
4033
4034 extrabytes = isc_buffer_remaininglength(&b);
4035
4036 debug("after parse");
4037 if (l->doing_xfr && l->xfr_q == NULL) {
4038 l->xfr_q = query;
4039 /*
4040 * Once we are in the XFR message, increase
4041 * the timeout to much longer, so brief network
4042 * outages won't cause the XFR to abort
4043 */
4044 if (timeout != INT_MAX && query->timer != NULL) {
4045 unsigned int local_timeout;
4046
4047 if (timeout == 0) {
4048 if (l->tcp_mode) {
4049 local_timeout = TCP_TIMEOUT * 4;
4050 } else {
4051 local_timeout = UDP_TIMEOUT * 4;
4052 }
4053 } else {
4054 if (timeout < (INT_MAX / 4)) {
4055 local_timeout = timeout * 4;
4056 } else {
4057 local_timeout = INT_MAX;
4058 }
4059 }
4060 debug("have local timeout of %d", local_timeout);
4061 isc_interval_set(&l->interval, local_timeout, 0);
4062 result = isc_timer_reset(query->timer,
4063 isc_timertype_once, NULL,
4064 &l->interval, false);
4065 check_result(result, "isc_timer_reset");
4066 }
4067 }
4068
4069 if (!done_process_opt) {
4070 if (l->cookie != NULL) {
4071 if (msg->opt == NULL) {
4072 dighost_warning("expected opt record in "
4073 "response");
4074 } else {
4075 process_opt(l, msg);
4076 }
4077 } else if (l->sendcookie && msg->opt != NULL) {
4078 process_opt(l, msg);
4079 }
4080 }
4081 if (!l->doing_xfr || l->xfr_q == query) {
4082 if (msg->rcode == dns_rcode_nxdomain &&
4083 (l->origin != NULL || l->need_search))
4084 {
4085 if (!next_origin(query->lookup) || showsearch) {
4086 dighost_printmessage(query, &b, msg, true);
4087 dighost_received(isc_buffer_usedlength(&b),
4088 &sevent->address, query);
4089 }
4090 } else if (!l->trace && !l->ns_search_only) {
4091 dighost_printmessage(query, &b, msg, true);
4092 } else if (l->trace) {
4093 int nl = 0;
4094 int count = msg->counts[DNS_SECTION_ANSWER];
4095
4096 debug("in TRACE code");
4097 if (!l->ns_search_only) {
4098 dighost_printmessage(query, &b, msg, true);
4099 }
4100
4101 l->rdtype = l->qrdtype;
4102 if (l->trace_root || (l->ns_search_only && count > 0)) {
4103 if (!l->trace_root) {
4104 l->rdtype = dns_rdatatype_soa;
4105 }
4106 nl = followup_lookup(msg, query,
4107 DNS_SECTION_ANSWER);
4108 l->trace_root = false;
4109 } else if (count == 0) {
4110 nl = followup_lookup(msg, query,
4111 DNS_SECTION_AUTHORITY);
4112 }
4113 if (nl == 0) {
4114 docancel = true;
4115 }
4116 } else {
4117 debug("in NSSEARCH code");
4118
4119 if (l->trace_root) {
4120 /*
4121 * This is the initial NS query.
4122 */
4123 int nl;
4124
4125 l->rdtype = dns_rdatatype_soa;
4126 nl = followup_lookup(msg, query,
4127 DNS_SECTION_ANSWER);
4128 if (nl == 0) {
4129 docancel = true;
4130 }
4131 l->trace_root = false;
4132 usesearch = false;
4133 } else {
4134 dighost_printmessage(query, &b, msg, true);
4135 }
4136 }
4137 }
4138
4139 if (l->pending) {
4140 debug("still pending.");
4141 }
4142 if (l->doing_xfr) {
4143 if (query != l->xfr_q) {
4144 dns_message_detach(&msg);
4145 isc_event_free(&event);
4146 query->waiting_connect = false;
4147 UNLOCK_LOOKUP;
4148 return;
4149 }
4150 if (!docancel) {
4151 docancel = check_for_more_data(query, msg, sevent);
4152 }
4153 if (docancel) {
4154 dns_message_detach(&msg);
4155 clear_query(query);
4156 cancel_lookup(l);
4157 check_next_lookup(l);
4158 }
4159 } else {
4160 if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
4161 dighost_received(isc_buffer_usedlength(&b),
4162 &sevent->address, query);
4163 }
4164
4165 if (!query->lookup->ns_search_only) {
4166 query->lookup->pending = false;
4167 }
4168 if (!query->lookup->ns_search_only ||
4169 query->lookup->trace_root || docancel)
4170 {
4171 dns_message_detach(&msg);
4172 cancel_lookup(l);
4173 }
4174 clear_query(query);
4175 check_next_lookup(l);
4176 }
4177 if (msg != NULL) {
4178 dns_message_detach(&msg);
4179 }
4180 isc_event_free(&event);
4181 UNLOCK_LOOKUP;
4182 return;
4183
4184 udp_mismatch:
4185 isc_buffer_invalidate(&query->recvbuf);
4186 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
4187 isc_buffer_availableregion(&query->recvbuf, &r);
4188 result = isc_socket_recv(query->sock, &r, 1, global_task, recv_done,
4189 query);
4190 check_result(result, "isc_socket_recv");
4191 recvcount++;
4192 isc_event_free(&event);
4193 UNLOCK_LOOKUP;
4194 return;
4195 }
4196
4197 /*%
4198 * Turn a name into an address, using system-supplied routines. This is
4199 * used in looking up server names, etc... and needs to use system-supplied
4200 * routines, since they may be using a non-DNS system for these lookups.
4201 */
4202 isc_result_t
4203 get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr) {
4204 int count;
4205 isc_result_t result;
4206 bool is_running;
4207
4208 is_running = isc_app_isrunning();
4209 if (is_running) {
4210 isc_app_block();
4211 }
4212 result = bind9_getaddresses(host, myport, sockaddr, 1, &count);
4213 if (is_running) {
4214 isc_app_unblock();
4215 }
4216 if (result != ISC_R_SUCCESS) {
4217 return (result);
4218 }
4219
4220 INSIST(count == 1);
4221
4222 return (ISC_R_SUCCESS);
4223 }
4224
4225 int
4226 getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) {
4227 isc_result_t result;
4228 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
4229 isc_netaddr_t netaddr;
4230 int count, i;
4231 dig_server_t *srv;
4232 char tmp[ISC_NETADDR_FORMATSIZE];
4233
4234 result = bind9_getaddresses(host, 0, sockaddrs, DIG_MAX_ADDRESSES,
4235 &count);
4236 if (resultp != NULL) {
4237 *resultp = result;
4238 }
4239 if (result != ISC_R_SUCCESS) {
4240 if (resultp == NULL) {
4241 fatal("couldn't get address for '%s': %s", host,
4242 isc_result_totext(result));
4243 }
4244 return (0);
4245 }
4246
4247 for (i = 0; i < count; i++) {
4248 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
4249 isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
4250 srv = make_server(tmp, host);
4251 ISC_LIST_APPEND(lookup->my_server_list, srv, link);
4252 }
4253
4254 return (count);
4255 }
4256
4257 /*%
4258 * Initiate either a TCP or UDP lookup
4259 */
4260 void
4261 do_lookup(dig_lookup_t *lookup) {
4262 dig_query_t *query;
4263
4264 REQUIRE(lookup != NULL);
4265
4266 debug("do_lookup(%p)", lookup);
4267 lookup->pending = true;
4268 query = ISC_LIST_HEAD(lookup->q);
4269 if (query != NULL) {
4270 REQUIRE(DIG_VALID_QUERY(query));
4271 if (lookup->tcp_mode) {
4272 send_tcp_connect(query);
4273 } else {
4274 send_udp(query);
4275 }
4276 }
4277 }
4278
4279 /*%
4280 * Start everything in action upon task startup.
4281 */
4282 void
4283 onrun_callback(isc_task_t *task, isc_event_t *event) {
4284 UNUSED(task);
4285
4286 isc_event_free(&event);
4287 LOCK_LOOKUP;
4288 start_lookup();
4289 UNLOCK_LOOKUP;
4290 }
4291
4292 /*%
4293 * Make everything on the lookup queue go away. Mainly used by the
4294 * SIGINT handler.
4295 */
4296 void
4297 cancel_all(void) {
4298 dig_lookup_t *l, *n;
4299 dig_query_t *q, *nq;
4300
4301 debug("cancel_all()");
4302
4303 LOCK_LOOKUP;
4304 if (free_now) {
4305 UNLOCK_LOOKUP;
4306 return;
4307 }
4308 cancel_now = true;
4309 if (current_lookup != NULL) {
4310 for (q = ISC_LIST_HEAD(current_lookup->q); q != NULL; q = nq) {
4311 nq = ISC_LIST_NEXT(q, link);
4312 debug("canceling pending query %p, belonging to %p", q,
4313 current_lookup);
4314 if (q->sock != NULL) {
4315 isc_socket_cancel(q->sock, NULL,
4316 ISC_SOCKCANCEL_ALL);
4317 } else {
4318 clear_query(q);
4319 }
4320 }
4321 for (q = ISC_LIST_HEAD(current_lookup->connecting); q != NULL;
4322 q = nq)
4323 {
4324 nq = ISC_LIST_NEXT(q, clink);
4325 debug("canceling connecting query %p, belonging to %p",
4326 q, current_lookup);
4327 if (q->sock != NULL) {
4328 isc_socket_cancel(q->sock, NULL,
4329 ISC_SOCKCANCEL_ALL);
4330 } else {
4331 clear_query(q);
4332 }
4333 }
4334 }
4335 l = ISC_LIST_HEAD(lookup_list);
4336 while (l != NULL) {
4337 n = ISC_LIST_NEXT(l, link);
4338 ISC_LIST_DEQUEUE(lookup_list, l, link);
4339 try_clear_lookup(l);
4340 l = n;
4341 }
4342 UNLOCK_LOOKUP;
4343 }
4344
4345 /*%
4346 * Destroy all of the libs we are using, and get everything ready for a
4347 * clean shutdown.
4348 */
4349 void
4350 destroy_libs(void) {
4351 #ifdef HAVE_LIBIDN2
4352 isc_result_t result;
4353 #endif /* HAVE_LIBIDN2 */
4354
4355 if (keep != NULL) {
4356 isc_socket_detach(&keep);
4357 }
4358 debug("destroy_libs()");
4359 if (global_task != NULL) {
4360 debug("freeing task");
4361 isc_task_detach(&global_task);
4362 }
4363
4364 if (taskmgr != NULL) {
4365 debug("freeing taskmgr");
4366 isc_managers_destroy(&netmgr, &taskmgr);
4367 }
4368 LOCK_LOOKUP;
4369 REQUIRE(sockcount == 0);
4370 REQUIRE(recvcount == 0);
4371 REQUIRE(sendcount == 0);
4372
4373 INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
4374 INSIST(current_lookup == NULL);
4375 INSIST(!free_now);
4376
4377 free_now = true;
4378
4379 flush_server_list();
4380
4381 clear_searchlist();
4382
4383 #ifdef HAVE_LIBIDN2
4384 result = dns_name_settotextfilter(NULL);
4385 check_result(result, "dns_name_settotextfilter");
4386 #endif /* HAVE_LIBIDN2 */
4387
4388 if (socketmgr != NULL) {
4389 debug("freeing socketmgr");
4390 isc_socketmgr_destroy(&socketmgr);
4391 }
4392 if (timermgr != NULL) {
4393 debug("freeing timermgr");
4394 isc_timermgr_destroy(&timermgr);
4395 }
4396 if (tsigkey != NULL) {
4397 debug("freeing key %p", tsigkey);
4398 dns_tsigkey_detach(&tsigkey);
4399 }
4400 if (namebuf != NULL) {
4401 isc_buffer_free(&namebuf);
4402 }
4403
4404 if (is_dst_up) {
4405 debug("destroy DST lib");
4406 dst_lib_destroy();
4407 is_dst_up = false;
4408 }
4409
4410 UNLOCK_LOOKUP;
4411 isc_mutex_destroy(&lookup_lock);
4412 debug("Removing log context");
4413 isc_log_destroy(&lctx);
4414
4415 debug("Destroy memory");
4416 if (memdebugging != 0) {
4417 isc_mem_stats(mctx, stderr);
4418 }
4419 if (mctx != NULL) {
4420 isc_mem_destroy(&mctx);
4421 }
4422 }
4423
4424 #ifdef HAVE_LIBIDN2
4425 static isc_result_t
4426 idn_output_filter(isc_buffer_t *buffer, unsigned int used_org) {
4427 char src[MXNAME], *dst = NULL;
4428 size_t srclen, dstlen;
4429 isc_result_t result = ISC_R_SUCCESS;
4430
4431 /*
4432 * Copy name from 'buffer' to 'src' and terminate it with NULL.
4433 */
4434 srclen = isc_buffer_usedlength(buffer) - used_org;
4435 if (srclen >= sizeof(src)) {
4436 warn("Input name too long to perform IDN conversion");
4437 goto cleanup;
4438 }
4439 memmove(src, (char *)isc_buffer_base(buffer) + used_org, srclen);
4440 src[srclen] = '\0';
4441
4442 systemlocale(LC_ALL);
4443
4444 /*
4445 * Convert 'src' to the current locale's character encoding.
4446 */
4447 idn_ace_to_locale(src, &dst);
4448
4449 resetlocale(LC_ALL);
4450
4451 /*
4452 * Check whether the converted name will fit back into 'buffer'.
4453 */
4454 dstlen = strlen(dst);
4455 if (isc_buffer_length(buffer) < used_org + dstlen) {
4456 result = ISC_R_NOSPACE;
4457 goto cleanup;
4458 }
4459
4460 /*
4461 * Put the converted name back into 'buffer'.
4462 */
4463 isc_buffer_subtract(buffer, srclen);
4464 memmove(isc_buffer_used(buffer), dst, dstlen);
4465 isc_buffer_add(buffer, dstlen);
4466
4467 /*
4468 * Clean up.
4469 */
4470 cleanup:
4471 if (dst != NULL) {
4472 idn2_free(dst);
4473 }
4474
4475 return (result);
4476 }
4477
4478 /*%
4479 * Convert 'src', which is a string using the current locale's character
4480 * encoding, into an ACE string suitable for use in the DNS, storing the
4481 * conversion result in 'dst', which is 'dstlen' bytes large.
4482 *
4483 * 'dst' MUST be large enough to hold any valid domain name.
4484 */
4485 static void
4486 idn_locale_to_ace(const char *src, char *dst, size_t dstlen) {
4487 const char *final_src;
4488 char *ascii_src;
4489 int res;
4490
4491 systemlocale(LC_ALL);
4492
4493 /*
4494 * We trust libidn2 to return an error if 'src' is too large to be a
4495 * valid domain name.
4496 */
4497 res = idn2_to_ascii_lz(src, &ascii_src, IDN2_NONTRANSITIONAL);
4498 if (res == IDN2_DISALLOWED) {
4499 res = idn2_to_ascii_lz(src, &ascii_src, IDN2_TRANSITIONAL);
4500 }
4501 if (res != IDN2_OK) {
4502 fatal("'%s' is not a legal IDNA2008 name (%s), use +noidnin",
4503 src, idn2_strerror(res));
4504 }
4505
4506 /*
4507 * idn2_to_ascii_lz() normalizes all strings to lower case, but we
4508 * generally don't want to lowercase all input strings; make sure to
4509 * return the original case if the two strings differ only in case.
4510 */
4511 final_src = (strcasecmp(src, ascii_src) == 0 ? src : ascii_src);
4512
4513 (void)strlcpy(dst, final_src, dstlen);
4514
4515 idn2_free(ascii_src);
4516
4517 resetlocale(LC_ALL);
4518 }
4519
4520 /*%
4521 * Convert 'src', which is an ACE string suitable for use in the DNS, into a
4522 * string using the current locale's character encoding, storing the conversion
4523 * result in 'dst'.
4524 *
4525 * The caller MUST subsequently release 'dst' using idn2_free().
4526 */
4527 static void
4528 idn_ace_to_locale(const char *src, char **dst) {
4529 char *local_src, *utf8_src;
4530 int res;
4531
4532 systemlocale(LC_ALL);
4533
4534 /*
4535 * We need to:
4536 *
4537 * 1) check whether 'src' is a valid IDNA2008 name,
4538 * 2) if it is, output it in the current locale's character encoding.
4539 *
4540 * Unlike idn2_to_ascii_*(), idn2_to_unicode_*() functions are unable
4541 * to perform IDNA2008 validity checks. Thus, we need to decode any
4542 * Punycode in 'src', check if the resulting name is a valid IDNA2008
4543 * name, and only once we ensure it is, output that name in the current
4544 * locale's character encoding.
4545 *
4546 * We could just use idn2_to_unicode_8zlz() + idn2_to_ascii_lz(), but
4547 * then we would not be able to universally tell invalid names and
4548 * character encoding errors apart (if the current locale uses ASCII
4549 * for character encoding, the former function would fail even for a
4550 * valid IDNA2008 name, as long as it contained any non-ASCII
4551 * character). Thus, we need to take a longer route.
4552 *
4553 * First, convert 'src' to UTF-8, ignoring the current locale.
4554 */
4555 res = idn2_to_unicode_8z8z(src, &utf8_src, 0);
4556 if (res != IDN2_OK) {
4557 fatal("Bad ACE string '%s' (%s), use +noidnout", src,
4558 idn2_strerror(res));
4559 }
4560
4561 /*
4562 * Then, check whether decoded 'src' is a valid IDNA2008 name
4563 * and if disallowed character is found, fallback to IDNA2003.
4564 */
4565 res = idn2_to_ascii_8z(utf8_src, NULL, IDN2_NONTRANSITIONAL);
4566 if (res == IDN2_DISALLOWED) {
4567 res = idn2_to_ascii_8z(utf8_src, NULL, IDN2_TRANSITIONAL);
4568 }
4569 if (res != IDN2_OK) {
4570 fatal("'%s' is not a legal IDNA2008 name (%s), use +noidnout",
4571 src, idn2_strerror(res));
4572 }
4573
4574 /*
4575 * Finally, try converting the decoded 'src' into the current locale's
4576 * character encoding.
4577 */
4578 res = idn2_to_unicode_8zlz(utf8_src, &local_src, 0);
4579 if (res != IDN2_OK) {
4580 static bool warned = false;
4581
4582 res = idn2_to_ascii_8z(utf8_src, &local_src, 0);
4583 if (res != IDN2_OK) {
4584 fatal("Cannot represent '%s' "
4585 "in the current locale nor ascii (%s), "
4586 "use +noidnout or a different locale",
4587 src, idn2_strerror(res));
4588 } else if (!warned) {
4589 fprintf(stderr,
4590 ";; Warning: cannot represent '%s' "
4591 "in the current locale",
4592 local_src);
4593 warned = true;
4594 }
4595 }
4596
4597 /*
4598 * Free the interim conversion result.
4599 */
4600 idn2_free(utf8_src);
4601
4602 *dst = local_src;
4603
4604 resetlocale(LC_ALL);
4605 }
4606 #endif /* HAVE_LIBIDN2 */
4607