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