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