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