1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 /* $Id: dighost.c,v 1.40 2024/12/27 09:04:48 florian Exp $ */
18
19 /*! \file
20 * \note
21 * Notice to programmers: Do not use this code as an example of how to
22 * use the ISC library to perform DNS lookups. Dig and Host both operate
23 * on the request level, since they allow fine-tuning of output and are
24 * intended as debugging tools. As a result, they perform many of the
25 * functions which could be better handled using the dns_resolver
26 * functions in most applications.
27 */
28
29 #include <sys/socket.h>
30 #include <sys/time.h>
31 #include <limits.h>
32 #include <locale.h>
33 #include <netdb.h>
34 #include <resolv.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <time.h>
38 #include <stdint.h>
39
40 #include <dns/fixedname.h>
41 #include <dns/log.h>
42 #include <dns/message.h>
43 #include <dns/name.h>
44 #include <dns/rdata.h>
45 #include <dns/rdataclass.h>
46 #include <dns/rdatalist.h>
47 #include <dns/rdataset.h>
48 #include <dns/rdatatype.h>
49 #include <dns/result.h>
50 #include <dns/tsig.h>
51
52 #include <dst/dst.h>
53 #include <dst/result.h>
54
55 #include <isc/base64.h>
56 #include <isc/hex.h>
57 #include <isc/log.h>
58 #include <isc/result.h>
59 #include <isc/serial.h>
60 #include <isc/sockaddr.h>
61 #include <isc/task.h>
62 #include <isc/timer.h>
63 #include <isc/types.h>
64 #include <isc/util.h>
65
66 #include <isccfg/namedconf.h>
67 #include <lwres/lwres.h>
68
69 #include "dig.h"
70
71 static lwres_conf_t lwconfdata;
72 static lwres_conf_t *lwconf = &lwconfdata;
73
74 dig_lookuplist_t lookup_list;
75 dig_serverlist_t server_list;
76 dig_serverlist_t root_hints_server_list;
77 dig_searchlistlist_t search_list;
78
79 int
80 check_ra = 0,
81 have_ipv4 = 1,
82 have_ipv6 = 1,
83 specified_source = 0,
84 free_now = 0,
85 cancel_now = 0,
86 usesearch = 0,
87 showsearch = 0,
88 qr = 0,
89 is_dst_up = 0,
90 keep_open = 0;
91 in_port_t port = 53;
92 unsigned int timeout = 0;
93 unsigned int extrabytes;
94 isc_log_t *lctx = NULL;
95 isc_taskmgr_t *taskmgr = NULL;
96 isc_task_t *global_task = NULL;
97 isc_timermgr_t *timermgr = NULL;
98 isc_socketmgr_t *socketmgr = NULL;
99 struct sockaddr_storage bind_address;
100 struct sockaddr_storage bind_any;
101 int sendcount = 0;
102 int recvcount = 0;
103 int sockcount = 0;
104 int ndots = -1;
105 int tries = 3;
106 int lookup_counter = 0;
107
108 static char sitvalue[256];
109
110 isc_socket_t *keep = NULL;
111 struct sockaddr_storage keepaddr;
112
113 static const struct {
114 const char *ns;
115 const int af;
116 } root_hints[] = {
117 { "198.41.0.4", AF_INET }, /* a.root-servers.net */
118 { "2001:503:ba3e::2:30", AF_INET6 }, /* a.root-servers.net */
119 { "170.247.170.2", AF_INET }, /* b.root-servers.net */
120 { "2801:1b8:10::b", AF_INET6 }, /* b.root-servers.net */
121 { "192.33.4.12", AF_INET }, /* c.root-servers.net */
122 { "2001:500:2::c", AF_INET6 }, /* c.root-servers.net */
123 { "199.7.91.13", AF_INET }, /* d.root-servers.net */
124 { "2001:500:2d::d", AF_INET6 }, /* d.root-servers.net */
125 { "192.203.230.10", AF_INET }, /* e.root-servers.net */
126 { "2001:500:a8::e", AF_INET6 }, /* e.root-servers.net */
127 { "192.5.5.241", AF_INET }, /* f.root-servers.net */
128 { "2001:500:2f::f", AF_INET6 }, /* f.root-servers.net */
129 { "192.112.36.4", AF_INET }, /* g.root-servers.net */
130 { "2001:500:12::d0d", AF_INET6 }, /* g.root-servers.net */
131 { "198.97.190.53", AF_INET }, /* h.root-servers.net */
132 { "2001:500:1::53", AF_INET6 }, /* h.root-servers.net */
133 { "192.36.148.17", AF_INET }, /* i.root-servers.net */
134 { "2001:7fe::53", AF_INET6 }, /* i.root-servers.net */
135 { "192.58.128.30", AF_INET }, /* j.root-servers.net */
136 { "2001:503:c27::2:30", AF_INET6 }, /* j.root-servers.net */
137 { "193.0.14.129", AF_INET }, /* k.root-servers.net */
138 { "2001:7fd::1", AF_INET6 }, /* k.root-servers.net */
139 { "199.7.83.42", AF_INET }, /* l.root-servers.net */
140 { "2001:500:9f::42", AF_INET6 }, /* l.root-servers.net */
141 { "202.12.27.33", AF_INET }, /* m.root-servers.net */
142 { "2001:dc3::35", AF_INET6 } /* m.root-servers.net */
143 };
144
145 /*%
146 * Exit Codes:
147 *
148 *\li 0 Everything went well, including things like NXDOMAIN
149 *\li 1 Usage error
150 *\li 7 Got too many RR's or Names
151 *\li 8 Couldn't open batch file
152 *\li 9 No reply from server
153 *\li 10 Internal error
154 */
155 int exitcode = 0;
156 int fatalexit = 0;
157 char keynametext[MXNAME];
158 char keyfile[MXNAME] = "";
159 char keysecret[MXNAME] = "";
160 unsigned char cookie_secret[33];
161 unsigned char cookie[8];
162 dns_name_t *hmacname = NULL;
163 unsigned int digestbits = 0;
164 isc_buffer_t *namebuf = NULL;
165 dns_tsigkey_t *tsigkey = NULL;
166 int validated = 1;
167 int debugging = 0;
168 int debugtiming = 0;
169 char *progname = NULL;
170 dig_lookup_t *current_lookup = NULL;
171
172 #define DIG_MAX_ADDRESSES 20
173
174 /* dynamic callbacks */
175
176 isc_result_t
177 (*dighost_printmessage)(dig_query_t *query, dns_message_t *msg,
178 int headers);
179
180 void
181 (*dighost_received)(unsigned int bytes, struct sockaddr_storage *from, dig_query_t *query);
182
183 void
184 (*dighost_trying)(char *frm, dig_lookup_t *lookup);
185
186 void
187 (*dighost_shutdown)(void);
188
189 /* forward declarations */
190
191 static void
192 cancel_lookup(dig_lookup_t *lookup);
193
194 static void
195 recv_done(isc_task_t *task, isc_event_t *event);
196
197 static void
198 send_udp(dig_query_t *query);
199
200 static void
201 connect_timeout(isc_task_t *task, isc_event_t *event);
202
203 static void
204 launch_next_query(dig_query_t *query, int include_question);
205
206 static void
207 check_next_lookup(dig_lookup_t *lookup);
208
209 static int
210 next_origin(dig_lookup_t *oldlookup);
211
212 char *
next_token(char ** stringp,const char * delim)213 next_token(char **stringp, const char *delim) {
214 char *res;
215
216 do {
217 res = strsep(stringp, delim);
218 if (res == NULL)
219 break;
220 } while (*res == '\0');
221 return (res);
222 }
223
224 static int
count_dots(char * string)225 count_dots(char *string) {
226 char *s;
227 int i = 0;
228
229 s = string;
230 while (*s != '\0') {
231 if (*s == '.')
232 i++;
233 s++;
234 }
235 return (i);
236 }
237
238 static void
hex_dump(isc_buffer_t * b)239 hex_dump(isc_buffer_t *b) {
240 unsigned int len, i;
241 isc_region_t r;
242
243 isc_buffer_usedregion(b, &r);
244
245 printf("%u bytes\n", r.length);
246 for (len = 0; len < r.length; len++) {
247 printf("%02x ", r.base[len]);
248 if (len % 16 == 15) {
249 fputs(" ", stdout);
250 for (i = len - 15; i <= len; i++) {
251 if (r.base[i] >= '!' && r.base[i] <= '}')
252 putchar(r.base[i]);
253 else
254 putchar('.');
255 }
256 printf("\n");
257 }
258 }
259 if (len % 16 != 0) {
260 for (i = len; (i % 16) != 0; i++)
261 fputs(" ", stdout);
262 fputs(" ", stdout);
263 for (i = ((len>>4)<<4); i < len; i++) {
264 if (r.base[i] >= '!' && r.base[i] <= '}')
265 putchar(r.base[i]);
266 else
267 putchar('.');
268 }
269 printf("\n");
270 }
271 }
272
273 /*%
274 * Append 'len' bytes of 'text' at '*p', failing with
275 * ISC_R_NOSPACE if that would advance p past 'end'.
276 */
277 static isc_result_t
append(const char * text,size_t len,char ** p,char * end)278 append(const char *text, size_t len, char **p, char *end) {
279 if (*p + len > end)
280 return (ISC_R_NOSPACE);
281 memmove(*p, text, len);
282 *p += len;
283 return (ISC_R_SUCCESS);
284 }
285
286 static isc_result_t
reverse_octets(const char * in,char ** p,char * end)287 reverse_octets(const char *in, char **p, char *end) {
288 const char *dot = strchr(in, '.');
289 size_t len;
290 if (dot != NULL) {
291 isc_result_t result;
292 result = reverse_octets(dot + 1, p, end);
293 if (result != ISC_R_SUCCESS)
294 return (result);
295 result = append(".", 1, p, end);
296 if (result != ISC_R_SUCCESS)
297 return (result);
298 len = (int) (dot - in);
299 } else {
300 len = (int) strlen(in);
301 }
302 return (append(in, len, p, end));
303 }
304
305 isc_result_t
get_reverse(char * reverse,size_t len,char * value,int ip6_int,int strict)306 get_reverse(char *reverse, size_t len, char *value, int ip6_int,
307 int strict)
308 {
309 int r;
310 struct in_addr in;
311 struct in6_addr in6;
312 isc_result_t result;
313
314 r = inet_pton(AF_INET6, value, &in6);
315 if (r > 0) {
316 /* This is a valid IPv6 address. */
317 static char hex_digits[] = {
318 '0', '1', '2', '3', '4', '5', '6', '7',
319 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
320 };
321 int i;
322 unsigned char *bytes = (unsigned char *)&in6;
323 char* cp;
324
325 if (len <= 15 * 4 + sizeof("ip6.int"))
326 return (ISC_R_NOMEMORY);
327
328 cp = reverse;
329 for (i = 15; i >= 0; i--) {
330 *cp++ = hex_digits[bytes[i] & 0x0f];
331 *cp++ = '.';
332 *cp++ = hex_digits[(bytes[i] >> 4) & 0x0f];
333 *cp++ = '.';
334 }
335 *cp = '\0';
336 if (strlcat(reverse, ip6_int ? "ip6.int" : "ip6.arpa", len)
337 >= len)
338 return (ISC_R_NOSPACE);
339 return (ISC_R_SUCCESS);
340 } else {
341 /*
342 * Not a valid IPv6 address. Assume IPv4.
343 * If 'strict' is not set, construct the
344 * in-addr.arpa name by blindly reversing
345 * octets whether or not they look like integers,
346 * so that this can be used for RFC2317 names
347 * and such.
348 */
349 char *p = reverse;
350 char *end = reverse + len;
351 if (strict && inet_pton(AF_INET, value, &in) != 1)
352 return (DNS_R_BADDOTTEDQUAD);
353 result = reverse_octets(value, &p, end);
354 if (result != ISC_R_SUCCESS)
355 return (result);
356 /* Append .in-addr.arpa. and a terminating NUL. */
357 result = append(".in-addr.arpa.", 15, &p, end);
358 return (result);
359 }
360 }
361
362 void
fatal(const char * format,...)363 fatal(const char *format, ...) {
364 va_list args;
365
366 fflush(stdout);
367 fprintf(stderr, "%s: ", progname);
368 va_start(args, format);
369 vfprintf(stderr, format, args);
370 va_end(args);
371 fprintf(stderr, "\n");
372 if (exitcode < 10)
373 exitcode = 10;
374 if (fatalexit != 0)
375 exitcode = fatalexit;
376 exit(exitcode);
377 }
378
379 void
debug(const char * format,...)380 debug(const char *format, ...) {
381 va_list args;
382 struct timespec t;
383
384 if (debugging) {
385 fflush(stdout);
386 if (debugtiming) {
387 clock_gettime(CLOCK_MONOTONIC, &t);
388 fprintf(stderr, "%lld.%06ld: ", t.tv_sec, t.tv_nsec /
389 1000);
390 }
391 va_start(args, format);
392 vfprintf(stderr, format, args);
393 va_end(args);
394 fprintf(stderr, "\n");
395 }
396 }
397
398 void
check_result(isc_result_t result,const char * msg)399 check_result(isc_result_t result, const char *msg) {
400 if (result != ISC_R_SUCCESS) {
401 fatal("%s: %s", msg, isc_result_totext(result));
402 }
403 }
404
405 /*%
406 * Create a server structure, which is part of the lookup structure.
407 * This is little more than a linked list of servers to query in hopes
408 * of finding the answer the user is looking for
409 */
410 dig_server_t *
make_server(const char * servname,const char * userarg)411 make_server(const char *servname, const char *userarg) {
412 dig_server_t *srv;
413
414 REQUIRE(servname != NULL);
415
416 debug("make_server(%s)", servname);
417 srv = malloc(sizeof(struct dig_server));
418 if (srv == NULL)
419 fatal("memory allocation failure in %s:%d",
420 __FILE__, __LINE__);
421 strlcpy(srv->servername, servname, MXNAME);
422 strlcpy(srv->userarg, userarg, MXNAME);
423 ISC_LINK_INIT(srv, link);
424 return (srv);
425 }
426
427 static int
addr2af(int lwresaddrtype)428 addr2af(int lwresaddrtype)
429 {
430 int af = 0;
431
432 switch (lwresaddrtype) {
433 case LWRES_ADDRTYPE_V4:
434 af = AF_INET;
435 break;
436
437 case LWRES_ADDRTYPE_V6:
438 af = AF_INET6;
439 break;
440 }
441
442 return (af);
443 }
444
445 /*%
446 * Create a copy of the server list from the lwres configuration structure.
447 * The dest list must have already had ISC_LIST_INIT applied.
448 */
449 static void
copy_server_list(lwres_conf_t * confdata,dig_serverlist_t * dest)450 copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) {
451 dig_server_t *newsrv;
452 char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") +
453 sizeof("%4000000000")];
454 int af;
455 int i;
456
457 debug("copy_server_list()");
458 for (i = 0; i < confdata->nsnext; i++) {
459 af = addr2af(confdata->nameservers[i].family);
460
461 if (af == AF_INET && !have_ipv4)
462 continue;
463 if (af == AF_INET6 && !have_ipv6)
464 continue;
465
466 inet_ntop(af, confdata->nameservers[i].address,
467 tmp, sizeof(tmp));
468 if (af == AF_INET6 && confdata->nameservers[i].zone != 0) {
469 char buf[sizeof("%4000000000")];
470 snprintf(buf, sizeof(buf), "%%%u",
471 confdata->nameservers[i].zone);
472 strlcat(tmp, buf, sizeof(tmp));
473 }
474 newsrv = make_server(tmp, tmp);
475 ISC_LINK_INIT(newsrv, link);
476 ISC_LIST_ENQUEUE(*dest, newsrv, link);
477 }
478 }
479
480 void
flush_server_list(void)481 flush_server_list(void) {
482 dig_server_t *s, *ps;
483
484 debug("flush_server_list()");
485 s = ISC_LIST_HEAD(server_list);
486 while (s != NULL) {
487 ps = s;
488 s = ISC_LIST_NEXT(s, link);
489 ISC_LIST_DEQUEUE(server_list, ps, link);
490 free(ps);
491 }
492 }
493
494 /* this used to be bind9_getaddresses from lib/bind9 */
495 static isc_result_t
get_addresses(const char * hostname,in_port_t dstport,struct sockaddr_storage * addrs,int addrsize,int * addrcount)496 get_addresses(const char *hostname, in_port_t dstport,
497 struct sockaddr_storage *addrs, int addrsize, int *addrcount)
498 {
499 struct addrinfo *ai = NULL, *tmpai, hints;
500 int result, i;
501 char dport[sizeof("65535")];
502
503 REQUIRE(hostname != NULL);
504 REQUIRE(addrs != NULL);
505 REQUIRE(addrcount != NULL);
506 REQUIRE(addrsize > 0);
507
508 memset(&hints, 0, sizeof(hints));
509 if (!have_ipv6)
510 hints.ai_family = PF_INET;
511 else if (!have_ipv4)
512 hints.ai_family = PF_INET6;
513 else {
514 hints.ai_family = PF_UNSPEC;
515 hints.ai_flags = AI_ADDRCONFIG;
516 }
517 hints.ai_socktype = SOCK_DGRAM;
518
519 snprintf(dport, sizeof(dport), "%d", dstport);
520 result = getaddrinfo(hostname, dport, &hints, &ai);
521 switch (result) {
522 case 0:
523 break;
524 case EAI_NONAME:
525 case EAI_NODATA:
526 return (ISC_R_NOTFOUND);
527 default:
528 return (ISC_R_FAILURE);
529 }
530 for (tmpai = ai, i = 0;
531 tmpai != NULL && i < addrsize;
532 tmpai = tmpai->ai_next)
533 {
534 if (tmpai->ai_family != AF_INET &&
535 tmpai->ai_family != AF_INET6)
536 continue;
537 if (tmpai->ai_addrlen > sizeof(addrs[i]))
538 continue;
539 memset(&addrs[i], 0, sizeof(addrs[i]));
540 memcpy(&addrs[i], tmpai->ai_addr, tmpai->ai_addrlen);
541 i++;
542
543 }
544 freeaddrinfo(ai);
545 *addrcount = i;
546 if (*addrcount == 0)
547 return (ISC_R_NOTFOUND);
548 else
549 return (ISC_R_SUCCESS);
550 }
551
552 isc_result_t
set_nameserver(char * opt)553 set_nameserver(char *opt) {
554 isc_result_t result;
555 struct sockaddr_storage sockaddrs[DIG_MAX_ADDRESSES];
556 int count, i;
557 dig_server_t *srv;
558 char tmp[NI_MAXHOST];
559
560 if (opt == NULL)
561 return ISC_R_NOTFOUND;
562
563 result = get_addresses(opt, 0, sockaddrs,
564 DIG_MAX_ADDRESSES, &count);
565 if (result != ISC_R_SUCCESS)
566 return (result);
567
568 flush_server_list();
569
570 for (i = 0; i < count; i++) {
571 int error;
572 error = getnameinfo((struct sockaddr *)&sockaddrs[i],
573 sockaddrs[i].ss_len, tmp, sizeof(tmp), NULL, 0,
574 NI_NUMERICHOST | NI_NUMERICSERV);
575 if (error)
576 fatal("%s", gai_strerror(error));
577 srv = make_server(tmp, opt);
578 if (srv == NULL)
579 fatal("memory allocation failure");
580 ISC_LIST_APPEND(server_list, srv, link);
581 }
582 return (ISC_R_SUCCESS);
583 }
584
585 static isc_result_t
add_nameserver(lwres_conf_t * confdata,const char * addr,int af)586 add_nameserver(lwres_conf_t *confdata, const char *addr, int af) {
587
588 int i = confdata->nsnext;
589
590 if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS)
591 return (ISC_R_FAILURE);
592
593 switch (af) {
594 case AF_INET:
595 confdata->nameservers[i].family = LWRES_ADDRTYPE_V4;
596 confdata->nameservers[i].length = sizeof(struct in_addr);
597 break;
598 case AF_INET6:
599 confdata->nameservers[i].family = LWRES_ADDRTYPE_V6;
600 confdata->nameservers[i].length = sizeof(struct in6_addr);
601 break;
602 default:
603 return (ISC_R_FAILURE);
604 }
605
606 if (inet_pton(af, addr, &confdata->nameservers[i].address) == 1) {
607 confdata->nsnext++;
608 return (ISC_R_SUCCESS);
609 }
610 return (ISC_R_FAILURE);
611 }
612
613 /*%
614 * Produce a cloned server list. The dest list must have already had
615 * ISC_LIST_INIT applied.
616 */
617 void
clone_server_list(dig_serverlist_t src,dig_serverlist_t * dest)618 clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
619 dig_server_t *srv, *newsrv;
620
621 debug("clone_server_list()");
622 srv = ISC_LIST_HEAD(src);
623 while (srv != NULL) {
624 newsrv = make_server(srv->servername, srv->userarg);
625 ISC_LINK_INIT(newsrv, link);
626 ISC_LIST_ENQUEUE(*dest, newsrv, link);
627 srv = ISC_LIST_NEXT(srv, link);
628 }
629 }
630
631 /*%
632 * Create an empty lookup structure, which holds all the information needed
633 * to get an answer to a user's question. This structure contains two
634 * linked lists: the server list (servers to query) and the query list
635 * (outstanding queries which have been made to the listed servers).
636 */
637 dig_lookup_t *
make_empty_lookup(void)638 make_empty_lookup(void) {
639 dig_lookup_t *looknew;
640
641 debug("make_empty_lookup()");
642
643 INSIST(!free_now);
644
645 looknew = malloc(sizeof(struct dig_lookup));
646 if (looknew == NULL)
647 fatal("memory allocation failure in %s:%d",
648 __FILE__, __LINE__);
649 looknew->pending = 1;
650 looknew->textname[0] = 0;
651 looknew->cmdline[0] = 0;
652 looknew->rdtype = dns_rdatatype_a;
653 looknew->qrdtype = dns_rdatatype_a;
654 looknew->rdclass = dns_rdataclass_in;
655 looknew->rdtypeset = 0;
656 looknew->rdclassset = 0;
657 looknew->sendspace = NULL;
658 looknew->sendmsg = NULL;
659 looknew->name = NULL;
660 looknew->oname = NULL;
661 looknew->xfr_q = NULL;
662 looknew->current_query = NULL;
663 looknew->doing_xfr = 0;
664 looknew->ixfr_serial = 0;
665 looknew->trace = 0;
666 looknew->trace_root = 0;
667 looknew->identify = 0;
668 looknew->identify_previous_line = 0;
669 looknew->ignore = 0;
670 looknew->servfail_stops = 1;
671 looknew->besteffort = 1;
672 looknew->dnssec = 0;
673 looknew->ednsflags = 0;
674 looknew->opcode = dns_opcode_query;
675 looknew->expire = 0;
676 looknew->nsid = 0;
677 looknew->idnout = 0;
678 looknew->sit = 0;
679 looknew->udpsize = 0;
680 looknew->edns = -1;
681 looknew->recurse = 1;
682 looknew->aaonly = 0;
683 looknew->adflag = 0;
684 looknew->cdflag = 0;
685 looknew->ns_search_only = 0;
686 looknew->origin = NULL;
687 looknew->tsigctx = NULL;
688 looknew->querysig = NULL;
689 looknew->retries = tries;
690 looknew->nsfound = 0;
691 looknew->tcp_mode = 0;
692 looknew->tcp_mode_set = 0;
693 looknew->ip6_int = 0;
694 looknew->comments = 1;
695 looknew->stats = 1;
696 looknew->section_question = 1;
697 looknew->section_answer = 1;
698 looknew->section_authority = 1;
699 looknew->section_additional = 1;
700 looknew->new_search = 0;
701 looknew->done_as_is = 0;
702 looknew->need_search = 0;
703 looknew->ecs_addr = NULL;
704 looknew->ecs_plen = 0;
705 looknew->sitvalue = NULL;
706 looknew->ednsopts = NULL;
707 looknew->ednsoptscnt = 0;
708 looknew->ednsneg = 0;
709 looknew->eoferr = 0;
710 dns_fixedname_init(&looknew->fdomain);
711 ISC_LINK_INIT(looknew, link);
712 ISC_LIST_INIT(looknew->q);
713 ISC_LIST_INIT(looknew->connecting);
714 ISC_LIST_INIT(looknew->my_server_list);
715 return (looknew);
716 }
717
718 #define EDNSOPT_OPTIONS 100U
719
720 static void
cloneopts(dig_lookup_t * looknew,dig_lookup_t * lookold)721 cloneopts(dig_lookup_t *looknew, dig_lookup_t *lookold) {
722 size_t len = sizeof(looknew->ednsopts[0]) * EDNSOPT_OPTIONS;
723 size_t i;
724 looknew->ednsopts = malloc(len);
725 if (looknew->ednsopts == NULL)
726 fatal("out of memory");
727 for (i = 0; i < EDNSOPT_OPTIONS; i++) {
728 looknew->ednsopts[i].code = 0;
729 looknew->ednsopts[i].length = 0;
730 looknew->ednsopts[i].value = NULL;
731 }
732 looknew->ednsoptscnt = 0;
733 if (lookold == NULL || lookold->ednsopts == NULL)
734 return;
735
736 for (i = 0; i < lookold->ednsoptscnt; i++) {
737 len = lookold->ednsopts[i].length;
738 if (len != 0) {
739 INSIST(lookold->ednsopts[i].value != NULL);
740 looknew->ednsopts[i].value =
741 malloc(len);
742 if (looknew->ednsopts[i].value == NULL)
743 fatal("out of memory");
744 memmove(looknew->ednsopts[i].value,
745 lookold->ednsopts[i].value, len);
746 }
747 looknew->ednsopts[i].code = lookold->ednsopts[i].code;
748 looknew->ednsopts[i].length = len;
749 }
750 looknew->ednsoptscnt = lookold->ednsoptscnt;
751 }
752
753 /*%
754 * Clone a lookup, perhaps copying the server list. This does not clone
755 * the query list, since it will be regenerated by the setup_lookup()
756 * function, nor does it queue up the new lookup for processing.
757 * Caution: If you don't clone the servers, you MUST clone the server
758 * list separately from somewhere else, or construct it by hand.
759 */
760 dig_lookup_t *
clone_lookup(dig_lookup_t * lookold,int servers)761 clone_lookup(dig_lookup_t *lookold, int servers) {
762 dig_lookup_t *looknew;
763
764 debug("clone_lookup()");
765
766 INSIST(!free_now);
767
768 looknew = make_empty_lookup();
769 INSIST(looknew != NULL);
770 strlcpy(looknew->textname, lookold->textname, MXNAME);
771 strlcpy(looknew->cmdline, lookold->cmdline, MXNAME);
772 looknew->textname[MXNAME-1] = 0;
773 looknew->rdtype = lookold->rdtype;
774 looknew->qrdtype = lookold->qrdtype;
775 looknew->rdclass = lookold->rdclass;
776 looknew->rdtypeset = lookold->rdtypeset;
777 looknew->rdclassset = lookold->rdclassset;
778 looknew->doing_xfr = lookold->doing_xfr;
779 looknew->ixfr_serial = lookold->ixfr_serial;
780 looknew->trace = lookold->trace;
781 looknew->trace_root = lookold->trace_root;
782 looknew->identify = lookold->identify;
783 looknew->identify_previous_line = lookold->identify_previous_line;
784 looknew->ignore = lookold->ignore;
785 looknew->servfail_stops = lookold->servfail_stops;
786 looknew->besteffort = lookold->besteffort;
787 looknew->dnssec = lookold->dnssec;
788 looknew->ednsflags = lookold->ednsflags;
789 looknew->opcode = lookold->opcode;
790 looknew->expire = lookold->expire;
791 looknew->nsid = lookold->nsid;
792 looknew->sit = lookold->sit;
793 looknew->sitvalue = lookold->sitvalue;
794 if (lookold->ednsopts != NULL) {
795 cloneopts(looknew, lookold);
796 } else {
797 looknew->ednsopts = NULL;
798 looknew->ednsoptscnt = 0;
799 }
800 looknew->ednsneg = lookold->ednsneg;
801 looknew->idnout = lookold->idnout;
802 looknew->udpsize = lookold->udpsize;
803 looknew->edns = lookold->edns;
804 looknew->recurse = lookold->recurse;
805 looknew->aaonly = lookold->aaonly;
806 looknew->adflag = lookold->adflag;
807 looknew->cdflag = lookold->cdflag;
808 looknew->ns_search_only = lookold->ns_search_only;
809 looknew->tcp_mode = lookold->tcp_mode;
810 looknew->tcp_mode_set = lookold->tcp_mode_set;
811 looknew->comments = lookold->comments;
812 looknew->stats = lookold->stats;
813 looknew->section_question = lookold->section_question;
814 looknew->section_answer = lookold->section_answer;
815 looknew->section_authority = lookold->section_authority;
816 looknew->section_additional = lookold->section_additional;
817 looknew->origin = lookold->origin;
818 looknew->retries = lookold->retries;
819 looknew->tsigctx = NULL;
820 looknew->need_search = lookold->need_search;
821 looknew->done_as_is = lookold->done_as_is;
822 looknew->eoferr = lookold->eoferr;
823
824 if (lookold->ecs_addr != NULL) {
825 size_t len = sizeof(struct sockaddr_storage);
826 looknew->ecs_addr = malloc(len);
827 if (looknew->ecs_addr == NULL)
828 fatal("out of memory");
829 memmove(looknew->ecs_addr, lookold->ecs_addr, len);
830 looknew->ecs_plen = lookold->ecs_plen;
831 }
832
833 dns_name_copy(dns_fixedname_name(&lookold->fdomain),
834 dns_fixedname_name(&looknew->fdomain), NULL);
835
836 if (servers)
837 clone_server_list(lookold->my_server_list,
838 &looknew->my_server_list);
839 return (looknew);
840 }
841
842 /*%
843 * Requeue a lookup for further processing, perhaps copying the server
844 * list. The new lookup structure is returned to the caller, and is
845 * queued for processing. If servers are not cloned in the requeue, they
846 * must be added before allowing the current event to complete, since the
847 * completion of the event may result in the next entry on the lookup
848 * queue getting run.
849 */
850 dig_lookup_t *
requeue_lookup(dig_lookup_t * lookold,int servers)851 requeue_lookup(dig_lookup_t *lookold, int servers) {
852 dig_lookup_t *looknew;
853
854 debug("requeue_lookup()");
855
856 lookup_counter++;
857 if (lookup_counter > LOOKUP_LIMIT)
858 fatal("too many lookups");
859
860 looknew = clone_lookup(lookold, servers);
861 INSIST(looknew != NULL);
862
863 debug("before insertion, init@%p -> %p, new@%p -> %p",
864 lookold, lookold->link.next, looknew, looknew->link.next);
865 ISC_LIST_PREPEND(lookup_list, looknew, link);
866 debug("after insertion, init -> %p, new = %p, new -> %p",
867 lookold, looknew, looknew->link.next);
868 return (looknew);
869 }
870
871 void
setup_text_key(void)872 setup_text_key(void) {
873 isc_result_t result;
874 dns_name_t keyname;
875 isc_buffer_t secretbuf;
876 unsigned int secretsize;
877 unsigned char *secretstore;
878
879 debug("setup_text_key()");
880 result = isc_buffer_allocate(&namebuf, MXNAME);
881 check_result(result, "isc_buffer_allocate");
882 dns_name_init(&keyname, NULL);
883 check_result(result, "dns_name_init");
884 isc_buffer_putstr(namebuf, keynametext);
885 secretsize = (unsigned int) strlen(keysecret) * 3 / 4;
886 secretstore = malloc(secretsize);
887 if (secretstore == NULL)
888 fatal("memory allocation failure in %s:%d",
889 __FILE__, __LINE__);
890 isc_buffer_init(&secretbuf, secretstore, secretsize);
891 result = isc_base64_decodestring(keysecret, &secretbuf);
892 if (result != ISC_R_SUCCESS)
893 goto failure;
894
895 secretsize = isc_buffer_usedlength(&secretbuf);
896
897 if (hmacname == NULL) {
898 result = DST_R_UNSUPPORTEDALG;
899 goto failure;
900 }
901
902 result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf);
903 if (result != ISC_R_SUCCESS)
904 goto failure;
905
906 result = dns_tsigkey_create(&keyname, hmacname, secretstore,
907 (int)secretsize, 0, NULL, 0, 0,
908 &tsigkey);
909 failure:
910 if (result != ISC_R_SUCCESS)
911 printf(";; Couldn't create key %s: %s\n",
912 keynametext, isc_result_totext(result));
913 else
914 dst_key_setbits(tsigkey->key, digestbits);
915
916 free(secretstore);
917 dns_name_invalidate(&keyname);
918 isc_buffer_free(&namebuf);
919 }
920
921 static uint32_t
parse_bits(char * arg,uint32_t max)922 parse_bits(char *arg, uint32_t max) {
923 uint32_t tmp;
924 const char *errstr;
925
926 tmp = strtonum(arg, 0, max, &errstr);
927 if (errstr != NULL)
928 fatal("digest bits is %s: '%s'", errstr, arg);
929 tmp = (tmp + 7) & ~0x7U;
930 return (tmp);
931 }
932
933 isc_result_t
parse_netprefix(struct sockaddr_storage ** sap,int * plen,const char * value)934 parse_netprefix(struct sockaddr_storage **sap, int *plen, const char *value) {
935 struct sockaddr_storage *sa = NULL;
936 struct in_addr *in4;
937 struct in6_addr *in6;
938 int prefix_length;
939
940 REQUIRE(sap != NULL && *sap == NULL);
941
942 sa = calloc(1, sizeof(*sa));
943 if (sa == NULL)
944 fatal("out of memory");
945
946 in4 = &((struct sockaddr_in *)sa)->sin_addr;
947 in6 = &((struct sockaddr_in6 *)sa)->sin6_addr;
948
949 if (strcmp(value, "0") == 0) {
950 sa->ss_family = AF_UNSPEC;
951 prefix_length = 0;
952 goto done;
953 }
954
955 if ((prefix_length = inet_net_pton(AF_INET6, value, in6, sizeof(*in6)))
956 != -1) {
957 sa->ss_len = sizeof(struct sockaddr_in6);
958 sa->ss_family = AF_INET6;
959 } else if ((prefix_length = inet_net_pton(AF_INET, value, in4,
960 sizeof(*in4))) != -1) {
961 sa->ss_len = sizeof(struct sockaddr_in);
962 sa->ss_family = AF_INET;
963 } else
964 fatal("invalid address '%s'", value);
965
966 done:
967 *plen = prefix_length;
968 *sap = sa;
969
970 return (ISC_R_SUCCESS);
971 }
972
973 /*
974 * Parse HMAC algorithm specification
975 */
976 void
parse_hmac(const char * hmac)977 parse_hmac(const char *hmac) {
978 char buf[20];
979 size_t len;
980
981 REQUIRE(hmac != NULL);
982
983 len = strlen(hmac);
984 if (len >= sizeof(buf))
985 fatal("unknown key type '%.*s'", (int)len, hmac);
986 strlcpy(buf, hmac, sizeof(buf));
987
988 digestbits = 0;
989
990 if (strcasecmp(buf, "hmac-sha1") == 0) {
991 hmacname = DNS_TSIG_HMACSHA1_NAME;
992 digestbits = 0;
993 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
994 hmacname = DNS_TSIG_HMACSHA1_NAME;
995 digestbits = parse_bits(&buf[10], 160);
996 } else if (strcasecmp(buf, "hmac-sha224") == 0) {
997 hmacname = DNS_TSIG_HMACSHA224_NAME;
998 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
999 hmacname = DNS_TSIG_HMACSHA224_NAME;
1000 digestbits = parse_bits(&buf[12], 224);
1001 } else if (strcasecmp(buf, "hmac-sha256") == 0) {
1002 hmacname = DNS_TSIG_HMACSHA256_NAME;
1003 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
1004 hmacname = DNS_TSIG_HMACSHA256_NAME;
1005 digestbits = parse_bits(&buf[12], 256);
1006 } else if (strcasecmp(buf, "hmac-sha384") == 0) {
1007 hmacname = DNS_TSIG_HMACSHA384_NAME;
1008 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
1009 hmacname = DNS_TSIG_HMACSHA384_NAME;
1010 digestbits = parse_bits(&buf[12], 384);
1011 } else if (strcasecmp(buf, "hmac-sha512") == 0) {
1012 hmacname = DNS_TSIG_HMACSHA512_NAME;
1013 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
1014 hmacname = DNS_TSIG_HMACSHA512_NAME;
1015 digestbits = parse_bits(&buf[12], 512);
1016 } else {
1017 fprintf(stderr, ";; Warning, ignoring "
1018 "invalid TSIG algorithm %s\n", buf);
1019 }
1020 }
1021
1022 /*
1023 * Get a key from a named.conf format keyfile
1024 */
1025 static isc_result_t
read_confkey(void)1026 read_confkey(void) {
1027 cfg_parser_t *pctx = NULL;
1028 cfg_obj_t *file = NULL;
1029 const cfg_obj_t *keyobj = NULL;
1030 const cfg_obj_t *secretobj = NULL;
1031 const cfg_obj_t *algorithmobj = NULL;
1032 const char *keyname;
1033 const char *secretstr;
1034 const char *algorithm;
1035 isc_result_t result;
1036
1037 result = cfg_parser_create(NULL, &pctx);
1038 if (result != ISC_R_SUCCESS)
1039 goto cleanup;
1040
1041 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
1042 &file);
1043 if (result != ISC_R_SUCCESS)
1044 goto cleanup;
1045
1046 result = cfg_map_get(file, "key", &keyobj);
1047 if (result != ISC_R_SUCCESS)
1048 goto cleanup;
1049
1050 (void) cfg_map_get(keyobj, "secret", &secretobj);
1051 (void) cfg_map_get(keyobj, "algorithm", &algorithmobj);
1052 if (secretobj == NULL || algorithmobj == NULL)
1053 fatal("key must have algorithm and secret");
1054
1055 keyname = cfg_obj_asstring(cfg_map_getname(keyobj));
1056 secretstr = cfg_obj_asstring(secretobj);
1057 algorithm = cfg_obj_asstring(algorithmobj);
1058
1059 strlcpy(keynametext, keyname, sizeof(keynametext));
1060 strlcpy(keysecret, secretstr, sizeof(keysecret));
1061 parse_hmac(algorithm);
1062 setup_text_key();
1063
1064 cleanup:
1065 if (pctx != NULL) {
1066 if (file != NULL)
1067 cfg_obj_destroy(pctx, &file);
1068 cfg_parser_destroy(&pctx);
1069 }
1070
1071 return (result);
1072 }
1073
1074 void
setup_file_key(void)1075 setup_file_key(void) {
1076 isc_result_t result;
1077
1078 debug("setup_file_key()");
1079
1080 /* Try reading the key as a session.key keyfile */
1081 result = read_confkey();
1082
1083 if (result != ISC_R_SUCCESS)
1084 fprintf(stderr, "Couldn't read key from %s: %s\n",
1085 keyfile, isc_result_totext(result));
1086 }
1087
1088 static dig_searchlist_t *
make_searchlist_entry(char * domain)1089 make_searchlist_entry(char *domain) {
1090 dig_searchlist_t *search;
1091 search = malloc(sizeof(*search));
1092 if (search == NULL)
1093 fatal("memory allocation failure in %s:%d",
1094 __FILE__, __LINE__);
1095 strlcpy(search->origin, domain, MXNAME);
1096 search->origin[MXNAME-1] = 0;
1097 ISC_LINK_INIT(search, link);
1098 return (search);
1099 }
1100
1101 static void
clear_searchlist(void)1102 clear_searchlist(void) {
1103 dig_searchlist_t *search;
1104 while ((search = ISC_LIST_HEAD(search_list)) != NULL) {
1105 ISC_LIST_UNLINK(search_list, search, link);
1106 free(search);
1107 }
1108 }
1109
1110 static void
create_search_list(lwres_conf_t * confdata)1111 create_search_list(lwres_conf_t *confdata) {
1112 int i;
1113 dig_searchlist_t *search;
1114
1115 debug("create_search_list()");
1116 clear_searchlist();
1117
1118 for (i = 0; i < confdata->searchnxt; i++) {
1119 search = make_searchlist_entry(confdata->search[i]);
1120 ISC_LIST_APPEND(search_list, search, link);
1121 }
1122 }
1123
1124 /*%
1125 * Setup the system as a whole, reading key information and resolv.conf
1126 * settings.
1127 */
1128 void
setup_system(int ipv4only,int ipv6only)1129 setup_system(int ipv4only, int ipv6only) {
1130 dig_searchlist_t *domain = NULL;
1131 lwres_result_t lwresult;
1132 int lwresflags = 0;
1133
1134 debug("setup_system()");
1135
1136 if (ipv4only) {
1137 if (have_ipv4)
1138 have_ipv6 = 0;
1139 else
1140 fatal("can't find IPv4 networking");
1141 }
1142
1143 if (ipv6only) {
1144 if (have_ipv6)
1145 have_ipv4 = 0;
1146 else
1147 fatal("can't find IPv6 networking");
1148 }
1149
1150 if (have_ipv4)
1151 lwresflags |= LWRES_USEIPV4;
1152 if (have_ipv6)
1153 lwresflags |= LWRES_USEIPV6;
1154 lwres_conf_init(lwconf, lwresflags);
1155
1156 lwresult = lwres_conf_parse(lwconf, _PATH_RESCONF);
1157 if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND)
1158 fatal("parse of %s failed", _PATH_RESCONF);
1159
1160 /* Make the search list */
1161 if (lwconf->searchnxt > 0)
1162 create_search_list(lwconf);
1163 else { /* No search list. Use the domain name if any */
1164 if (lwconf->domainname != NULL) {
1165 domain = make_searchlist_entry(lwconf->domainname);
1166 ISC_LIST_APPEND(search_list, domain, link);
1167 domain = NULL;
1168 }
1169 }
1170
1171 if (ndots == -1) {
1172 ndots = lwconf->ndots;
1173 debug("ndots is %d.", ndots);
1174 }
1175
1176 /* If user doesn't specify server use nameservers from resolv.conf. */
1177 if (ISC_LIST_EMPTY(server_list))
1178 copy_server_list(lwconf, &server_list);
1179
1180 /* If we don't find a nameserver fall back to localhost */
1181 if (ISC_LIST_EMPTY(server_list)) {
1182 if (have_ipv4) {
1183 lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET);
1184 if (lwresult != ISC_R_SUCCESS)
1185 fatal("add_nameserver failed");
1186 }
1187 if (have_ipv6) {
1188 lwresult = add_nameserver(lwconf, "::1", AF_INET6);
1189 if (lwresult != ISC_R_SUCCESS)
1190 fatal("add_nameserver failed");
1191 }
1192
1193 copy_server_list(lwconf, &server_list);
1194 }
1195
1196 if (keyfile[0] != 0)
1197 setup_file_key();
1198 else if (keysecret[0] != 0)
1199 setup_text_key();
1200 arc4random_buf(cookie_secret, sizeof(cookie_secret));
1201 }
1202
1203 /*%
1204 * Override the search list derived from resolv.conf by 'domain'.
1205 */
1206 void
set_search_domain(char * domain)1207 set_search_domain(char *domain) {
1208 dig_searchlist_t *search;
1209
1210 clear_searchlist();
1211 search = make_searchlist_entry(domain);
1212 ISC_LIST_APPEND(search_list, search, link);
1213 }
1214
1215 /*%
1216 * Setup the ISC and DNS libraries for use by the system.
1217 */
1218 void
setup_libs(void)1219 setup_libs(void) {
1220 isc_result_t result;
1221 isc_logconfig_t *logconfig = NULL;
1222
1223 debug("setup_libs()");
1224
1225 dns_result_register();
1226
1227 result = isc_log_create(&lctx, &logconfig);
1228 check_result(result, "isc_log_create");
1229
1230 isc_log_setcontext(lctx);
1231 dns_log_init(lctx);
1232 dns_log_setcontext(lctx);
1233
1234 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
1235 check_result(result, "isc_log_usechannel");
1236
1237 isc_log_setdebuglevel(lctx, 0);
1238
1239 result = isc_taskmgr_create(1, 0, &taskmgr);
1240 check_result(result, "isc_taskmgr_create");
1241
1242 result = isc_task_create(taskmgr, 0, &global_task);
1243 check_result(result, "isc_task_create");
1244 isc_task_setname(global_task, "dig", NULL);
1245
1246 result = isc_timermgr_create(&timermgr);
1247 check_result(result, "isc_timermgr_create");
1248
1249 result = isc_socketmgr_create(&socketmgr);
1250 check_result(result, "isc_socketmgr_create");
1251
1252 check_result(result, "isc_entropy_create");
1253
1254 result = dst_lib_init();
1255 check_result(result, "dst_lib_init");
1256 is_dst_up = 1;
1257 }
1258
1259 typedef struct dig_ednsoptname {
1260 uint32_t code;
1261 const char *name;
1262 } dig_ednsoptname_t;
1263
1264 dig_ednsoptname_t optnames[] = {
1265 { 3, "NSID" }, /* RFC 5001 */
1266 { 5, "DAU" }, /* RFC 6975 */
1267 { 6, "DHU" }, /* RFC 6975 */
1268 { 7, "N3U" }, /* RFC 6975 */
1269 { 8, "ECS" }, /* RFC 7871 */
1270 { 9, "EXPIRE" }, /* RFC 7314 */
1271 { 10, "COOKIE" }, /* RFC 7873 */
1272 { 11, "KEEPALIVE" }, /* RFC 7828 */
1273 { 12, "PADDING" }, /* RFC 7830 */
1274 { 12, "PAD" }, /* shorthand */
1275 { 13, "CHAIN" }, /* RFC 7901 */
1276 { 14, "KEY-TAG" }, /* RFC 8145 */
1277 { 19, "ZONEVERSION" }, /* RFC 9660 */
1278 { 26946, "DEVICEID" }, /* Brian Hartvigsen */
1279 };
1280
1281 #define N_EDNS_OPTNAMES (sizeof(optnames) / sizeof(optnames[0]))
1282
1283 void
save_opt(dig_lookup_t * lookup,char * code,char * value)1284 save_opt(dig_lookup_t *lookup, char *code, char *value) {
1285 isc_result_t result;
1286 uint32_t num = 0;
1287 isc_buffer_t b;
1288 int found = 0;
1289 unsigned int i;
1290 const char *errstr;
1291
1292 if (lookup->ednsoptscnt >= EDNSOPT_OPTIONS)
1293 fatal("too many ednsopts");
1294
1295 for (i = 0; i < N_EDNS_OPTNAMES; i++) {
1296 if (strcasecmp(code, optnames[i].name) == 0) {
1297 num = optnames[i].code;
1298 found = 1;
1299 break;
1300 }
1301 }
1302
1303 if (!found) {
1304 num = strtonum(code, 0, 65535, &errstr);
1305 if (errstr != NULL)
1306 fatal("edns code point is %s: '%s'", errstr, code);
1307 }
1308
1309 if (lookup->ednsopts == NULL) {
1310 cloneopts(lookup, NULL);
1311 }
1312
1313 if (lookup->ednsopts[lookup->ednsoptscnt].value != NULL)
1314 free(lookup->ednsopts[lookup->ednsoptscnt].value);
1315
1316 lookup->ednsopts[lookup->ednsoptscnt].code = num;
1317 lookup->ednsopts[lookup->ednsoptscnt].length = 0;
1318 lookup->ednsopts[lookup->ednsoptscnt].value = NULL;
1319
1320 if (value != NULL) {
1321 char *buf;
1322 buf = malloc(strlen(value)/2 + 1);
1323 if (buf == NULL)
1324 fatal("out of memory");
1325 isc_buffer_init(&b, buf, (unsigned int) strlen(value)/2 + 1);
1326 result = isc_hex_decodestring(value, &b);
1327 check_result(result, "isc_hex_decodestring");
1328 lookup->ednsopts[lookup->ednsoptscnt].value =
1329 isc_buffer_base(&b);
1330 lookup->ednsopts[lookup->ednsoptscnt].length =
1331 isc_buffer_usedlength(&b);
1332 }
1333
1334 lookup->ednsoptscnt++;
1335 }
1336
1337 /*%
1338 * Add EDNS0 option record to a message. Currently, the only supported
1339 * options are UDP buffer size, the DO bit, and EDNS options
1340 * (e.g., NSID, SIT, client-subnet)
1341 */
1342 static void
add_opt(dns_message_t * msg,uint16_t udpsize,uint16_t edns,unsigned int flags,dns_ednsopt_t * opts,size_t count)1343 add_opt(dns_message_t *msg, uint16_t udpsize, uint16_t edns,
1344 unsigned int flags, dns_ednsopt_t *opts, size_t count)
1345 {
1346 dns_rdataset_t *rdataset = NULL;
1347 isc_result_t result;
1348
1349 debug("add_opt()");
1350 result = dns_message_buildopt(msg, &rdataset, edns, udpsize, flags,
1351 opts, count);
1352 check_result(result, "dns_message_buildopt");
1353 result = dns_message_setopt(msg, rdataset);
1354 check_result(result, "dns_message_setopt");
1355 }
1356
1357 /*%
1358 * Add a question section to a message, asking for the specified name,
1359 * type, and class.
1360 */
1361 static void
add_question(dns_message_t * message,dns_name_t * name,dns_rdataclass_t rdclass,dns_rdatatype_t rdtype)1362 add_question(dns_message_t *message, dns_name_t *name,
1363 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype)
1364 {
1365 dns_rdataset_t *rdataset;
1366 isc_result_t result;
1367
1368 debug("add_question()");
1369 rdataset = NULL;
1370 result = dns_message_gettemprdataset(message, &rdataset);
1371 check_result(result, "dns_message_gettemprdataset()");
1372 dns_rdataset_makequestion(rdataset, rdclass, rdtype);
1373 ISC_LIST_APPEND(name->list, rdataset, link);
1374 }
1375
1376 /*%
1377 * Check if we're done with all the queued lookups, which is true iff
1378 * all sockets, sends, and recvs are accounted for (counters == 0),
1379 * and the lookup list is empty.
1380 * If we are done, pass control back out to dighost_shutdown() (which is
1381 * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
1382 * a whole or reseed the lookup list.
1383 */
1384 static void
check_if_done(void)1385 check_if_done(void) {
1386 debug("check_if_done()");
1387 debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
1388 if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
1389 sendcount == 0) {
1390 INSIST(sockcount == 0);
1391 INSIST(recvcount == 0);
1392 debug("shutting down");
1393 dighost_shutdown();
1394 }
1395 }
1396
1397 /*%
1398 * Clear out a query when we're done with it. WARNING: This routine
1399 * WILL invalidate the query pointer.
1400 */
1401 static void
clear_query(dig_query_t * query)1402 clear_query(dig_query_t *query) {
1403 dig_lookup_t *lookup;
1404
1405 REQUIRE(query != NULL);
1406
1407 debug("clear_query(%p)", query);
1408
1409 if (query->timer != NULL)
1410 isc_timer_detach(&query->timer);
1411 lookup = query->lookup;
1412
1413 if (lookup->current_query == query)
1414 lookup->current_query = NULL;
1415
1416 if (ISC_LINK_LINKED(query, link))
1417 ISC_LIST_UNLINK(lookup->q, query, link);
1418 if (ISC_LINK_LINKED(query, clink))
1419 ISC_LIST_UNLINK(lookup->connecting, query, clink);
1420 if (ISC_LINK_LINKED(&query->recvbuf, link))
1421 ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf,
1422 link);
1423 if (ISC_LINK_LINKED(&query->lengthbuf, link))
1424 ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf,
1425 link);
1426 INSIST(query->recvspace != NULL);
1427
1428 if (query->sock != NULL) {
1429 isc_socket_detach(&query->sock);
1430 sockcount--;
1431 debug("sockcount=%d", sockcount);
1432 }
1433 free(query->recvspace);
1434 isc_buffer_invalidate(&query->recvbuf);
1435 isc_buffer_invalidate(&query->lengthbuf);
1436 if (query->waiting_senddone)
1437 query->pending_free = 1;
1438 else
1439 free(query);
1440 }
1441
1442 /*%
1443 * Try and clear out a lookup if we're done with it. Return 1 if
1444 * the lookup was successfully cleared. If 1 is returned, the
1445 * lookup pointer has been invalidated.
1446 */
1447 static int
try_clear_lookup(dig_lookup_t * lookup)1448 try_clear_lookup(dig_lookup_t *lookup) {
1449 dig_query_t *q;
1450
1451 REQUIRE(lookup != NULL);
1452
1453 debug("try_clear_lookup(%p)", lookup);
1454
1455 if (ISC_LIST_HEAD(lookup->q) != NULL ||
1456 ISC_LIST_HEAD(lookup->connecting) != NULL)
1457 {
1458 if (debugging) {
1459 q = ISC_LIST_HEAD(lookup->q);
1460 while (q != NULL) {
1461 debug("query to %s still pending", q->servname);
1462 q = ISC_LIST_NEXT(q, link);
1463 }
1464
1465 q = ISC_LIST_HEAD(lookup->connecting);
1466 while (q != NULL) {
1467 debug("query to %s still connecting",
1468 q->servname);
1469 q = ISC_LIST_NEXT(q, clink);
1470 }
1471 }
1472 return (0);
1473 }
1474
1475 /*
1476 * At this point, we know there are no queries on the lookup,
1477 * so can make it go away also.
1478 */
1479 destroy_lookup(lookup);
1480 return (1);
1481 }
1482
1483 void
destroy_lookup(dig_lookup_t * lookup)1484 destroy_lookup(dig_lookup_t *lookup) {
1485 dig_server_t *s;
1486 void *ptr;
1487
1488 debug("destroy");
1489 s = ISC_LIST_HEAD(lookup->my_server_list);
1490 while (s != NULL) {
1491 debug("freeing server %p belonging to %p", s, lookup);
1492 ptr = s;
1493 s = ISC_LIST_NEXT(s, link);
1494 ISC_LIST_DEQUEUE(lookup->my_server_list,
1495 (dig_server_t *)ptr, link);
1496 free(ptr);
1497 }
1498 if (lookup->sendmsg != NULL)
1499 dns_message_destroy(&lookup->sendmsg);
1500 if (lookup->querysig != NULL) {
1501 debug("freeing buffer %p", lookup->querysig);
1502 isc_buffer_free(&lookup->querysig);
1503 }
1504 if (lookup->sendspace != NULL)
1505 free(lookup->sendspace);
1506
1507 if (lookup->tsigctx != NULL)
1508 dst_context_destroy(&lookup->tsigctx);
1509
1510 if (lookup->ecs_addr != NULL)
1511 free(lookup->ecs_addr);
1512
1513 if (lookup->ednsopts != NULL) {
1514 size_t i;
1515 for (i = 0; i < EDNSOPT_OPTIONS; i++) {
1516 if (lookup->ednsopts[i].value != NULL)
1517 free(lookup->ednsopts[i].value);
1518 }
1519 free(lookup->ednsopts);
1520 }
1521
1522 free(lookup);
1523 }
1524
1525 /*%
1526 * If we can, start the next lookup in the queue running.
1527 * This assumes that the lookup on the head of the queue hasn't been
1528 * started yet. It also removes the lookup from the head of the queue,
1529 * setting the current_lookup pointer pointing to it.
1530 */
1531 void
start_lookup(void)1532 start_lookup(void) {
1533 debug("start_lookup()");
1534 if (cancel_now)
1535 return;
1536
1537 /*
1538 * If there's a current lookup running, we really shouldn't get
1539 * here.
1540 */
1541 INSIST(current_lookup == NULL);
1542
1543 current_lookup = ISC_LIST_HEAD(lookup_list);
1544 /*
1545 * Put the current lookup somewhere so cancel_all can find it
1546 */
1547 if (current_lookup != NULL) {
1548 ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
1549 if (setup_lookup(current_lookup))
1550 do_lookup(current_lookup);
1551 else if (next_origin(current_lookup))
1552 check_next_lookup(current_lookup);
1553 } else {
1554 check_if_done();
1555 }
1556 }
1557
1558 /*%
1559 * If we can, clear the current lookup and start the next one running.
1560 * This calls try_clear_lookup, so may invalidate the lookup pointer.
1561 */
1562 static void
check_next_lookup(dig_lookup_t * lookup)1563 check_next_lookup(dig_lookup_t *lookup) {
1564
1565 INSIST(!free_now);
1566
1567 debug("check_next_lookup(%p)", lookup);
1568
1569 if (ISC_LIST_HEAD(lookup->q) != NULL) {
1570 debug("still have a worker");
1571 return;
1572 }
1573 if (try_clear_lookup(lookup)) {
1574 current_lookup = NULL;
1575 start_lookup();
1576 }
1577 }
1578
1579 /*%
1580 * Create and queue a new lookup as a followup to the current lookup,
1581 * based on the supplied message and section. This is used in trace and
1582 * name server search modes to start a new lookup using servers from
1583 * NS records in a reply. Returns the number of followup lookups made.
1584 */
1585 static int
followup_lookup(dns_message_t * msg,dig_query_t * query,dns_section_t section)1586 followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section)
1587 {
1588 dig_lookup_t *lookup = NULL;
1589 dig_server_t *srv = NULL;
1590 dns_rdataset_t *rdataset = NULL;
1591 dns_rdata_t rdata = DNS_RDATA_INIT;
1592 dns_name_t *name = NULL;
1593 isc_result_t result;
1594 int success = 0;
1595 int numLookups = 0;
1596 int num;
1597 isc_result_t lresult, addresses_result;
1598 char bad_namestr[DNS_NAME_FORMATSIZE];
1599 dns_name_t *domain;
1600 int horizontal = 0, bad = 0;
1601
1602 INSIST(!free_now);
1603
1604 debug("following up %s", query->lookup->textname);
1605
1606 addresses_result = ISC_R_SUCCESS;
1607 bad_namestr[0] = '\0';
1608 for (result = dns_message_firstname(msg, section);
1609 result == ISC_R_SUCCESS;
1610 result = dns_message_nextname(msg, section)) {
1611 name = NULL;
1612 dns_message_currentname(msg, section, &name);
1613
1614 if (section == DNS_SECTION_AUTHORITY) {
1615 rdataset = NULL;
1616 result = dns_message_findtype(name, dns_rdatatype_soa,
1617 0, &rdataset);
1618 if (result == ISC_R_SUCCESS)
1619 return (0);
1620 }
1621 rdataset = NULL;
1622 result = dns_message_findtype(name, dns_rdatatype_ns, 0,
1623 &rdataset);
1624 if (result != ISC_R_SUCCESS)
1625 continue;
1626
1627 debug("found NS set");
1628
1629 if (query->lookup->trace && !query->lookup->trace_root) {
1630 dns_namereln_t namereln;
1631 unsigned int nlabels;
1632 int order;
1633
1634 domain = dns_fixedname_name(&query->lookup->fdomain);
1635 namereln = dns_name_fullcompare(name, domain,
1636 &order, &nlabels);
1637 if (namereln == dns_namereln_equal) {
1638 if (!horizontal)
1639 printf(";; BAD (HORIZONTAL) REFERRAL\n");
1640 horizontal = 1;
1641 } else if (namereln != dns_namereln_subdomain) {
1642 if (!bad)
1643 printf(";; BAD REFERRAL\n");
1644 bad = 1;
1645 continue;
1646 }
1647 }
1648
1649 for (result = dns_rdataset_first(rdataset);
1650 result == ISC_R_SUCCESS;
1651 result = dns_rdataset_next(rdataset)) {
1652 char namestr[DNS_NAME_FORMATSIZE];
1653 dns_rdata_ns_t ns;
1654
1655 if (query->lookup->trace_root &&
1656 query->lookup->nsfound >= MXSERV)
1657 break;
1658
1659 dns_rdataset_current(rdataset, &rdata);
1660
1661 query->lookup->nsfound++;
1662 result = dns_rdata_tostruct_ns(&rdata, &ns);
1663 check_result(result, "dns_rdata_tostruct_ns");
1664 dns_name_format(&ns.name, namestr, sizeof(namestr));
1665 dns_rdata_freestruct_ns(&ns);
1666
1667 /* Initialize lookup if we've not yet */
1668 debug("found NS %s", namestr);
1669 if (!success) {
1670 success = 1;
1671 lookup_counter++;
1672 lookup = requeue_lookup(query->lookup,
1673 0);
1674 cancel_lookup(query->lookup);
1675 lookup->doing_xfr = 0;
1676 if (!lookup->trace_root &&
1677 section == DNS_SECTION_ANSWER)
1678 lookup->trace = 0;
1679 else
1680 lookup->trace = query->lookup->trace;
1681 lookup->ns_search_only =
1682 query->lookup->ns_search_only;
1683 lookup->trace_root = 0;
1684 if (lookup->ns_search_only)
1685 lookup->recurse = 0;
1686 domain = dns_fixedname_name(&lookup->fdomain);
1687 dns_name_copy(name, domain, NULL);
1688 }
1689 debug("adding server %s", namestr);
1690 num = getaddresses(lookup, namestr, &lresult);
1691 if (lresult != ISC_R_SUCCESS) {
1692 printf("couldn't get address for '%s': %s\n",
1693 namestr, isc_result_totext(lresult));
1694 if (addresses_result == ISC_R_SUCCESS) {
1695 addresses_result = lresult;
1696 strlcpy(bad_namestr, namestr,
1697 sizeof(bad_namestr));
1698 }
1699 }
1700 numLookups += num;
1701 dns_rdata_reset(&rdata);
1702 }
1703 }
1704 if (numLookups == 0 && addresses_result != ISC_R_SUCCESS) {
1705 fatal("couldn't get address for '%s': %s",
1706 bad_namestr, isc_result_totext(result));
1707 }
1708
1709 if (lookup == NULL &&
1710 section == DNS_SECTION_ANSWER &&
1711 (query->lookup->trace || query->lookup->ns_search_only))
1712 return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY));
1713
1714 /*
1715 * Randomize the order the nameserver will be tried.
1716 */
1717 if (numLookups > 1) {
1718 uint32_t i, j;
1719 dig_serverlist_t my_server_list;
1720 dig_server_t *next;
1721
1722 ISC_LIST_INIT(my_server_list);
1723
1724 i = numLookups;
1725 for (srv = ISC_LIST_HEAD(lookup->my_server_list);
1726 srv != NULL;
1727 srv = ISC_LIST_HEAD(lookup->my_server_list)) {
1728 INSIST(i > 0);
1729 j = arc4random_uniform(i);
1730 next = ISC_LIST_NEXT(srv, link);
1731 while (j-- > 0 && next != NULL) {
1732 srv = next;
1733 next = ISC_LIST_NEXT(srv, link);
1734 }
1735 ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link);
1736 ISC_LIST_APPEND(my_server_list, srv, link);
1737 i--;
1738 }
1739 ISC_LIST_APPENDLIST(lookup->my_server_list,
1740 my_server_list, link);
1741 }
1742
1743 return (numLookups);
1744 }
1745
1746 /*%
1747 * Create and queue a new lookup using the next origin from the search
1748 * list, read in setup_system().
1749 *
1750 * Return 1 iff there was another searchlist entry.
1751 */
1752 static int
next_origin(dig_lookup_t * oldlookup)1753 next_origin(dig_lookup_t *oldlookup) {
1754 dig_lookup_t *newlookup;
1755 dig_searchlist_t *search;
1756 dns_fixedname_t fixed;
1757 dns_name_t *name;
1758 isc_result_t result;
1759
1760 INSIST(!free_now);
1761
1762 debug("next_origin()");
1763 debug("following up %s", oldlookup->textname);
1764
1765 if (!usesearch)
1766 /*
1767 * We're not using a search list, so don't even think
1768 * about finding the next entry.
1769 */
1770 return (0);
1771
1772 /*
1773 * Check for a absolute name or ndots being met.
1774 */
1775 dns_fixedname_init(&fixed);
1776 name = dns_fixedname_name(&fixed);
1777 result = dns_name_fromstring2(name, oldlookup->textname, NULL, 0);
1778 if (result == ISC_R_SUCCESS &&
1779 (dns_name_isabsolute(name) ||
1780 (int)dns_name_countlabels(name) > ndots))
1781 return (0);
1782
1783 if (oldlookup->origin == NULL && !oldlookup->need_search)
1784 /*
1785 * Then we just did rootorg; there's nothing left.
1786 */
1787 return (0);
1788 if (oldlookup->origin == NULL && oldlookup->need_search) {
1789 newlookup = requeue_lookup(oldlookup, 1);
1790 newlookup->origin = ISC_LIST_HEAD(search_list);
1791 newlookup->need_search = 0;
1792 } else {
1793 search = ISC_LIST_NEXT(oldlookup->origin, link);
1794 if (search == NULL && oldlookup->done_as_is)
1795 return (0);
1796 newlookup = requeue_lookup(oldlookup, 1);
1797 newlookup->origin = search;
1798 }
1799 cancel_lookup(oldlookup);
1800 return (1);
1801 }
1802
1803 /*%
1804 * Insert an SOA record into the sendmessage in a lookup. Used for
1805 * creating IXFR queries.
1806 */
1807 static void
insert_soa(dig_lookup_t * lookup)1808 insert_soa(dig_lookup_t *lookup) {
1809 isc_result_t result;
1810 dns_rdata_soa_t soa;
1811 dns_rdata_t *rdata = NULL;
1812 dns_rdatalist_t *rdatalist = NULL;
1813 dns_rdataset_t *rdataset = NULL;
1814 dns_name_t *soaname = NULL;
1815
1816 debug("insert_soa()");
1817 soa.serial = lookup->ixfr_serial;
1818 soa.refresh = 0;
1819 soa.retry = 0;
1820 soa.expire = 0;
1821 soa.minimum = 0;
1822 soa.common.rdclass = lookup->rdclass;
1823 soa.common.rdtype = dns_rdatatype_soa;
1824
1825 dns_name_init(&soa.origin, NULL);
1826 dns_name_init(&soa.contact, NULL);
1827
1828 dns_name_clone(dns_rootname, &soa.origin);
1829 dns_name_clone(dns_rootname, &soa.contact);
1830
1831 isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
1832 sizeof(lookup->rdatastore));
1833
1834 result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
1835 check_result(result, "dns_message_gettemprdata");
1836
1837 result = dns_rdata_fromstruct_soa(rdata, lookup->rdclass,
1838 dns_rdatatype_soa, &soa,
1839 &lookup->rdatabuf);
1840 check_result(result, "isc_rdata_fromstruct_soa");
1841
1842 result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
1843 check_result(result, "dns_message_gettemprdatalist");
1844
1845 result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
1846 check_result(result, "dns_message_gettemprdataset");
1847
1848 dns_rdatalist_init(rdatalist);
1849 rdatalist->type = dns_rdatatype_soa;
1850 rdatalist->rdclass = lookup->rdclass;
1851 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1852
1853 dns_rdatalist_tordataset(rdatalist, rdataset);
1854
1855 result = dns_message_gettempname(lookup->sendmsg, &soaname);
1856 check_result(result, "dns_message_gettempname");
1857 dns_name_init(soaname, NULL);
1858 dns_name_clone(lookup->name, soaname);
1859 ISC_LIST_INIT(soaname->list);
1860 ISC_LIST_APPEND(soaname->list, rdataset, link);
1861 dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
1862 }
1863
1864 static void
compute_cookie(unsigned char * clientcookie,size_t len)1865 compute_cookie(unsigned char *clientcookie, size_t len) {
1866 /* XXXMPA need to fix, should be per server. */
1867 INSIST(len >= 8U);
1868 memmove(clientcookie, cookie_secret, 8);
1869 }
1870
1871 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
1872 static void
populate_root_hints(void)1873 populate_root_hints(void)
1874 {
1875 dig_server_t *newsrv;
1876 size_t i;
1877
1878 if (!ISC_LIST_EMPTY(root_hints_server_list))
1879 return;
1880
1881 for (i = 0; i < nitems(root_hints); i++) {
1882 if (!have_ipv4 && root_hints[i].af == AF_INET)
1883 continue;
1884 if (!have_ipv6 && root_hints[i].af == AF_INET6)
1885 continue;
1886 newsrv = make_server(root_hints[i].ns, root_hints[i].ns);
1887 ISC_LINK_INIT(newsrv, link);
1888 ISC_LIST_ENQUEUE(root_hints_server_list, newsrv, link);
1889 }
1890 }
1891 #undef nitems
1892
1893 /*%
1894 * Setup the supplied lookup structure, making it ready to start sending
1895 * queries to servers. Create and initialize the message to be sent as
1896 * well as the query structures and buffer space for the replies. If the
1897 * server list is empty, clone it from the system default list.
1898 */
1899 int
setup_lookup(dig_lookup_t * lookup)1900 setup_lookup(dig_lookup_t *lookup) {
1901 isc_result_t result;
1902 uint32_t id;
1903 unsigned int len;
1904 dig_server_t *serv;
1905 dig_query_t *query;
1906 isc_buffer_t b;
1907 dns_compress_t cctx;
1908 char store[MXNAME];
1909 char ecsbuf[20];
1910 char sitbuf[256];
1911
1912 REQUIRE(lookup != NULL);
1913 INSIST(!free_now);
1914
1915 debug("setup_lookup(%p)", lookup);
1916
1917 result = dns_message_create(DNS_MESSAGE_INTENTRENDER,
1918 &lookup->sendmsg);
1919 check_result(result, "dns_message_create");
1920
1921 if (lookup->new_search) {
1922 debug("resetting lookup counter.");
1923 lookup_counter = 0;
1924 }
1925
1926 if (ISC_LIST_EMPTY(lookup->my_server_list)) {
1927 if (lookup->trace && lookup->trace_root) {
1928 populate_root_hints();
1929 clone_server_list(root_hints_server_list,
1930 &lookup->my_server_list);
1931 } else {
1932 debug("cloning server list");
1933 clone_server_list(server_list,
1934 &lookup->my_server_list);
1935 }
1936 }
1937 result = dns_message_gettempname(lookup->sendmsg, &lookup->name);
1938 check_result(result, "dns_message_gettempname");
1939 dns_name_init(lookup->name, NULL);
1940
1941 isc_buffer_init(&lookup->namebuf, lookup->name_space,
1942 sizeof(lookup->name_space));
1943 isc_buffer_init(&lookup->onamebuf, lookup->oname_space,
1944 sizeof(lookup->oname_space));
1945
1946 /*
1947 * If the name has too many dots, force the origin to be NULL
1948 * (which produces an absolute lookup). Otherwise, take the origin
1949 * we have if there's one in the struct already. If it's NULL,
1950 * take the first entry in the searchlist iff either usesearch
1951 * is TRUE or we got a domain line in the resolv.conf file.
1952 */
1953 if (lookup->new_search) {
1954 if ((count_dots(lookup->textname) >= ndots) || !usesearch) {
1955 lookup->origin = NULL; /* Force abs lookup */
1956 lookup->done_as_is = 1;
1957 lookup->need_search = usesearch;
1958 } else if (lookup->origin == NULL && usesearch) {
1959 lookup->origin = ISC_LIST_HEAD(search_list);
1960 lookup->need_search = 0;
1961 }
1962 }
1963
1964 if (lookup->origin != NULL) {
1965 debug("trying origin %s", lookup->origin->origin);
1966 result = dns_message_gettempname(lookup->sendmsg,
1967 &lookup->oname);
1968 check_result(result, "dns_message_gettempname");
1969 dns_name_init(lookup->oname, NULL);
1970 /* XXX Helper funct to conv char* to name? */
1971 len = (unsigned int) strlen(lookup->origin->origin);
1972 isc_buffer_init(&b, lookup->origin->origin, len);
1973 isc_buffer_add(&b, len);
1974 result = dns_name_fromtext(lookup->oname, &b, dns_rootname,
1975 0, &lookup->onamebuf);
1976 if (result != ISC_R_SUCCESS) {
1977 dns_message_puttempname(lookup->sendmsg,
1978 &lookup->name);
1979 dns_message_puttempname(lookup->sendmsg,
1980 &lookup->oname);
1981 fatal("'%s' is not in legal name syntax (%s)",
1982 lookup->origin->origin,
1983 isc_result_totext(result));
1984 }
1985 if (lookup->trace && lookup->trace_root) {
1986 dns_name_clone(dns_rootname, lookup->name);
1987 } else {
1988 dns_fixedname_t fixed;
1989 dns_name_t *name;
1990
1991 dns_fixedname_init(&fixed);
1992 name = dns_fixedname_name(&fixed);
1993 len = (unsigned int) strlen(lookup->textname);
1994 isc_buffer_init(&b, lookup->textname, len);
1995 isc_buffer_add(&b, len);
1996 result = dns_name_fromtext(name, &b, NULL, 0, NULL);
1997 if (result == ISC_R_SUCCESS &&
1998 !dns_name_isabsolute(name))
1999 result = dns_name_concatenate(name,
2000 lookup->oname,
2001 lookup->name,
2002 &lookup->namebuf);
2003 else if (result == ISC_R_SUCCESS)
2004 result = dns_name_copy(name, lookup->name,
2005 &lookup->namebuf);
2006 if (result != ISC_R_SUCCESS) {
2007 dns_message_puttempname(lookup->sendmsg,
2008 &lookup->name);
2009 dns_message_puttempname(lookup->sendmsg,
2010 &lookup->oname);
2011 if (result == DNS_R_NAMETOOLONG)
2012 return (0);
2013 fatal("'%s' is not in legal name syntax (%s)",
2014 lookup->textname,
2015 isc_result_totext(result));
2016 }
2017 }
2018 dns_message_puttempname(lookup->sendmsg, &lookup->oname);
2019 } else
2020 {
2021 debug("using root origin");
2022 if (lookup->trace && lookup->trace_root)
2023 dns_name_clone(dns_rootname, lookup->name);
2024 else {
2025 len = (unsigned int) strlen(lookup->textname);
2026 isc_buffer_init(&b, lookup->textname, len);
2027 isc_buffer_add(&b, len);
2028 result = dns_name_fromtext(lookup->name, &b,
2029 dns_rootname, 0,
2030 &lookup->namebuf);
2031 }
2032 if (result != ISC_R_SUCCESS) {
2033 dns_message_puttempname(lookup->sendmsg,
2034 &lookup->name);
2035 fatal("'%s' is not a legal name "
2036 "(%s)", lookup->textname,
2037 isc_result_totext(result));
2038 }
2039 }
2040 dns_name_format(lookup->name, store, sizeof(store));
2041 dighost_trying(store, lookup);
2042 INSIST(dns_name_isabsolute(lookup->name));
2043
2044 id = arc4random();
2045 lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
2046 lookup->sendmsg->opcode = lookup->opcode;
2047 lookup->msgcounter = 0;
2048 /*
2049 * If this is a trace request, completely disallow recursion, since
2050 * it's meaningless for traces.
2051 */
2052 if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root))
2053 lookup->recurse = 0;
2054
2055 if (lookup->recurse &&
2056 lookup->rdtype != dns_rdatatype_axfr &&
2057 lookup->rdtype != dns_rdatatype_ixfr) {
2058 debug("recursive query");
2059 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD;
2060 }
2061
2062 /* XXX aaflag */
2063 if (lookup->aaonly) {
2064 debug("AA query");
2065 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA;
2066 }
2067
2068 if (lookup->adflag) {
2069 debug("AD query");
2070 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD;
2071 }
2072
2073 if (lookup->cdflag) {
2074 debug("CD query");
2075 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD;
2076 }
2077
2078 dns_message_addname(lookup->sendmsg, lookup->name,
2079 DNS_SECTION_QUESTION);
2080
2081 if (lookup->trace && lookup->trace_root) {
2082 lookup->qrdtype = lookup->rdtype;
2083 lookup->rdtype = dns_rdatatype_ns;
2084 }
2085
2086 if ((lookup->rdtype == dns_rdatatype_axfr) ||
2087 (lookup->rdtype == dns_rdatatype_ixfr)) {
2088 /*
2089 * Force TCP mode if we're doing an axfr.
2090 */
2091 if (lookup->rdtype == dns_rdatatype_axfr) {
2092 lookup->doing_xfr = 1;
2093 lookup->tcp_mode = 1;
2094 } else if (lookup->tcp_mode) {
2095 lookup->doing_xfr = 1;
2096 }
2097 }
2098
2099 add_question(lookup->sendmsg, lookup->name, lookup->rdclass,
2100 lookup->rdtype);
2101
2102 /* add_soa */
2103 if (lookup->rdtype == dns_rdatatype_ixfr)
2104 insert_soa(lookup);
2105
2106 /* XXX Insist this? */
2107 lookup->tsigctx = NULL;
2108 lookup->querysig = NULL;
2109 if (tsigkey != NULL) {
2110 debug("initializing keys");
2111 result = dns_message_settsigkey(lookup->sendmsg, tsigkey);
2112 check_result(result, "dns_message_settsigkey");
2113 }
2114
2115 lookup->sendspace = malloc(COMMSIZE);
2116 if (lookup->sendspace == NULL)
2117 fatal("memory allocation failure");
2118
2119 result = dns_compress_init(&cctx, -1);
2120 check_result(result, "dns_compress_init");
2121
2122 debug("starting to render the message");
2123 isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE);
2124 result = dns_message_renderbegin(lookup->sendmsg, &cctx,
2125 &lookup->renderbuf);
2126 check_result(result, "dns_message_renderbegin");
2127 if (lookup->udpsize > 0 || lookup->dnssec ||
2128 lookup->edns > -1 || lookup->ecs_addr != NULL)
2129 {
2130 #define MAXOPTS (EDNSOPT_OPTIONS + DNS_EDNSOPTIONS)
2131 dns_ednsopt_t opts[MAXOPTS];
2132 unsigned int flags;
2133 unsigned int i = 0;
2134
2135 if (lookup->udpsize == 0)
2136 lookup->udpsize = 4096;
2137 if (lookup->edns < 0)
2138 lookup->edns = 0;
2139
2140 if (lookup->nsid) {
2141 INSIST(i < MAXOPTS);
2142 opts[i].code = DNS_OPT_NSID;
2143 opts[i].length = 0;
2144 opts[i].value = NULL;
2145 i++;
2146 }
2147
2148 if (lookup->ecs_addr != NULL) {
2149 uint8_t addr[16];
2150 uint16_t family;
2151 uint32_t plen;
2152 struct sockaddr *sa;
2153 struct sockaddr_in *sin;
2154 struct sockaddr_in6 *sin6;
2155 size_t addrl;
2156
2157 sa = (struct sockaddr *)lookup->ecs_addr;
2158 plen = lookup->ecs_plen;
2159
2160 /* Round up prefix len to a multiple of 8 */
2161 addrl = (plen + 7) / 8;
2162
2163 INSIST(i < MAXOPTS);
2164 opts[i].code = DNS_OPT_CLIENT_SUBNET;
2165 opts[i].length = (uint16_t) addrl + 4;
2166 check_result(result, "isc_buffer_allocate");
2167
2168 /*
2169 * XXXMUKS: According to RFC7871, "If there is
2170 * no ADDRESS set, i.e., SOURCE PREFIX-LENGTH is
2171 * set to 0, then FAMILY SHOULD be set to the
2172 * transport over which the query is sent."
2173 *
2174 * However, at this point we don't know what
2175 * transport(s) we'll be using, so we can't
2176 * set the value now. For now, we're using
2177 * IPv4 as the default the +subnet option
2178 * used an IPv4 prefix, or for +subnet=0,
2179 * and IPv6 if the +subnet option used an
2180 * IPv6 prefix.
2181 *
2182 * (For future work: preserve the offset into
2183 * the buffer where the family field is;
2184 * that way we can update it in send_udp()
2185 * or send_tcp_connect() once we know
2186 * what it outght to be.)
2187 */
2188 switch (sa->sa_family) {
2189 case AF_UNSPEC:
2190 INSIST(plen == 0);
2191 family = 1;
2192 break;
2193 case AF_INET:
2194 INSIST(plen <= 32);
2195 family = 1;
2196 sin = (struct sockaddr_in *) sa;
2197 memmove(addr, &sin->sin_addr, addrl);
2198 break;
2199 case AF_INET6:
2200 INSIST(plen <= 128);
2201 family = 2;
2202 sin6 = (struct sockaddr_in6 *) sa;
2203 memmove(addr, &sin6->sin6_addr, addrl);
2204 break;
2205 default:
2206 INSIST(0);
2207 }
2208
2209 isc_buffer_init(&b, ecsbuf, sizeof(ecsbuf));
2210 /* family */
2211 isc_buffer_putuint16(&b, family);
2212 /* source prefix-length */
2213 isc_buffer_putuint8(&b, plen);
2214 /* scope prefix-length */
2215 isc_buffer_putuint8(&b, 0);
2216
2217 /* address */
2218 if (addrl > 0) {
2219 /* Mask off last address byte */
2220 if ((plen % 8) != 0)
2221 addr[addrl - 1] &=
2222 ~0U << (8 - (plen % 8));
2223 isc_buffer_putmem(&b, addr,
2224 (unsigned)addrl);
2225 }
2226
2227 opts[i].value = (uint8_t *) ecsbuf;
2228 i++;
2229 }
2230
2231 if (lookup->sit) {
2232 INSIST(i < MAXOPTS);
2233 opts[i].code = DNS_OPT_COOKIE;
2234 if (lookup->sitvalue != NULL) {
2235 isc_buffer_init(&b, sitbuf, sizeof(sitbuf));
2236 result = isc_hex_decodestring(lookup->sitvalue,
2237 &b);
2238 check_result(result, "isc_hex_decodestring");
2239 opts[i].value = isc_buffer_base(&b);
2240 opts[i].length = isc_buffer_usedlength(&b);
2241 } else {
2242 compute_cookie(cookie, sizeof(cookie));
2243 opts[i].length = 8;
2244 opts[i].value = cookie;
2245 }
2246 i++;
2247 }
2248
2249 if (lookup->expire) {
2250 INSIST(i < MAXOPTS);
2251 opts[i].code = DNS_OPT_EXPIRE;
2252 opts[i].length = 0;
2253 opts[i].value = NULL;
2254 i++;
2255 }
2256
2257 if (lookup->ednsoptscnt != 0) {
2258 INSIST(i + lookup->ednsoptscnt <= MAXOPTS);
2259 memmove(&opts[i], lookup->ednsopts,
2260 sizeof(dns_ednsopt_t) * lookup->ednsoptscnt);
2261 i += lookup->ednsoptscnt;
2262 }
2263
2264 flags = lookup->ednsflags;
2265 flags &= ~DNS_MESSAGEEXTFLAG_DO;
2266 if (lookup->dnssec)
2267 flags |= DNS_MESSAGEEXTFLAG_DO;
2268 add_opt(lookup->sendmsg, lookup->udpsize,
2269 lookup->edns, flags, opts, i);
2270 }
2271
2272 result = dns_message_rendersection(lookup->sendmsg,
2273 DNS_SECTION_QUESTION);
2274 check_result(result, "dns_message_rendersection");
2275 result = dns_message_rendersection(lookup->sendmsg,
2276 DNS_SECTION_AUTHORITY);
2277 check_result(result, "dns_message_rendersection");
2278 result = dns_message_renderend(lookup->sendmsg);
2279 check_result(result, "dns_message_renderend");
2280 debug("done rendering");
2281
2282 dns_compress_invalidate(&cctx);
2283
2284 /*
2285 * Force TCP mode if the request is larger than 512 bytes.
2286 */
2287 if (isc_buffer_usedlength(&lookup->renderbuf) > 512)
2288 lookup->tcp_mode = 1;
2289
2290 lookup->pending = 0;
2291
2292 for (serv = ISC_LIST_HEAD(lookup->my_server_list);
2293 serv != NULL;
2294 serv = ISC_LIST_NEXT(serv, link)) {
2295 query = malloc(sizeof(dig_query_t));
2296 if (query == NULL)
2297 fatal("memory allocation failure in %s:%d",
2298 __FILE__, __LINE__);
2299 debug("create query %p linked to lookup %p",
2300 query, lookup);
2301 query->lookup = lookup;
2302 query->timer = NULL;
2303 query->waiting_connect = 0;
2304 query->waiting_senddone = 0;
2305 query->pending_free = 0;
2306 query->recv_made = 0;
2307 query->first_pass = 1;
2308 query->first_soa_rcvd = 0;
2309 query->second_rr_rcvd = 0;
2310 query->first_repeat_rcvd = 0;
2311 query->warn_id = 1;
2312 query->timedout = 0;
2313 query->first_rr_serial = 0;
2314 query->second_rr_serial = 0;
2315 query->servname = serv->servername;
2316 query->userarg = serv->userarg;
2317 query->rr_count = 0;
2318 query->msg_count = 0;
2319 query->byte_count = 0;
2320 query->ixfr_axfr = 0;
2321 ISC_LIST_INIT(query->recvlist);
2322 ISC_LIST_INIT(query->lengthlist);
2323 query->sock = NULL;
2324 query->recvspace = malloc(COMMSIZE);
2325 if (query->recvspace == NULL)
2326 fatal("memory allocation failure");
2327
2328 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
2329 isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
2330 isc_buffer_init(&query->slbuf, query->slspace, 2);
2331 query->sendbuf = lookup->renderbuf;
2332
2333 ISC_LINK_INIT(query, clink);
2334 ISC_LINK_INIT(query, link);
2335 ISC_LIST_ENQUEUE(lookup->q, query, link);
2336 }
2337
2338 /* XXX qrflag, print_query, etc... */
2339 if (!ISC_LIST_EMPTY(lookup->q) && qr) {
2340 extrabytes = 0;
2341 dighost_printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg,
2342 1);
2343 }
2344 return (1);
2345 }
2346
2347 /*%
2348 * Event handler for send completion. Track send counter, and clear out
2349 * the query if the send was canceled.
2350 */
2351 static void
send_done(isc_task_t * _task,isc_event_t * event)2352 send_done(isc_task_t *_task, isc_event_t *event) {
2353 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
2354 isc_buffer_t *b = NULL;
2355 dig_query_t *query, *next;
2356 dig_lookup_t *l;
2357
2358 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
2359
2360 UNUSED(_task);
2361
2362 debug("send_done()");
2363 sendcount--;
2364 debug("sendcount=%d", sendcount);
2365 INSIST(sendcount >= 0);
2366
2367 for (b = ISC_LIST_HEAD(sevent->bufferlist);
2368 b != NULL;
2369 b = ISC_LIST_HEAD(sevent->bufferlist)) {
2370 ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2371 free(b);
2372 }
2373
2374 query = event->ev_arg;
2375 query->waiting_senddone = 0;
2376 l = query->lookup;
2377
2378 if (l->ns_search_only && !l->trace_root && !l->tcp_mode) {
2379 debug("sending next, since searching");
2380 next = ISC_LIST_NEXT(query, link);
2381 if (next != NULL)
2382 send_udp(next);
2383 }
2384
2385 isc_event_free(&event);
2386
2387 if (query->pending_free)
2388 free(query);
2389
2390 check_if_done();
2391 }
2392
2393 /*%
2394 * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
2395 * IO sockets. The cancel handlers should take care of cleaning up the
2396 * query and lookup structures
2397 */
2398 static void
cancel_lookup(dig_lookup_t * lookup)2399 cancel_lookup(dig_lookup_t *lookup) {
2400 dig_query_t *query, *next;
2401
2402 debug("cancel_lookup()");
2403 query = ISC_LIST_HEAD(lookup->q);
2404 while (query != NULL) {
2405 next = ISC_LIST_NEXT(query, link);
2406 if (query->sock != NULL) {
2407 isc_socket_cancel(query->sock, global_task,
2408 ISC_SOCKCANCEL_ALL);
2409 check_if_done();
2410 } else {
2411 clear_query(query);
2412 }
2413 query = next;
2414 }
2415 lookup->pending = 0;
2416 lookup->retries = 0;
2417 }
2418
2419 static void
bringup_timer(dig_query_t * query,unsigned int default_timeout)2420 bringup_timer(dig_query_t *query, unsigned int default_timeout) {
2421 dig_lookup_t *l;
2422 unsigned int local_timeout;
2423 isc_result_t result;
2424
2425 debug("bringup_timer()");
2426 /*
2427 * If the timer already exists, that means we're calling this
2428 * a second time (for a retry). Don't need to recreate it,
2429 * just reset it.
2430 */
2431 l = query->lookup;
2432 if (ISC_LINK_LINKED(query, link) && ISC_LIST_NEXT(query, link) != NULL)
2433 local_timeout = SERVER_TIMEOUT;
2434 else {
2435 if (timeout == 0)
2436 local_timeout = default_timeout;
2437 else
2438 local_timeout = timeout;
2439 }
2440 debug("have local timeout of %d", local_timeout);
2441 l->interval.tv_sec = local_timeout;
2442 l->interval.tv_nsec = 0;
2443 if (query->timer != NULL)
2444 isc_timer_detach(&query->timer);
2445 result = isc_timer_create(timermgr,
2446 &l->interval, global_task, connect_timeout,
2447 query, &query->timer);
2448 check_result(result, "isc_timer_create");
2449 }
2450
2451 static void
force_timeout(dig_query_t * query)2452 force_timeout(dig_query_t *query) {
2453 isc_event_t *event;
2454
2455 debug("force_timeout ()");
2456 event = isc_event_allocate(query, ISC_TIMEREVENT_IDLE,
2457 connect_timeout, query,
2458 sizeof(isc_event_t));
2459 if (event == NULL) {
2460 fatal("isc_event_allocate: %s",
2461 isc_result_totext(ISC_R_NOMEMORY));
2462 }
2463 isc_task_send(global_task, &event);
2464
2465 /*
2466 * The timer may have expired if, for example, get_address() takes
2467 * long time and the timer was running on a different thread.
2468 * We need to cancel the possible timeout event not to confuse
2469 * ourselves due to the duplicate events.
2470 */
2471 if (query->timer != NULL)
2472 isc_timer_detach(&query->timer);
2473 }
2474
2475 static void
2476 connect_done(isc_task_t *task, isc_event_t *event);
2477
2478 /*%
2479 * Unlike send_udp, this can't be called multiple times with the same
2480 * query. When we retry TCP, we requeue the whole lookup, which should
2481 * start anew.
2482 */
2483 static void
send_tcp_connect(dig_query_t * query)2484 send_tcp_connect(dig_query_t *query) {
2485 isc_result_t result;
2486 dig_query_t *next;
2487 dig_lookup_t *l;
2488
2489 debug("send_tcp_connect(%p)", query);
2490
2491 l = query->lookup;
2492 query->waiting_connect = 1;
2493 query->lookup->current_query = query;
2494 result = get_address(query->servname, port, &query->sockaddr);
2495 if (result != ISC_R_SUCCESS) {
2496 /*
2497 * This servname doesn't have an address. Try the next server
2498 * by triggering an immediate 'timeout' (we lie, but the effect
2499 * is the same).
2500 */
2501 force_timeout(query);
2502 return;
2503 }
2504
2505 if (specified_source &&
2506 (isc_sockaddr_pf(&query->sockaddr) !=
2507 isc_sockaddr_pf(&bind_address))) {
2508 printf(";; Skipping server %s, incompatible "
2509 "address family\n", query->servname);
2510 query->waiting_connect = 0;
2511 if (ISC_LINK_LINKED(query, link))
2512 next = ISC_LIST_NEXT(query, link);
2513 else
2514 next = NULL;
2515 l = query->lookup;
2516 clear_query(query);
2517 if (next == NULL) {
2518 printf(";; No acceptable nameservers\n");
2519 check_next_lookup(l);
2520 return;
2521 }
2522 send_tcp_connect(next);
2523 return;
2524 }
2525
2526 INSIST(query->sock == NULL);
2527
2528 if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) {
2529 sockcount++;
2530 isc_socket_attach(keep, &query->sock);
2531 query->waiting_connect = 0;
2532 launch_next_query(query, 1);
2533 goto search;
2534 }
2535
2536 result = isc_socket_create(socketmgr,
2537 isc_sockaddr_pf(&query->sockaddr),
2538 isc_sockettype_tcp, &query->sock);
2539 check_result(result, "isc_socket_create");
2540 sockcount++;
2541 debug("sockcount=%d", sockcount);
2542 if (specified_source)
2543 result = isc_socket_bind(query->sock, &bind_address,
2544 ISC_SOCKET_REUSEADDRESS);
2545 else {
2546 if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
2547 have_ipv4)
2548 isc_sockaddr_any(&bind_any);
2549 else
2550 isc_sockaddr_any6(&bind_any);
2551 result = isc_socket_bind(query->sock, &bind_any, 0);
2552 }
2553 check_result(result, "isc_socket_bind");
2554 bringup_timer(query, TCP_TIMEOUT);
2555 result = isc_socket_connect(query->sock, &query->sockaddr,
2556 global_task, connect_done, query);
2557 check_result(result, "isc_socket_connect");
2558 search:
2559 /*
2560 * If we're at the endgame of a nameserver search, we need to
2561 * immediately bring up all the queries. Do it here.
2562 */
2563 if (l->ns_search_only && !l->trace_root) {
2564 debug("sending next, since searching");
2565 if (ISC_LINK_LINKED(query, link)) {
2566 next = ISC_LIST_NEXT(query, link);
2567 ISC_LIST_DEQUEUE(l->q, query, link);
2568 } else
2569 next = NULL;
2570 ISC_LIST_ENQUEUE(l->connecting, query, clink);
2571 if (next != NULL)
2572 send_tcp_connect(next);
2573 }
2574 }
2575
2576 static isc_buffer_t *
clone_buffer(isc_buffer_t * source)2577 clone_buffer(isc_buffer_t *source) {
2578 isc_buffer_t *buffer;
2579 buffer = malloc(sizeof(*buffer));
2580 if (buffer == NULL)
2581 fatal("memory allocation failure in %s:%d",
2582 __FILE__, __LINE__);
2583 *buffer = *source;
2584 return (buffer);
2585 }
2586
2587 /*%
2588 * Send a UDP packet to the remote nameserver, possible starting the
2589 * recv action as well. Also make sure that the timer is running and
2590 * is properly reset.
2591 */
2592 static void
send_udp(dig_query_t * query)2593 send_udp(dig_query_t *query) {
2594 dig_lookup_t *l = NULL;
2595 isc_result_t result;
2596 isc_buffer_t *sendbuf;
2597
2598 debug("send_udp(%p)", query);
2599
2600 l = query->lookup;
2601 bringup_timer(query, UDP_TIMEOUT);
2602 l->current_query = query;
2603 debug("working on lookup %p, query %p", query->lookup, query);
2604 if (!query->recv_made) {
2605 /* XXX Check the sense of this, need assertion? */
2606 query->waiting_connect = 0;
2607 result = get_address(query->servname, port, &query->sockaddr);
2608 if (result != ISC_R_SUCCESS) {
2609 /* This servname doesn't have an address. */
2610 force_timeout(query);
2611 return;
2612 }
2613
2614 result = isc_socket_create(socketmgr,
2615 isc_sockaddr_pf(&query->sockaddr),
2616 isc_sockettype_udp, &query->sock);
2617 check_result(result, "isc_socket_create");
2618 sockcount++;
2619 debug("sockcount=%d", sockcount);
2620 if (specified_source) {
2621 result = isc_socket_bind(query->sock, &bind_address,
2622 ISC_SOCKET_REUSEADDRESS);
2623 } else {
2624 isc_sockaddr_anyofpf(&bind_any,
2625 isc_sockaddr_pf(&query->sockaddr));
2626 result = isc_socket_bind(query->sock, &bind_any, 0);
2627 }
2628 check_result(result, "isc_socket_bind");
2629
2630 query->recv_made = 1;
2631 ISC_LINK_INIT(&query->recvbuf, link);
2632 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf,
2633 link);
2634 debug("recving with lookup=%p, query=%p, sock=%p",
2635 query->lookup, query, query->sock);
2636 result = isc_socket_recvv(query->sock, &query->recvlist, 1,
2637 global_task, recv_done, query);
2638 check_result(result, "isc_socket_recvv");
2639 recvcount++;
2640 debug("recvcount=%d", recvcount);
2641 }
2642 ISC_LIST_INIT(query->sendlist);
2643 sendbuf = clone_buffer(&query->sendbuf);
2644 ISC_LIST_ENQUEUE(query->sendlist, sendbuf, link);
2645 debug("sending a request");
2646 clock_gettime(CLOCK_MONOTONIC, &query->time_sent);
2647 INSIST(query->sock != NULL);
2648 query->waiting_senddone = 1;
2649 result = isc_socket_sendtov2(query->sock, &query->sendlist,
2650 global_task, send_done, query,
2651 &query->sockaddr, NULL,
2652 ISC_SOCKFLAG_NORETRY);
2653 check_result(result, "isc_socket_sendtov");
2654 sendcount++;
2655 }
2656
2657 /*%
2658 * IO timeout handler, used for both connect and recv timeouts. If
2659 * retries are still allowed, either resend the UDP packet or queue a
2660 * new TCP lookup. Otherwise, cancel the lookup.
2661 */
2662 static void
connect_timeout(isc_task_t * task,isc_event_t * event)2663 connect_timeout(isc_task_t *task, isc_event_t *event) {
2664 dig_lookup_t *l = NULL;
2665 dig_query_t *query = NULL, *cq;
2666
2667 UNUSED(task);
2668 REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE);
2669
2670 debug("connect_timeout()");
2671
2672 query = event->ev_arg;
2673 l = query->lookup;
2674 isc_event_free(&event);
2675
2676 INSIST(!free_now);
2677
2678 if ((query != NULL) && (query->lookup->current_query != NULL) &&
2679 ISC_LINK_LINKED(query->lookup->current_query, link) &&
2680 (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) {
2681 debug("trying next server...");
2682 cq = query->lookup->current_query;
2683 if (!l->tcp_mode)
2684 send_udp(ISC_LIST_NEXT(cq, link));
2685 else {
2686 if (query->sock != NULL)
2687 isc_socket_cancel(query->sock, NULL,
2688 ISC_SOCKCANCEL_ALL);
2689 send_tcp_connect(ISC_LIST_NEXT(cq, link));
2690 }
2691 return;
2692 }
2693
2694 if (l->tcp_mode && query->sock != NULL) {
2695 query->timedout = 1;
2696 isc_socket_cancel(query->sock, NULL, ISC_SOCKCANCEL_ALL);
2697 }
2698
2699 if (l->retries > 1) {
2700 if (!l->tcp_mode) {
2701 l->retries--;
2702 debug("resending UDP request to first server");
2703 send_udp(ISC_LIST_HEAD(l->q));
2704 } else {
2705 debug("making new TCP request, %d tries left",
2706 l->retries);
2707 l->retries--;
2708 requeue_lookup(l, 1);
2709 cancel_lookup(l);
2710 check_next_lookup(l);
2711 }
2712 } else {
2713 if (!l->ns_search_only) {
2714 fputs(l->cmdline, stdout);
2715 printf(";; connection timed out; no servers could be "
2716 "reached\n");
2717 }
2718 cancel_lookup(l);
2719 check_next_lookup(l);
2720 if (exitcode < 9)
2721 exitcode = 9;
2722 }
2723 }
2724
2725 /*%
2726 * Event handler for the TCP recv which gets the length header of TCP
2727 * packets. Start the next recv of length bytes.
2728 */
2729 static void
tcp_length_done(isc_task_t * task,isc_event_t * event)2730 tcp_length_done(isc_task_t *task, isc_event_t *event) {
2731 isc_socketevent_t *sevent;
2732 isc_buffer_t *b = NULL;
2733 isc_result_t result;
2734 dig_query_t *query = NULL;
2735 dig_lookup_t *l, *n;
2736 uint16_t length;
2737
2738 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
2739 INSIST(!free_now);
2740
2741 UNUSED(task);
2742
2743 debug("tcp_length_done()");
2744
2745 sevent = (isc_socketevent_t *)event;
2746 query = event->ev_arg;
2747
2748 recvcount--;
2749 INSIST(recvcount >= 0);
2750
2751 b = ISC_LIST_HEAD(sevent->bufferlist);
2752 INSIST(b == &query->lengthbuf);
2753 ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2754
2755 if (sevent->result == ISC_R_CANCELED) {
2756 isc_event_free(&event);
2757 l = query->lookup;
2758 clear_query(query);
2759 check_next_lookup(l);
2760 return;
2761 }
2762 if (sevent->result != ISC_R_SUCCESS) {
2763 char sockstr[ISC_SOCKADDR_FORMATSIZE];
2764 isc_sockaddr_format(&query->sockaddr, sockstr,
2765 sizeof(sockstr));
2766 printf(";; communications error to %s: %s\n",
2767 sockstr, isc_result_totext(sevent->result));
2768 if (keep != NULL)
2769 isc_socket_detach(&keep);
2770 l = query->lookup;
2771 isc_socket_detach(&query->sock);
2772 sockcount--;
2773 debug("sockcount=%d", sockcount);
2774 INSIST(sockcount >= 0);
2775 if (sevent->result == ISC_R_EOF && l->eoferr == 0U) {
2776 n = requeue_lookup(l, 1);
2777 n->eoferr++;
2778 }
2779 isc_event_free(&event);
2780 clear_query(query);
2781 cancel_lookup(l);
2782 check_next_lookup(l);
2783 return;
2784 }
2785 length = isc_buffer_getuint16(b);
2786 if (length == 0) {
2787 isc_event_free(&event);
2788 launch_next_query(query, 0);
2789 return;
2790 }
2791
2792 /*
2793 * Even though the buffer was already init'ed, we need
2794 * to redo it now, to force the length we want.
2795 */
2796 isc_buffer_invalidate(&query->recvbuf);
2797 isc_buffer_init(&query->recvbuf, query->recvspace, length);
2798 ENSURE(ISC_LIST_EMPTY(query->recvlist));
2799 ISC_LINK_INIT(&query->recvbuf, link);
2800 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
2801 debug("recving with lookup=%p, query=%p", query->lookup, query);
2802 result = isc_socket_recvv(query->sock, &query->recvlist, length, task,
2803 recv_done, query);
2804 check_result(result, "isc_socket_recvv");
2805 recvcount++;
2806 debug("resubmitted recv request with length %d, recvcount=%d",
2807 length, recvcount);
2808 isc_event_free(&event);
2809 }
2810
2811 /*%
2812 * For transfers that involve multiple recvs (XFR's in particular),
2813 * launch the next recv.
2814 */
2815 static void
launch_next_query(dig_query_t * query,int include_question)2816 launch_next_query(dig_query_t *query, int include_question) {
2817 isc_result_t result;
2818 dig_lookup_t *l;
2819 isc_buffer_t *buffer;
2820
2821 INSIST(!free_now);
2822
2823 debug("launch_next_query()");
2824
2825 if (!query->lookup->pending) {
2826 debug("ignoring launch_next_query because !pending");
2827 isc_socket_detach(&query->sock);
2828 sockcount--;
2829 debug("sockcount=%d", sockcount);
2830 INSIST(sockcount >= 0);
2831 query->waiting_connect = 0;
2832 l = query->lookup;
2833 clear_query(query);
2834 check_next_lookup(l);
2835 return;
2836 }
2837
2838 isc_buffer_clear(&query->slbuf);
2839 isc_buffer_clear(&query->lengthbuf);
2840 isc_buffer_putuint16(&query->slbuf, (uint16_t) query->sendbuf.used);
2841 ISC_LIST_INIT(query->sendlist);
2842 ISC_LINK_INIT(&query->slbuf, link);
2843 if (!query->first_soa_rcvd) {
2844 buffer = clone_buffer(&query->slbuf);
2845 ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
2846 if (include_question) {
2847 buffer = clone_buffer(&query->sendbuf);
2848 ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
2849 }
2850 }
2851
2852 ISC_LINK_INIT(&query->lengthbuf, link);
2853 ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
2854
2855 result = isc_socket_recvv(query->sock, &query->lengthlist, 0,
2856 global_task, tcp_length_done, query);
2857 check_result(result, "isc_socket_recvv");
2858 recvcount++;
2859 debug("recvcount=%d", recvcount);
2860 if (!query->first_soa_rcvd) {
2861 debug("sending a request in launch_next_query");
2862 clock_gettime(CLOCK_MONOTONIC, &query->time_sent);
2863 query->waiting_senddone = 1;
2864 result = isc_socket_sendv(query->sock, &query->sendlist,
2865 global_task, send_done, query);
2866 check_result(result, "isc_socket_sendv");
2867 sendcount++;
2868 debug("sendcount=%d", sendcount);
2869 }
2870 query->waiting_connect = 0;
2871 return;
2872 }
2873
2874 /*%
2875 * Event handler for TCP connect complete. Make sure the connection was
2876 * successful, then pass into launch_next_query to actually send the
2877 * question.
2878 */
2879 static void
connect_done(isc_task_t * task,isc_event_t * event)2880 connect_done(isc_task_t *task, isc_event_t *event) {
2881 char sockstr[ISC_SOCKADDR_FORMATSIZE];
2882 isc_socketevent_t *sevent = NULL;
2883 dig_query_t *query = NULL, *next;
2884 dig_lookup_t *l;
2885
2886 UNUSED(task);
2887
2888 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
2889 INSIST(!free_now);
2890
2891 debug("connect_done()");
2892
2893 sevent = (isc_socketevent_t *)event;
2894 query = sevent->ev_arg;
2895
2896 INSIST(query->waiting_connect);
2897
2898 query->waiting_connect = 0;
2899
2900 if (sevent->result == ISC_R_CANCELED) {
2901 debug("in cancel handler");
2902 isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
2903 if (query->timedout)
2904 printf(";; Connection to %s(%s) for %s failed: %s.\n",
2905 sockstr, query->servname,
2906 query->lookup->textname,
2907 isc_result_totext(ISC_R_TIMEDOUT));
2908 isc_socket_detach(&query->sock);
2909 INSIST(sockcount > 0);
2910 sockcount--;
2911 debug("sockcount=%d", sockcount);
2912 query->waiting_connect = 0;
2913 isc_event_free(&event);
2914 l = query->lookup;
2915 clear_query(query);
2916 check_next_lookup(l);
2917 return;
2918 }
2919 if (sevent->result != ISC_R_SUCCESS) {
2920
2921 debug("unsuccessful connection: %s",
2922 isc_result_totext(sevent->result));
2923 isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
2924 if (sevent->result != ISC_R_CANCELED)
2925 printf(";; Connection to %s(%s) for %s failed: "
2926 "%s.\n", sockstr,
2927 query->servname, query->lookup->textname,
2928 isc_result_totext(sevent->result));
2929 isc_socket_detach(&query->sock);
2930 INSIST(sockcount > 0);
2931 sockcount--;
2932 /* XXX Clean up exitcodes */
2933 if (exitcode < 9)
2934 exitcode = 9;
2935 debug("sockcount=%d", sockcount);
2936 query->waiting_connect = 0;
2937 isc_event_free(&event);
2938 l = query->lookup;
2939 if ((l->current_query != NULL) &&
2940 (ISC_LINK_LINKED(l->current_query, link)))
2941 next = ISC_LIST_NEXT(l->current_query, link);
2942 else
2943 next = NULL;
2944 clear_query(query);
2945 if (next != NULL) {
2946 bringup_timer(next, TCP_TIMEOUT);
2947 send_tcp_connect(next);
2948 } else
2949 check_next_lookup(l);
2950 return;
2951 }
2952 if (keep_open) {
2953 if (keep != NULL)
2954 isc_socket_detach(&keep);
2955 isc_socket_attach(query->sock, &keep);
2956 keepaddr = query->sockaddr;
2957 }
2958 launch_next_query(query, 1);
2959 isc_event_free(&event);
2960 }
2961
2962 /*%
2963 * Check if the ongoing XFR needs more data before it's complete, using
2964 * the semantics of IXFR and AXFR protocols. Much of the complexity of
2965 * this routine comes from determining when an IXFR is complete.
2966 * 0 means more data is on the way, and the recv has been issued.
2967 */
2968 static int
check_for_more_data(dig_query_t * query,dns_message_t * msg,isc_socketevent_t * sevent)2969 check_for_more_data(dig_query_t *query, dns_message_t *msg,
2970 isc_socketevent_t *sevent)
2971 {
2972 dns_rdataset_t *rdataset = NULL;
2973 dns_rdata_t rdata = DNS_RDATA_INIT;
2974 dns_rdata_soa_t soa;
2975 uint32_t ixfr_serial = query->lookup->ixfr_serial, serial;
2976 isc_result_t result;
2977 int ixfr = query->lookup->rdtype == dns_rdatatype_ixfr;
2978 int axfr = query->lookup->rdtype == dns_rdatatype_axfr;
2979
2980 if (ixfr)
2981 axfr = query->ixfr_axfr;
2982
2983 debug("check_for_more_data()");
2984
2985 /*
2986 * By the time we're in this routine, we know we're doing
2987 * either an AXFR or IXFR. If there's no second_rr_type,
2988 * then we don't yet know which kind of answer we got back
2989 * from the server. Here, we're going to walk through the
2990 * rr's in the message, acting as necessary whenever we hit
2991 * an SOA rr.
2992 */
2993
2994 query->msg_count++;
2995 query->byte_count += sevent->n;
2996 result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
2997 if (result != ISC_R_SUCCESS) {
2998 puts("; Transfer failed.");
2999 return (1);
3000 }
3001 do {
3002 dns_name_t *name;
3003 name = NULL;
3004 dns_message_currentname(msg, DNS_SECTION_ANSWER,
3005 &name);
3006 for (rdataset = ISC_LIST_HEAD(name->list);
3007 rdataset != NULL;
3008 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3009 result = dns_rdataset_first(rdataset);
3010 if (result != ISC_R_SUCCESS)
3011 continue;
3012 do {
3013 query->rr_count++;
3014 dns_rdata_reset(&rdata);
3015 dns_rdataset_current(rdataset, &rdata);
3016 /*
3017 * If this is the first rr, make sure
3018 * it's an SOA
3019 */
3020 if ((!query->first_soa_rcvd) &&
3021 (rdata.type != dns_rdatatype_soa)) {
3022 puts("; Transfer failed. "
3023 "Didn't start with SOA answer.");
3024 return (1);
3025 }
3026 if ((!query->second_rr_rcvd) &&
3027 (rdata.type != dns_rdatatype_soa)) {
3028 query->second_rr_rcvd = 1;
3029 query->second_rr_serial = 0;
3030 debug("got the second rr as nonsoa");
3031 axfr = query->ixfr_axfr = 1;
3032 goto next_rdata;
3033 }
3034
3035 /*
3036 * If the record is anything except an SOA
3037 * now, just continue on...
3038 */
3039 if (rdata.type != dns_rdatatype_soa)
3040 goto next_rdata;
3041
3042 /* Now we have an SOA. Work with it. */
3043 debug("got an SOA");
3044 result = dns_rdata_tostruct_soa(&rdata, &soa);
3045 check_result(result, "dns_rdata_tostruct_soa");
3046 serial = soa.serial;
3047 dns_rdata_freestruct_soa(&soa);
3048 if (!query->first_soa_rcvd) {
3049 query->first_soa_rcvd = 1;
3050 query->first_rr_serial = serial;
3051 debug("this is the first serial %u",
3052 serial);
3053 if (ixfr && isc_serial_ge(ixfr_serial,
3054 serial)) {
3055 debug("got up to date "
3056 "response");
3057 goto doexit;
3058 }
3059 goto next_rdata;
3060 }
3061 if (axfr) {
3062 debug("doing axfr, got second SOA");
3063 goto doexit;
3064 }
3065 if (!query->second_rr_rcvd) {
3066 if (query->first_rr_serial == serial) {
3067 debug("doing ixfr, got "
3068 "empty zone");
3069 goto doexit;
3070 }
3071 debug("this is the second serial %u",
3072 serial);
3073 query->second_rr_rcvd = 1;
3074 query->second_rr_serial = serial;
3075 goto next_rdata;
3076 }
3077 /*
3078 * If we get to this point, we're doing an
3079 * IXFR and have to start really looking
3080 * at serial numbers.
3081 */
3082 if (query->first_rr_serial == serial) {
3083 debug("got a match for ixfr");
3084 if (!query->first_repeat_rcvd) {
3085 query->first_repeat_rcvd =
3086 1;
3087 goto next_rdata;
3088 }
3089 debug("done with ixfr");
3090 goto doexit;
3091 }
3092 debug("meaningless soa %u", serial);
3093 next_rdata:
3094 result = dns_rdataset_next(rdataset);
3095 } while (result == ISC_R_SUCCESS);
3096 }
3097 result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
3098 } while (result == ISC_R_SUCCESS);
3099 launch_next_query(query, 0);
3100 return (0);
3101 doexit:
3102 dighost_received(sevent->n, &sevent->address, query);
3103 return (1);
3104 }
3105
3106 static void
process_sit(dig_lookup_t * l,dns_message_t * msg,isc_buffer_t * optbuf,size_t optlen)3107 process_sit(dig_lookup_t *l, dns_message_t *msg,
3108 isc_buffer_t *optbuf, size_t optlen)
3109 {
3110 char bb[256];
3111 isc_buffer_t hexbuf;
3112 size_t len;
3113 const unsigned char *sit;
3114 int copysit;
3115 isc_result_t result;
3116
3117 if (l->sitvalue != NULL) {
3118 isc_buffer_init(&hexbuf, bb, sizeof(bb));
3119 result = isc_hex_decodestring(l->sitvalue, &hexbuf);
3120 check_result(result, "isc_hex_decodestring");
3121 sit = isc_buffer_base(&hexbuf);
3122 len = isc_buffer_usedlength(&hexbuf);
3123 copysit = 0;
3124 } else {
3125 sit = cookie;
3126 len = sizeof(cookie);
3127 copysit = 1;
3128 }
3129
3130 INSIST(msg->sitok == 0 && msg->sitbad == 0);
3131 if (optlen >= len && optlen >= 8U) {
3132 if (timingsafe_bcmp(isc_buffer_current(optbuf), sit, 8) == 0) {
3133 msg->sitok = 1;
3134 } else {
3135 printf(";; Warning: SIT client cookie mismatch\n");
3136 msg->sitbad = 1;
3137 copysit = 0;
3138 }
3139 } else {
3140 printf(";; Warning: SIT bad token (too short)\n");
3141 msg->sitbad = 1;
3142 copysit = 0;
3143 }
3144 if (copysit) {
3145 isc_region_t r;
3146
3147 r.base = isc_buffer_current(optbuf);
3148 r.length = (unsigned int)optlen;
3149 isc_buffer_init(&hexbuf, sitvalue, sizeof(sitvalue));
3150 result = isc_hex_totext(&r, 2, "", &hexbuf);
3151 check_result(result, "isc_hex_totext");
3152 if (isc_buffer_availablelength(&hexbuf) > 0) {
3153 isc_buffer_putuint8(&hexbuf, 0);
3154 l->sitvalue = sitvalue;
3155 }
3156 }
3157 isc_buffer_forward(optbuf, (unsigned int)optlen);
3158 }
3159
3160 static void
process_opt(dig_lookup_t * l,dns_message_t * msg)3161 process_opt(dig_lookup_t *l, dns_message_t *msg) {
3162 dns_rdata_t rdata;
3163 isc_result_t result;
3164 isc_buffer_t optbuf;
3165 uint16_t optcode, optlen;
3166 dns_rdataset_t *opt = msg->opt;
3167 int seen_cookie = 0;
3168
3169 result = dns_rdataset_first(opt);
3170 if (result == ISC_R_SUCCESS) {
3171 dns_rdata_init(&rdata);
3172 dns_rdataset_current(opt, &rdata);
3173 isc_buffer_init(&optbuf, rdata.data, rdata.length);
3174 isc_buffer_add(&optbuf, rdata.length);
3175 while (isc_buffer_remaininglength(&optbuf) >= 4) {
3176 optcode = isc_buffer_getuint16(&optbuf);
3177 optlen = isc_buffer_getuint16(&optbuf);
3178 switch (optcode) {
3179 case DNS_OPT_COOKIE:
3180 /*
3181 * Only process the first cookie option.
3182 */
3183 if (seen_cookie) {
3184 isc_buffer_forward(&optbuf, optlen);
3185 break;
3186 }
3187 process_sit(l, msg, &optbuf, optlen);
3188 seen_cookie = 1;
3189 break;
3190 default:
3191 isc_buffer_forward(&optbuf, optlen);
3192 break;
3193 }
3194 }
3195 }
3196 }
3197
3198 static int
ednsvers(dns_rdataset_t * opt)3199 ednsvers(dns_rdataset_t *opt) {
3200 return ((opt->ttl >> 16) & 0xff);
3201 }
3202
3203 /*%
3204 * Event handler for recv complete. Perform whatever actions are necessary,
3205 * based on the specifics of the user's request.
3206 */
3207 static void
recv_done(isc_task_t * task,isc_event_t * event)3208 recv_done(isc_task_t *task, isc_event_t *event) {
3209 isc_socketevent_t *sevent = NULL;
3210 dig_query_t *query = NULL;
3211 isc_buffer_t *b = NULL;
3212 dns_message_t *msg = NULL;
3213 isc_result_t result;
3214 dig_lookup_t *n, *l;
3215 int docancel = 0;
3216 int match = 1;
3217 unsigned int parseflags;
3218 dns_messageid_t id;
3219 unsigned int msgflags;
3220 int newedns;
3221
3222 UNUSED(task);
3223 INSIST(!free_now);
3224
3225 debug("recv_done()");
3226
3227 recvcount--;
3228 debug("recvcount=%d", recvcount);
3229 INSIST(recvcount >= 0);
3230
3231 query = event->ev_arg;
3232 clock_gettime(CLOCK_MONOTONIC, &query->time_recv);
3233 debug("lookup=%p, query=%p", query->lookup, query);
3234
3235 l = query->lookup;
3236
3237 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
3238 sevent = (isc_socketevent_t *)event;
3239
3240 b = ISC_LIST_HEAD(sevent->bufferlist);
3241 INSIST(b == &query->recvbuf);
3242 ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link);
3243
3244 if ((l->tcp_mode) && (query->timer != NULL))
3245 isc_timer_touch(query->timer);
3246 if ((!l->pending && !l->ns_search_only) || cancel_now) {
3247 debug("no longer pending. Got %s",
3248 isc_result_totext(sevent->result));
3249 query->waiting_connect = 0;
3250
3251 isc_event_free(&event);
3252 clear_query(query);
3253 check_next_lookup(l);
3254 return;
3255 }
3256
3257 if (sevent->result != ISC_R_SUCCESS) {
3258 if (sevent->result == ISC_R_CANCELED) {
3259 debug("in recv cancel handler");
3260 query->waiting_connect = 0;
3261 } else {
3262 printf(";; communications error: %s\n",
3263 isc_result_totext(sevent->result));
3264 if (keep != NULL)
3265 isc_socket_detach(&keep);
3266 isc_socket_detach(&query->sock);
3267 sockcount--;
3268 debug("sockcount=%d", sockcount);
3269 INSIST(sockcount >= 0);
3270 }
3271 if (sevent->result == ISC_R_EOF && l->eoferr == 0U) {
3272 n = requeue_lookup(l, 1);
3273 n->eoferr++;
3274 }
3275 isc_event_free(&event);
3276 clear_query(query);
3277 cancel_lookup(l);
3278 check_next_lookup(l);
3279 return;
3280 }
3281
3282 if (!l->tcp_mode &&
3283 !isc_sockaddr_compare(&sevent->address, &query->sockaddr,
3284 ISC_SOCKADDR_CMPADDR|
3285 ISC_SOCKADDR_CMPPORT|
3286 ISC_SOCKADDR_CMPSCOPE|
3287 ISC_SOCKADDR_CMPSCOPEZERO)) {
3288 char buf1[ISC_SOCKADDR_FORMATSIZE];
3289 char buf2[ISC_SOCKADDR_FORMATSIZE];
3290 struct sockaddr_storage any;
3291
3292 if (isc_sockaddr_pf(&query->sockaddr) == AF_INET)
3293 isc_sockaddr_any(&any);
3294 else
3295 isc_sockaddr_any6(&any);
3296
3297 /*
3298 * We don't expect a match when the packet is
3299 * sent to 0.0.0.0, :: or to a multicast addresses.
3300 * XXXMPA broadcast needs to be handled here as well.
3301 */
3302 if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) &&
3303 !isc_sockaddr_ismulticast(&query->sockaddr)) ||
3304 isc_sockaddr_getport(&query->sockaddr) !=
3305 isc_sockaddr_getport(&sevent->address)) {
3306 isc_sockaddr_format(&sevent->address, buf1,
3307 sizeof(buf1));
3308 isc_sockaddr_format(&query->sockaddr, buf2,
3309 sizeof(buf2));
3310 printf(";; reply from unexpected source: %s,"
3311 " expected %s\n", buf1, buf2);
3312 match = 0;
3313 }
3314 }
3315
3316 result = dns_message_peekheader(b, &id, &msgflags);
3317 if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
3318 match = 0;
3319 if (l->tcp_mode) {
3320 int fail = 1;
3321 if (result == ISC_R_SUCCESS) {
3322 if (!query->first_soa_rcvd ||
3323 query->warn_id)
3324 printf(";; %s: ID mismatch: "
3325 "expected ID %u, got %u\n",
3326 query->first_soa_rcvd ?
3327 "WARNING" : "ERROR",
3328 l->sendmsg->id, id);
3329 if (query->first_soa_rcvd)
3330 fail = 0;
3331 query->warn_id = 0;
3332 } else
3333 printf(";; ERROR: short "
3334 "(< header size) message\n");
3335 if (fail) {
3336 isc_event_free(&event);
3337 clear_query(query);
3338 cancel_lookup(l);
3339 check_next_lookup(l);
3340 return;
3341 }
3342 match = 1;
3343 } else if (result == ISC_R_SUCCESS)
3344 printf(";; Warning: ID mismatch: "
3345 "expected ID %u, got %u\n", l->sendmsg->id, id);
3346 else
3347 printf(";; Warning: short "
3348 "(< header size) message received\n");
3349 }
3350
3351 if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0)
3352 printf(";; Warning: query response not set\n");
3353
3354 if (!match)
3355 goto udp_mismatch;
3356
3357 result = dns_message_create(DNS_MESSAGE_INTENTPARSE, &msg);
3358 check_result(result, "dns_message_create");
3359
3360 if (tsigkey != NULL) {
3361 if (l->querysig == NULL) {
3362 debug("getting initial querysig");
3363 result = dns_message_getquerytsig(l->sendmsg,
3364 &l->querysig);
3365 check_result(result, "dns_message_getquerytsig");
3366 }
3367 result = dns_message_setquerytsig(msg, l->querysig);
3368 check_result(result, "dns_message_setquerytsig");
3369 result = dns_message_settsigkey(msg, tsigkey);
3370 check_result(result, "dns_message_settsigkey");
3371 msg->tsigctx = l->tsigctx;
3372 l->tsigctx = NULL;
3373 if (l->msgcounter != 0)
3374 msg->tcp_continuation = 1;
3375 l->msgcounter++;
3376 }
3377
3378 debug("before parse starts");
3379 parseflags = 0;
3380 if (l->besteffort) {
3381 parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
3382 parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
3383 }
3384 result = dns_message_parse(msg, b, parseflags);
3385 if (result == DNS_R_RECOVERABLE) {
3386 printf(";; Warning: Message parser reports malformed "
3387 "message packet.\n");
3388 result = ISC_R_SUCCESS;
3389 }
3390 if (result != ISC_R_SUCCESS) {
3391 printf(";; Got bad packet: %s\n", isc_result_totext(result));
3392 hex_dump(b);
3393 query->waiting_connect = 0;
3394 dns_message_destroy(&msg);
3395 isc_event_free(&event);
3396 clear_query(query);
3397 cancel_lookup(l);
3398 check_next_lookup(l);
3399 return;
3400 }
3401 if (msg->counts[DNS_SECTION_QUESTION] != 0) {
3402 match = 1;
3403 for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
3404 result == ISC_R_SUCCESS && match;
3405 result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) {
3406 dns_name_t *name = NULL;
3407 dns_rdataset_t *rdataset;
3408
3409 dns_message_currentname(msg, DNS_SECTION_QUESTION,
3410 &name);
3411 for (rdataset = ISC_LIST_HEAD(name->list);
3412 rdataset != NULL;
3413 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3414 if (l->rdtype != rdataset->type ||
3415 l->rdclass != rdataset->rdclass ||
3416 !dns_name_equal(l->name, name)) {
3417 char namestr[DNS_NAME_FORMATSIZE];
3418 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3419 char classbuf[DNS_RDATACLASS_FORMATSIZE];
3420 dns_name_format(name, namestr,
3421 sizeof(namestr));
3422 dns_rdatatype_format(rdataset->type,
3423 typebuf,
3424 sizeof(typebuf));
3425 dns_rdataclass_format(rdataset->rdclass,
3426 classbuf,
3427 sizeof(classbuf));
3428 printf(";; Question section mismatch: "
3429 "got %s/%s/%s\n",
3430 namestr, typebuf, classbuf);
3431 match = 0;
3432 }
3433 }
3434 }
3435 if (!match) {
3436 dns_message_destroy(&msg);
3437 if (l->tcp_mode) {
3438 isc_event_free(&event);
3439 clear_query(query);
3440 cancel_lookup(l);
3441 check_next_lookup(l);
3442 return;
3443 } else
3444 goto udp_mismatch;
3445 }
3446 }
3447 if (msg->rcode == dns_rcode_badvers && msg->opt != NULL &&
3448 (newedns = ednsvers(msg->opt)) < l->edns && l->ednsneg) {
3449 /*
3450 * Add minimum EDNS version required checks here if needed.
3451 */
3452 if (l->comments)
3453 printf(";; BADVERS, retrying with EDNS version %u.\n",
3454 (unsigned int)newedns);
3455 l->edns = newedns;
3456 n = requeue_lookup(l, 1);
3457 if (l->trace && l->trace_root)
3458 n->rdtype = l->qrdtype;
3459 dns_message_destroy(&msg);
3460 isc_event_free(&event);
3461 clear_query(query);
3462 cancel_lookup(l);
3463 check_next_lookup(l);
3464 return;
3465 }
3466 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 &&
3467 !l->ignore && !l->tcp_mode) {
3468 if (l->sitvalue == NULL && l->sit && msg->opt != NULL)
3469 process_opt(l, msg);
3470 if (l->comments)
3471 printf(";; Truncated, retrying in TCP mode.\n");
3472 n = requeue_lookup(l, 1);
3473 n->tcp_mode = 1;
3474 if (l->trace && l->trace_root)
3475 n->rdtype = l->qrdtype;
3476 dns_message_destroy(&msg);
3477 isc_event_free(&event);
3478 clear_query(query);
3479 cancel_lookup(l);
3480 check_next_lookup(l);
3481 return;
3482 }
3483 if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) ||
3484 (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse))
3485 {
3486 dig_query_t *next = ISC_LIST_NEXT(query, link);
3487 if (l->current_query == query)
3488 l->current_query = NULL;
3489 if (next != NULL) {
3490 debug("sending query %p\n", next);
3491 if (l->tcp_mode)
3492 send_tcp_connect(next);
3493 else
3494 send_udp(next);
3495 }
3496 /*
3497 * If our query is at the head of the list and there
3498 * is no next, we're the only one left, so fall
3499 * through to print the message.
3500 */
3501 if ((ISC_LIST_HEAD(l->q) != query) ||
3502 (ISC_LIST_NEXT(query, link) != NULL)) {
3503 if (l->comments)
3504 printf(";; Got %s from %s, "
3505 "trying next server\n",
3506 msg->rcode == dns_rcode_servfail ?
3507 "SERVFAIL reply" :
3508 "recursion not available",
3509 query->servname);
3510 clear_query(query);
3511 check_next_lookup(l);
3512 dns_message_destroy(&msg);
3513 isc_event_free(&event);
3514 return;
3515 }
3516 }
3517
3518 if (tsigkey != NULL) {
3519 result = dns_tsig_verify(&query->recvbuf, msg);
3520 if (result != ISC_R_SUCCESS) {
3521 printf(";; Couldn't verify signature: %s\n",
3522 isc_result_totext(result));
3523 validated = 0;
3524 }
3525 l->tsigctx = msg->tsigctx;
3526 msg->tsigctx = NULL;
3527 if (l->querysig != NULL) {
3528 debug("freeing querysig buffer %p", l->querysig);
3529 isc_buffer_free(&l->querysig);
3530 }
3531 result = dns_message_getquerytsig(msg, &l->querysig);
3532 check_result(result,"dns_message_getquerytsig");
3533 }
3534
3535 extrabytes = isc_buffer_remaininglength(b);
3536
3537 debug("after parse");
3538 if (l->doing_xfr && l->xfr_q == NULL) {
3539 l->xfr_q = query;
3540 /*
3541 * Once we are in the XFR message, increase
3542 * the timeout to much longer, so brief network
3543 * outages won't cause the XFR to abort
3544 */
3545 if (timeout != INT_MAX && query->timer != NULL) {
3546 unsigned int local_timeout;
3547
3548 if (timeout == 0) {
3549 if (l->tcp_mode)
3550 local_timeout = TCP_TIMEOUT * 4;
3551 else
3552 local_timeout = UDP_TIMEOUT * 4;
3553 } else {
3554 if (timeout < (INT_MAX / 4))
3555 local_timeout = timeout * 4;
3556 else
3557 local_timeout = INT_MAX;
3558 }
3559 debug("have local timeout of %d", local_timeout);
3560 l->interval.tv_sec = local_timeout;
3561 l->interval.tv_nsec = 0;
3562 result = isc_timer_reset(query->timer,
3563 &l->interval,
3564 0);
3565 check_result(result, "isc_timer_reset");
3566 }
3567 }
3568
3569 if (l->sitvalue != NULL) {
3570 if (msg->opt == NULL)
3571 printf(";; expected opt record in response\n");
3572 else
3573 process_opt(l, msg);
3574 } else if (l->sit && msg->opt != NULL)
3575 process_opt(l, msg);
3576
3577 if (!l->doing_xfr || l->xfr_q == query) {
3578 if (msg->rcode == dns_rcode_nxdomain &&
3579 (l->origin != NULL || l->need_search)) {
3580 if (!next_origin(query->lookup) || showsearch) {
3581 dighost_printmessage(query, msg, 1);
3582 dighost_received(b->used, &sevent->address, query);
3583 }
3584 } else if (!l->trace && !l->ns_search_only) {
3585 dighost_printmessage(query, msg, 1);
3586 } else if (l->trace) {
3587 int nl = 0;
3588 int count = msg->counts[DNS_SECTION_ANSWER];
3589
3590 debug("in TRACE code");
3591 if (!l->ns_search_only)
3592 dighost_printmessage(query, msg, 1);
3593
3594 l->rdtype = l->qrdtype;
3595 if (l->trace_root || (l->ns_search_only && count > 0)) {
3596 if (!l->trace_root)
3597 l->rdtype = dns_rdatatype_soa;
3598 nl = followup_lookup(msg, query,
3599 DNS_SECTION_ANSWER);
3600 l->trace_root = 0;
3601 } else if (count == 0)
3602 nl = followup_lookup(msg, query,
3603 DNS_SECTION_AUTHORITY);
3604 if (nl == 0)
3605 docancel = 1;
3606 } else {
3607 debug("in NSSEARCH code");
3608
3609 if (l->trace_root) {
3610 /*
3611 * This is the initial NS query.
3612 */
3613 int nl;
3614
3615 l->rdtype = dns_rdatatype_soa;
3616 nl = followup_lookup(msg, query,
3617 DNS_SECTION_ANSWER);
3618 if (nl == 0)
3619 docancel = 1;
3620 l->trace_root = 0;
3621 usesearch = 0;
3622 } else
3623 dighost_printmessage(query, msg, 1);
3624 }
3625 }
3626
3627 if (l->pending)
3628 debug("still pending.");
3629 if (l->doing_xfr) {
3630 if (query != l->xfr_q) {
3631 dns_message_destroy(&msg);
3632 isc_event_free(&event);
3633 query->waiting_connect = 0;
3634 return;
3635 }
3636 if (!docancel)
3637 docancel = check_for_more_data(query, msg, sevent);
3638 if (docancel) {
3639 dns_message_destroy(&msg);
3640 clear_query(query);
3641 cancel_lookup(l);
3642 check_next_lookup(l);
3643 }
3644 } else {
3645
3646 if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
3647 dighost_received(b->used, &sevent->address, query);
3648 }
3649
3650 if (!query->lookup->ns_search_only)
3651 query->lookup->pending = 0;
3652 if (!query->lookup->ns_search_only ||
3653 query->lookup->trace_root || docancel) {
3654 dns_message_destroy(&msg);
3655
3656 cancel_lookup(l);
3657 }
3658 clear_query(query);
3659 check_next_lookup(l);
3660 }
3661 if (msg != NULL) {
3662 dns_message_destroy(&msg);
3663 }
3664 isc_event_free(&event);
3665 return;
3666
3667 udp_mismatch:
3668 isc_buffer_invalidate(&query->recvbuf);
3669 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
3670 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
3671 result = isc_socket_recvv(query->sock, &query->recvlist, 1,
3672 global_task, recv_done, query);
3673 check_result(result, "isc_socket_recvv");
3674 recvcount++;
3675 isc_event_free(&event);
3676 return;
3677 }
3678
3679 /*%
3680 * Turn a name into an address, using system-supplied routines. This is
3681 * used in looking up server names, etc... and needs to use system-supplied
3682 * routines, since they may be using a non-DNS system for these lookups.
3683 */
3684 isc_result_t
get_address(char * host,in_port_t myport,struct sockaddr_storage * sockaddr)3685 get_address(char *host, in_port_t myport, struct sockaddr_storage *sockaddr) {
3686 int count;
3687 isc_result_t result;
3688
3689 result = get_addresses(host, myport, sockaddr, 1, &count);
3690 if (result != ISC_R_SUCCESS)
3691 return (result);
3692
3693 INSIST(count == 1);
3694
3695 return (ISC_R_SUCCESS);
3696 }
3697
3698 int
getaddresses(dig_lookup_t * lookup,const char * host,isc_result_t * resultp)3699 getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) {
3700 isc_result_t result;
3701 struct sockaddr_storage sockaddrs[DIG_MAX_ADDRESSES];
3702 int count, i;
3703 dig_server_t *srv;
3704 char tmp[NI_MAXHOST];
3705
3706 result = get_addresses(host, 0, sockaddrs,
3707 DIG_MAX_ADDRESSES, &count);
3708 if (resultp != NULL)
3709 *resultp = result;
3710 if (result != ISC_R_SUCCESS) {
3711 if (resultp == NULL)
3712 fatal("couldn't get address for '%s': %s",
3713 host, isc_result_totext(result));
3714 return (0);
3715 }
3716
3717 for (i = 0; i < count; i++) {
3718 int error;
3719 error = getnameinfo((struct sockaddr *)&sockaddrs[i],
3720 sockaddrs[i].ss_len, tmp, sizeof(tmp), NULL, 0,
3721 NI_NUMERICHOST | NI_NUMERICSERV);
3722 if (error)
3723 fatal("%s", gai_strerror(error));
3724
3725 srv = make_server(tmp, host);
3726 ISC_LIST_APPEND(lookup->my_server_list, srv, link);
3727 }
3728
3729 return (count);
3730 }
3731
3732 /*%
3733 * Initiate either a TCP or UDP lookup
3734 */
3735 void
do_lookup(dig_lookup_t * lookup)3736 do_lookup(dig_lookup_t *lookup) {
3737 dig_query_t *query;
3738
3739 REQUIRE(lookup != NULL);
3740
3741 debug("do_lookup()");
3742 lookup->pending = 1;
3743 query = ISC_LIST_HEAD(lookup->q);
3744 if (query != NULL) {
3745 if (lookup->tcp_mode)
3746 send_tcp_connect(query);
3747 else
3748 send_udp(query);
3749 }
3750 }
3751
3752 /*%
3753 * Start everything in action upon task startup.
3754 */
3755 void
onrun_callback(isc_task_t * task,isc_event_t * event)3756 onrun_callback(isc_task_t *task, isc_event_t *event) {
3757 UNUSED(task);
3758
3759 isc_event_free(&event);
3760 start_lookup();
3761 }
3762
3763 /*%
3764 * Make everything on the lookup queue go away. Mainly used by the
3765 * SIGINT handler.
3766 */
3767 void
cancel_all(void)3768 cancel_all(void) {
3769 dig_lookup_t *l, *n;
3770 dig_query_t *q, *nq;
3771
3772 debug("cancel_all()");
3773
3774 if (free_now) {
3775 return;
3776 }
3777 cancel_now = 1;
3778 if (current_lookup != NULL) {
3779 for (q = ISC_LIST_HEAD(current_lookup->q);
3780 q != NULL;
3781 q = nq)
3782 {
3783 nq = ISC_LIST_NEXT(q, link);
3784 debug("canceling pending query %p, belonging to %p",
3785 q, current_lookup);
3786 if (q->sock != NULL)
3787 isc_socket_cancel(q->sock, NULL,
3788 ISC_SOCKCANCEL_ALL);
3789 else
3790 clear_query(q);
3791 }
3792 for (q = ISC_LIST_HEAD(current_lookup->connecting);
3793 q != NULL;
3794 q = nq)
3795 {
3796 nq = ISC_LIST_NEXT(q, clink);
3797 debug("canceling connecting query %p, belonging to %p",
3798 q, current_lookup);
3799 if (q->sock != NULL)
3800 isc_socket_cancel(q->sock, NULL,
3801 ISC_SOCKCANCEL_ALL);
3802 else
3803 clear_query(q);
3804 }
3805 }
3806 l = ISC_LIST_HEAD(lookup_list);
3807 while (l != NULL) {
3808 n = ISC_LIST_NEXT(l, link);
3809 ISC_LIST_DEQUEUE(lookup_list, l, link);
3810 try_clear_lookup(l);
3811 l = n;
3812 }
3813 }
3814
3815 /*%
3816 * Destroy all of the libs we are using, and get everything ready for a
3817 * clean shutdown.
3818 */
3819 void
destroy_libs(void)3820 destroy_libs(void) {
3821
3822 if (keep != NULL)
3823 isc_socket_detach(&keep);
3824 debug("destroy_libs()");
3825 if (global_task != NULL) {
3826 debug("freeing task");
3827 isc_task_detach(&global_task);
3828 }
3829 /*
3830 * The taskmgr_destroy() call blocks until all events are cleared
3831 * from the task.
3832 */
3833 if (taskmgr != NULL) {
3834 debug("freeing taskmgr");
3835 isc_taskmgr_destroy(&taskmgr);
3836 }
3837 REQUIRE(sockcount == 0);
3838 REQUIRE(recvcount == 0);
3839 REQUIRE(sendcount == 0);
3840
3841 INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
3842 INSIST(current_lookup == NULL);
3843 INSIST(!free_now);
3844
3845 free_now = 1;
3846
3847 lwres_conf_clear(lwconf);
3848
3849 flush_server_list();
3850
3851 clear_searchlist();
3852
3853 if (socketmgr != NULL) {
3854 debug("freeing socketmgr");
3855 isc_socketmgr_destroy(&socketmgr);
3856 }
3857 if (timermgr != NULL) {
3858 debug("freeing timermgr");
3859 isc_timermgr_destroy(&timermgr);
3860 }
3861 if (tsigkey != NULL) {
3862 debug("freeing key %p", tsigkey);
3863 dns_tsigkey_detach(&tsigkey);
3864 }
3865 if (namebuf != NULL)
3866 isc_buffer_free(&namebuf);
3867
3868 if (is_dst_up) {
3869 debug("destroy DST lib");
3870 dst_lib_destroy();
3871 is_dst_up = 0;
3872 }
3873
3874 debug("Removing log context");
3875 isc_log_destroy(&lctx);
3876
3877 }
3878
3879 int64_t
uelapsed(const struct timespec * t1,const struct timespec * t2)3880 uelapsed(const struct timespec *t1, const struct timespec *t2)
3881 {
3882 struct timespec diff, zero = {0, 0};
3883 struct timeval tv;
3884
3885 timespecsub(t1, t2, &diff);
3886
3887 if (timespeccmp(&diff, &zero, <=))
3888 return 0;
3889
3890 TIMESPEC_TO_TIMEVAL(&tv, &diff);
3891
3892 return (tv.tv_sec * 1000000 + tv.tv_usec);
3893 }
3894