1 /*
2 * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-2003 Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /* $Id: dighost.c,v 1.345 2011/12/07 17:23:28 each Exp $ */
19
20 /*! \file
21 * \note
22 * Notice to programmers: Do not use this code as an example of how to
23 * use the ISC library to perform DNS lookups. Dig and Host both operate
24 * on the request level, since they allow fine-tuning of output and are
25 * intended as debugging tools. As a result, they perform many of the
26 * functions which could be better handled using the dns_resolver
27 * functions in most applications.
28 */
29
30 #include <config.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <limits.h>
35
36 #ifdef HAVE_LOCALE_H
37 #include <locale.h>
38 #endif
39
40 #ifdef WITH_IDN
41 #include <idn/result.h>
42 #include <idn/log.h>
43 #include <idn/resconf.h>
44 #include <idn/api.h>
45 #endif
46
47 #include <dns/byaddr.h>
48 #ifdef DIG_SIGCHASE
49 #include <dns/callbacks.h>
50 #include <dns/dnssec.h>
51 #include <dns/ds.h>
52 #include <dns/master.h>
53 #include <dns/nsec.h>
54 #include <isc/random.h>
55 #include <ctype.h>
56 #endif
57 #include <dns/fixedname.h>
58 #include <dns/log.h>
59 #include <dns/message.h>
60 #include <dns/name.h>
61 #include <dns/rcode.h>
62 #include <dns/rdata.h>
63 #include <dns/rdataclass.h>
64 #include <dns/rdatalist.h>
65 #include <dns/rdataset.h>
66 #include <dns/rdatastruct.h>
67 #include <dns/rdatatype.h>
68 #include <dns/result.h>
69 #include <dns/tsig.h>
70
71 #include <dst/dst.h>
72 #include <dst/result.h>
73
74 #include <isc/app.h>
75 #include <isc/base64.h>
76 #include <isc/entropy.h>
77 #include <isc/file.h>
78 #include <isc/lang.h>
79 #include <isc/log.h>
80 #include <isc/netaddr.h>
81 #ifdef DIG_SIGCHASE
82 #include <isc/netdb.h>
83 #endif
84 #include <isc/parseint.h>
85 #include <isc/print.h>
86 #include <isc/random.h>
87 #include <isc/result.h>
88 #include <isc/safe.h>
89 #include <isc/serial.h>
90 #include <isc/string.h>
91 #include <isc/task.h>
92 #include <isc/timer.h>
93 #include <isc/types.h>
94 #include <isc/util.h>
95
96 #include <isccfg/namedconf.h>
97
98 #include <lwres/lwres.h>
99 #include <lwres/net.h>
100
101 #include <bind9/getaddresses.h>
102
103 #include <dig/dig.h>
104
105 #if ! defined(NS_INADDRSZ)
106 #define NS_INADDRSZ 4
107 #endif
108
109 #if ! defined(NS_IN6ADDRSZ)
110 #define NS_IN6ADDRSZ 16
111 #endif
112
113 static lwres_context_t *lwctx = NULL;
114 static lwres_conf_t *lwconf;
115
116 dig_lookuplist_t lookup_list;
117 dig_serverlist_t server_list;
118 dig_searchlistlist_t search_list;
119
120 isc_boolean_t
121 check_ra = ISC_FALSE,
122 have_ipv4 = ISC_FALSE,
123 have_ipv6 = ISC_FALSE,
124 specified_source = ISC_FALSE,
125 free_now = ISC_FALSE,
126 cancel_now = ISC_FALSE,
127 usesearch = ISC_FALSE,
128 showsearch = ISC_FALSE,
129 qr = ISC_FALSE,
130 is_dst_up = ISC_FALSE,
131 keep_open = ISC_FALSE;
132 in_port_t port = 53;
133 unsigned int timeout = 0;
134 unsigned int extrabytes;
135 isc_mem_t *mctx = NULL;
136 isc_log_t *lctx = NULL;
137 isc_taskmgr_t *taskmgr = NULL;
138 isc_task_t *global_task = NULL;
139 isc_timermgr_t *timermgr = NULL;
140 isc_socketmgr_t *socketmgr = NULL;
141 isc_sockaddr_t bind_address;
142 isc_sockaddr_t bind_any;
143 int sendcount = 0;
144 int recvcount = 0;
145 int sockcount = 0;
146 int ndots = -1;
147 int tries = 3;
148 int lookup_counter = 0;
149
150 #ifdef WITH_IDN
151 static void initialize_idn(void);
152 static isc_result_t output_filter(isc_buffer_t *buffer,
153 unsigned int used_org,
154 isc_boolean_t absolute);
155 static idn_result_t append_textname(char *name, const char *origin,
156 size_t namesize);
157 static void idn_check_result(idn_result_t r, const char *msg);
158
159 #define MAXDLEN 256
160 int idnoptions = 0;
161 #endif
162
163 isc_socket_t *keep = NULL;
164 isc_sockaddr_t keepaddr;
165
166 /*%
167 * Exit Codes:
168 *
169 *\li 0 Everything went well, including things like NXDOMAIN
170 *\li 1 Usage error
171 *\li 7 Got too many RR's or Names
172 *\li 8 Couldn't open batch file
173 *\li 9 No reply from server
174 *\li 10 Internal error
175 */
176 int exitcode = 0;
177 int fatalexit = 0;
178 char keynametext[MXNAME];
179 char keyfile[MXNAME] = "";
180 char keysecret[MXNAME] = "";
181 dns_name_t *hmacname = NULL;
182 unsigned int digestbits = 0;
183 isc_buffer_t *namebuf = NULL;
184 dns_tsigkey_t *key = NULL;
185 isc_boolean_t validated = ISC_TRUE;
186 isc_entropy_t *entp = NULL;
187 isc_mempool_t *commctx = NULL;
188 isc_boolean_t debugging = ISC_FALSE;
189 isc_boolean_t debugtiming = ISC_FALSE;
190 isc_boolean_t memdebugging = ISC_FALSE;
191 char *progname = NULL;
192 isc_mutex_t lookup_lock;
193 dig_lookup_t *current_lookup = NULL;
194
195 #ifdef DIG_SIGCHASE
196
197 isc_result_t get_trusted_key(void);
198 dns_rdataset_t * sigchase_scanname(dns_rdatatype_t type,
199 dns_rdatatype_t covers,
200 isc_boolean_t *lookedup,
201 dns_name_t *rdata_name);
202 dns_rdataset_t * chase_scanname_section(dns_message_t *msg,
203 dns_name_t *name,
204 dns_rdatatype_t type,
205 dns_rdatatype_t covers,
206 int section);
207 isc_result_t advanced_rrsearch(dns_rdataset_t **rdataset,
208 dns_name_t *name,
209 dns_rdatatype_t type,
210 dns_rdatatype_t covers,
211 isc_boolean_t *lookedup);
212 isc_result_t sigchase_verify_sig_key(dns_name_t *name,
213 dns_rdataset_t *rdataset,
214 dst_key_t* dnsseckey,
215 dns_rdataset_t *sigrdataset);
216 isc_result_t sigchase_verify_sig(dns_name_t *name,
217 dns_rdataset_t *rdataset,
218 dns_rdataset_t *keyrdataset,
219 dns_rdataset_t *sigrdataset);
220 isc_result_t sigchase_verify_ds(dns_name_t *name,
221 dns_rdataset_t *keyrdataset,
222 dns_rdataset_t *dsrdataset);
223 void sigchase(dns_message_t *msg);
224 void print_rdata(dns_rdata_t *rdata, isc_mem_t *mctx);
225 void print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset);
226 void dup_name(dns_name_t *source, dns_name_t* target);
227 void free_name(dns_name_t *name);
228 void dump_database(void);
229 void dump_database_section(dns_message_t *msg, int section);
230 dns_rdataset_t * search_type(dns_name_t *name, dns_rdatatype_t type,
231 dns_rdatatype_t covers);
232 isc_result_t contains_trusted_key(dns_name_t *name,
233 dns_rdataset_t *rdataset,
234 dns_rdataset_t *sigrdataset);
235 void print_type(dns_rdatatype_t type);
236 isc_result_t prove_nx_domain(dns_message_t * msg,
237 dns_name_t * name,
238 dns_name_t * rdata_name,
239 dns_rdataset_t ** rdataset,
240 dns_rdataset_t ** sigrdataset);
241 isc_result_t prove_nx_type(dns_message_t * msg, dns_name_t *name,
242 dns_rdataset_t *nsec,
243 dns_rdataclass_t class,
244 dns_rdatatype_t type,
245 dns_name_t * rdata_name,
246 dns_rdataset_t ** rdataset,
247 dns_rdataset_t ** sigrdataset);
248 isc_result_t prove_nx(dns_message_t * msg, dns_name_t * name,
249 dns_rdataclass_t class,
250 dns_rdatatype_t type,
251 dns_name_t * rdata_name,
252 dns_rdataset_t ** rdataset,
253 dns_rdataset_t ** sigrdataset);
254 static void nameFromString(const char *str, dns_name_t *p_ret);
255 int inf_name(dns_name_t * name1, dns_name_t * name2);
256 isc_result_t removetmpkey(const char *file);
257 void clean_trustedkey(void);
258 isc_result_t insert_trustedkey(void *arg, dns_name_t *name,
259 dns_rdataset_t *rdataset);
260 #if DIG_SIGCHASE_BU
261 isc_result_t getneededrr(dns_message_t *msg);
262 void sigchase_bottom_up(dns_message_t *msg);
263 void sigchase_bu(dns_message_t *msg);
264 #endif
265 #if DIG_SIGCHASE_TD
266 isc_result_t initialization(dns_name_t *name);
267 isc_result_t prepare_lookup(dns_name_t *name);
268 isc_result_t grandfather_pb_test(dns_name_t * zone_name,
269 dns_rdataset_t *sigrdataset);
270 isc_result_t child_of_zone(dns_name_t *name,
271 dns_name_t *zone_name,
272 dns_name_t *child_name);
273 void sigchase_td(dns_message_t *msg);
274 #endif
275 char trustedkey[MXNAME] = "";
276
277 dns_rdataset_t *chase_rdataset = NULL;
278 dns_rdataset_t *chase_sigrdataset = NULL;
279 dns_rdataset_t *chase_dsrdataset = NULL;
280 dns_rdataset_t *chase_sigdsrdataset = NULL;
281 dns_rdataset_t *chase_keyrdataset = NULL;
282 dns_rdataset_t *chase_sigkeyrdataset = NULL;
283 dns_rdataset_t *chase_nsrdataset = NULL;
284
285 dns_name_t chase_name; /* the query name */
286 #if DIG_SIGCHASE_TD
287 /*
288 * the current name is the parent name when we follow delegation
289 */
290 dns_name_t chase_current_name;
291 /*
292 * the child name is used for delegation (NS DS responses in AUTHORITY section)
293 */
294 dns_name_t chase_authority_name;
295 #endif
296 #if DIG_SIGCHASE_BU
297 dns_name_t chase_signame;
298 #endif
299
300
301 isc_boolean_t chase_siglookedup = ISC_FALSE;
302 isc_boolean_t chase_keylookedup = ISC_FALSE;
303 isc_boolean_t chase_sigkeylookedup = ISC_FALSE;
304 isc_boolean_t chase_dslookedup = ISC_FALSE;
305 isc_boolean_t chase_sigdslookedup = ISC_FALSE;
306 #if DIG_SIGCHASE_TD
307 isc_boolean_t chase_nslookedup = ISC_FALSE;
308 isc_boolean_t chase_lookedup = ISC_FALSE;
309
310
311 isc_boolean_t delegation_follow = ISC_FALSE;
312 isc_boolean_t grandfather_pb = ISC_FALSE;
313 isc_boolean_t have_response = ISC_FALSE;
314 isc_boolean_t have_delegation_ns = ISC_FALSE;
315 dns_message_t * error_message = NULL;
316 #endif
317
318 isc_boolean_t dsvalidating = ISC_FALSE;
319 isc_boolean_t chase_name_dup = ISC_FALSE;
320
321 ISC_LIST(dig_message_t) chase_message_list;
322 ISC_LIST(dig_message_t) chase_message_list2;
323
324
325 #define MAX_TRUSTED_KEY 5
326 typedef struct struct_trusted_key_list {
327 dst_key_t * key[MAX_TRUSTED_KEY];
328 int nb_tk;
329 } struct_tk_list;
330
331 struct_tk_list tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0};
332
333 #endif
334
335 #define DIG_MAX_ADDRESSES 20
336
337 /*%
338 * Apply and clear locks at the event level in global task.
339 * Can I get rid of these using shutdown events? XXX
340 */
341 #define LOCK_LOOKUP {\
342 debug("lock_lookup %s:%d", __FILE__, __LINE__);\
343 check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\
344 debug("success");\
345 }
346 #define UNLOCK_LOOKUP {\
347 debug("unlock_lookup %s:%d", __FILE__, __LINE__);\
348 check_result(isc_mutex_unlock((&lookup_lock)),\
349 "isc_mutex_unlock");\
350 }
351
352 static void
353 cancel_lookup(dig_lookup_t *lookup);
354
355 static void
356 recv_done(isc_task_t *task, isc_event_t *event);
357
358 static void
359 send_udp(dig_query_t *query);
360
361 static void
362 connect_timeout(isc_task_t *task, isc_event_t *event);
363
364 static void
365 launch_next_query(dig_query_t *query, isc_boolean_t include_question);
366
367 static void
368 check_next_lookup(dig_lookup_t *lookup);
369
370 static isc_boolean_t
371 next_origin(dig_lookup_t *oldlookup);
372
373 static void *
mem_alloc(void * arg,size_t size)374 mem_alloc(void *arg, size_t size) {
375 return (isc_mem_get(arg, size));
376 }
377
378 static void
mem_free(void * arg,void * mem,size_t size)379 mem_free(void *arg, void *mem, size_t size) {
380 isc_mem_put(arg, mem, size);
381 }
382
383 char *
next_token(char ** stringp,const char * delim)384 next_token(char **stringp, const char *delim) {
385 char *res;
386
387 do {
388 res = strsep(stringp, delim);
389 if (res == NULL)
390 break;
391 } while (*res == '\0');
392 return (res);
393 }
394
395 static int
count_dots(char * string)396 count_dots(char *string) {
397 char *s;
398 int i = 0;
399
400 s = string;
401 while (*s != '\0') {
402 if (*s == '.')
403 i++;
404 s++;
405 }
406 return (i);
407 }
408
409 static void
hex_dump(isc_buffer_t * b)410 hex_dump(isc_buffer_t *b) {
411 unsigned int len, i;
412 isc_region_t r;
413
414 isc_buffer_usedregion(b, &r);
415
416 printf("%d bytes\n", r.length);
417 for (len = 0; len < r.length; len++) {
418 printf("%02x ", r.base[len]);
419 if (len % 16 == 15) {
420 fputs(" ", stdout);
421 for (i = len - 15; i <= len; i++) {
422 if (r.base[i] >= '!' && r.base[i] <= '}')
423 putchar(r.base[i]);
424 else
425 putchar('.');
426 }
427 printf("\n");
428 }
429 }
430 if (len % 16 != 0) {
431 for (i = len; (i % 16) != 0; i++)
432 fputs(" ", stdout);
433 fputs(" ", stdout);
434 for (i = ((len>>4)<<4); i < len; i++) {
435 if (r.base[i] >= '!' && r.base[i] <= '}')
436 putchar(r.base[i]);
437 else
438 putchar('.');
439 }
440 printf("\n");
441 }
442 }
443
444 /*%
445 * Append 'len' bytes of 'text' at '*p', failing with
446 * ISC_R_NOSPACE if that would advance p past 'end'.
447 */
448 static isc_result_t
append(const char * text,int len,char ** p,char * end)449 append(const char *text, int len, char **p, char *end) {
450 if (len > end - *p)
451 return (ISC_R_NOSPACE);
452 memmove(*p, text, len);
453 *p += len;
454 return (ISC_R_SUCCESS);
455 }
456
457 static isc_result_t
reverse_octets(const char * in,char ** p,char * end)458 reverse_octets(const char *in, char **p, char *end) {
459 const char *dot = strchr(in, '.');
460 int len;
461 if (dot != NULL) {
462 isc_result_t result;
463 result = reverse_octets(dot + 1, p, end);
464 if (result != ISC_R_SUCCESS)
465 return (result);
466 result = append(".", 1, p, end);
467 if (result != ISC_R_SUCCESS)
468 return (result);
469 len = (int)(dot - in);
470 } else {
471 len = strlen(in);
472 }
473 return (append(in, len, p, end));
474 }
475
476 isc_result_t
get_reverse(char * reverse,size_t len,char * value,isc_boolean_t ip6_int,isc_boolean_t strict)477 get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int,
478 isc_boolean_t strict)
479 {
480 int r;
481 isc_result_t result;
482 isc_netaddr_t addr;
483
484 addr.family = AF_INET6;
485 r = inet_pton(AF_INET6, value, &addr.type.in6);
486 if (r > 0) {
487 /* This is a valid IPv6 address. */
488 dns_fixedname_t fname;
489 dns_name_t *name;
490 unsigned int options = 0;
491
492 if (ip6_int)
493 options |= DNS_BYADDROPT_IPV6INT;
494 dns_fixedname_init(&fname);
495 name = dns_fixedname_name(&fname);
496 result = dns_byaddr_createptrname2(&addr, options, name);
497 if (result != ISC_R_SUCCESS)
498 return (result);
499 dns_name_format(name, reverse, (unsigned int)len);
500 return (ISC_R_SUCCESS);
501 } else {
502 /*
503 * Not a valid IPv6 address. Assume IPv4.
504 * If 'strict' is not set, construct the
505 * in-addr.arpa name by blindly reversing
506 * octets whether or not they look like integers,
507 * so that this can be used for RFC2317 names
508 * and such.
509 */
510 char *p = reverse;
511 char *end = reverse + len;
512 if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1)
513 return (DNS_R_BADDOTTEDQUAD);
514 result = reverse_octets(value, &p, end);
515 if (result != ISC_R_SUCCESS)
516 return (result);
517 /* Append .in-addr.arpa. and a terminating NUL. */
518 result = append(".in-addr.arpa.", 15, &p, end);
519 if (result != ISC_R_SUCCESS)
520 return (result);
521 return (ISC_R_SUCCESS);
522 }
523 }
524
525 void
fatal(const char * format,...)526 fatal(const char *format, ...) {
527 va_list args;
528
529 fflush(stdout);
530 fprintf(stderr, "%s: ", progname);
531 va_start(args, format);
532 vfprintf(stderr, format, args);
533 va_end(args);
534 fprintf(stderr, "\n");
535 if (exitcode < 10)
536 exitcode = 10;
537 if (fatalexit != 0)
538 exitcode = fatalexit;
539 exit(exitcode);
540 }
541
542 void
debug(const char * format,...)543 debug(const char *format, ...) {
544 va_list args;
545 isc_time_t t;
546
547 if (debugging) {
548 fflush(stdout);
549 if (debugtiming) {
550 TIME_NOW(&t);
551 fprintf(stderr, "%d.%06d: ", isc_time_seconds(&t),
552 isc_time_nanoseconds(&t) / 1000);
553 }
554 va_start(args, format);
555 vfprintf(stderr, format, args);
556 va_end(args);
557 fprintf(stderr, "\n");
558 }
559 }
560
561 void
check_result(isc_result_t result,const char * msg)562 check_result(isc_result_t result, const char *msg) {
563 if (result != ISC_R_SUCCESS) {
564 fatal("%s: %s", msg, isc_result_totext(result));
565 }
566 }
567
568 /*%
569 * Create a server structure, which is part of the lookup structure.
570 * This is little more than a linked list of servers to query in hopes
571 * of finding the answer the user is looking for
572 */
573 dig_server_t *
make_server(const char * servname,const char * userarg)574 make_server(const char *servname, const char *userarg) {
575 dig_server_t *srv;
576
577 REQUIRE(servname != NULL);
578
579 debug("make_server(%s)", servname);
580 srv = isc_mem_allocate(mctx, sizeof(struct dig_server));
581 if (srv == NULL)
582 fatal("memory allocation failure in %s:%d",
583 __FILE__, __LINE__);
584 strlcpy(srv->servername, servname, MXNAME);
585 strlcpy(srv->userarg, userarg, MXNAME);
586 ISC_LINK_INIT(srv, link);
587 return (srv);
588 }
589
590 static int
addr2af(int lwresaddrtype)591 addr2af(int lwresaddrtype)
592 {
593 int af = 0;
594
595 switch (lwresaddrtype) {
596 case LWRES_ADDRTYPE_V4:
597 af = AF_INET;
598 break;
599
600 case LWRES_ADDRTYPE_V6:
601 af = AF_INET6;
602 break;
603 }
604
605 return (af);
606 }
607
608 /*%
609 * Create a copy of the server list from the lwres configuration structure.
610 * The dest list must have already had ISC_LIST_INIT applied.
611 */
612 static void
copy_server_list(lwres_conf_t * confdata,dig_serverlist_t * dest)613 copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) {
614 dig_server_t *newsrv;
615 char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") +
616 sizeof("%4000000000")];
617 int af;
618 int i;
619
620 debug("copy_server_list()");
621 for (i = 0; i < confdata->nsnext; i++) {
622 af = addr2af(confdata->nameservers[i].family);
623
624 if (af == AF_INET && !have_ipv4)
625 continue;
626 if (af == AF_INET6 && !have_ipv6)
627 continue;
628
629 lwres_net_ntop(af, confdata->nameservers[i].address,
630 tmp, sizeof(tmp));
631 if (af == AF_INET6 && confdata->nameservers[i].zone != 0) {
632 char buf[sizeof("%4000000000")];
633 snprintf(buf, sizeof(buf), "%%%u",
634 confdata->nameservers[i].zone);
635 strlcat(tmp, buf, sizeof(tmp));
636 }
637 newsrv = make_server(tmp, tmp);
638 ISC_LINK_INIT(newsrv, link);
639 ISC_LIST_ENQUEUE(*dest, newsrv, link);
640 }
641 }
642
643 void
flush_server_list(void)644 flush_server_list(void) {
645 dig_server_t *s, *ps;
646
647 debug("flush_server_list()");
648 s = ISC_LIST_HEAD(server_list);
649 while (s != NULL) {
650 ps = s;
651 s = ISC_LIST_NEXT(s, link);
652 ISC_LIST_DEQUEUE(server_list, ps, link);
653 isc_mem_free(mctx, ps);
654 }
655 }
656
657 void
set_nameserver(char * opt)658 set_nameserver(char *opt) {
659 isc_result_t result;
660 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
661 isc_netaddr_t netaddr;
662 int count, i;
663 dig_server_t *srv;
664 char tmp[ISC_NETADDR_FORMATSIZE];
665
666 if (opt == NULL)
667 return;
668
669 result = bind9_getaddresses(opt, 0, sockaddrs,
670 DIG_MAX_ADDRESSES, &count);
671 if (result != ISC_R_SUCCESS)
672 fatal("couldn't get address for '%s': %s",
673 opt, isc_result_totext(result));
674
675 flush_server_list();
676
677 for (i = 0; i < count; i++) {
678 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
679 isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
680 srv = make_server(tmp, opt);
681 if (srv == NULL)
682 fatal("memory allocation failure");
683 ISC_LIST_APPEND(server_list, srv, link);
684 }
685 }
686
687 static isc_result_t
add_nameserver(lwres_conf_t * confdata,const char * addr,int af)688 add_nameserver(lwres_conf_t *confdata, const char *addr, int af) {
689
690 int i = confdata->nsnext;
691
692 if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS)
693 return (ISC_R_FAILURE);
694
695 switch (af) {
696 case AF_INET:
697 confdata->nameservers[i].family = LWRES_ADDRTYPE_V4;
698 confdata->nameservers[i].length = NS_INADDRSZ;
699 break;
700 case AF_INET6:
701 confdata->nameservers[i].family = LWRES_ADDRTYPE_V6;
702 confdata->nameservers[i].length = NS_IN6ADDRSZ;
703 break;
704 default:
705 return (ISC_R_FAILURE);
706 }
707
708 if (lwres_net_pton(af, addr, &confdata->nameservers[i].address) == 1) {
709 confdata->nsnext++;
710 return (ISC_R_SUCCESS);
711 }
712 return (ISC_R_FAILURE);
713 }
714
715 /*%
716 * Produce a cloned server list. The dest list must have already had
717 * ISC_LIST_INIT applied.
718 */
719 void
clone_server_list(dig_serverlist_t src,dig_serverlist_t * dest)720 clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
721 dig_server_t *srv, *newsrv;
722
723 debug("clone_server_list()");
724 srv = ISC_LIST_HEAD(src);
725 while (srv != NULL) {
726 newsrv = make_server(srv->servername, srv->userarg);
727 ISC_LINK_INIT(newsrv, link);
728 ISC_LIST_ENQUEUE(*dest, newsrv, link);
729 srv = ISC_LIST_NEXT(srv, link);
730 }
731 }
732
733 /*%
734 * Create an empty lookup structure, which holds all the information needed
735 * to get an answer to a user's question. This structure contains two
736 * linked lists: the server list (servers to query) and the query list
737 * (outstanding queries which have been made to the listed servers).
738 */
739 dig_lookup_t *
make_empty_lookup(void)740 make_empty_lookup(void) {
741 dig_lookup_t *looknew;
742
743 debug("make_empty_lookup()");
744
745 INSIST(!free_now);
746
747 looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
748 if (looknew == NULL)
749 fatal("memory allocation failure in %s:%d",
750 __FILE__, __LINE__);
751 looknew->pending = ISC_TRUE;
752 looknew->textname[0] = 0;
753 looknew->cmdline[0] = 0;
754 looknew->rdtype = dns_rdatatype_a;
755 looknew->qrdtype = dns_rdatatype_a;
756 looknew->rdclass = dns_rdataclass_in;
757 looknew->rdtypeset = ISC_FALSE;
758 looknew->rdclassset = ISC_FALSE;
759 looknew->sendspace = NULL;
760 looknew->sendmsg = NULL;
761 looknew->name = NULL;
762 looknew->oname = NULL;
763 looknew->timer = NULL;
764 looknew->xfr_q = NULL;
765 looknew->current_query = NULL;
766 looknew->doing_xfr = ISC_FALSE;
767 looknew->ixfr_serial = 0;
768 looknew->trace = ISC_FALSE;
769 looknew->trace_root = ISC_FALSE;
770 looknew->identify = ISC_FALSE;
771 looknew->identify_previous_line = ISC_FALSE;
772 looknew->ignore = ISC_FALSE;
773 looknew->servfail_stops = ISC_TRUE;
774 looknew->besteffort = ISC_TRUE;
775 looknew->dnssec = ISC_FALSE;
776 looknew->nsid = ISC_FALSE;
777 #ifdef DIG_SIGCHASE
778 looknew->sigchase = ISC_FALSE;
779 #if DIG_SIGCHASE_TD
780 looknew->do_topdown = ISC_FALSE;
781 looknew->trace_root_sigchase = ISC_FALSE;
782 looknew->rdtype_sigchaseset = ISC_FALSE;
783 looknew->rdtype_sigchase = dns_rdatatype_any;
784 looknew->qrdtype_sigchase = dns_rdatatype_any;
785 looknew->rdclass_sigchase = dns_rdataclass_in;
786 looknew->rdclass_sigchaseset = ISC_FALSE;
787 #endif
788 #endif
789 looknew->udpsize = 0;
790 looknew->edns = -1;
791 looknew->recurse = ISC_TRUE;
792 looknew->aaonly = ISC_FALSE;
793 looknew->adflag = ISC_FALSE;
794 looknew->cdflag = ISC_FALSE;
795 looknew->ns_search_only = ISC_FALSE;
796 looknew->origin = NULL;
797 looknew->tsigctx = NULL;
798 looknew->querysig = NULL;
799 looknew->retries = tries;
800 looknew->nsfound = 0;
801 looknew->tcp_mode = ISC_FALSE;
802 looknew->tcp_mode_set = ISC_FALSE;
803 looknew->ip6_int = ISC_FALSE;
804 looknew->comments = ISC_TRUE;
805 looknew->stats = ISC_TRUE;
806 looknew->section_question = ISC_TRUE;
807 looknew->section_answer = ISC_TRUE;
808 looknew->section_authority = ISC_TRUE;
809 looknew->section_additional = ISC_TRUE;
810 looknew->new_search = ISC_FALSE;
811 looknew->done_as_is = ISC_FALSE;
812 looknew->need_search = ISC_FALSE;
813 dns_fixedname_init(&looknew->fdomain);
814 ISC_LINK_INIT(looknew, link);
815 ISC_LIST_INIT(looknew->q);
816 ISC_LIST_INIT(looknew->connecting);
817 ISC_LIST_INIT(looknew->my_server_list);
818 return (looknew);
819 }
820
821 /*%
822 * Clone a lookup, perhaps copying the server list. This does not clone
823 * the query list, since it will be regenerated by the setup_lookup()
824 * function, nor does it queue up the new lookup for processing.
825 * Caution: If you don't clone the servers, you MUST clone the server
826 * list separately from somewhere else, or construct it by hand.
827 */
828 dig_lookup_t *
clone_lookup(dig_lookup_t * lookold,isc_boolean_t servers)829 clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
830 dig_lookup_t *looknew;
831
832 debug("clone_lookup()");
833
834 INSIST(!free_now);
835
836 looknew = make_empty_lookup();
837 INSIST(looknew != NULL);
838 strlcpy(looknew->textname, lookold->textname, MXNAME);
839 #if DIG_SIGCHASE_TD
840 strlcpy(looknew->textnamesigchase, lookold->textnamesigchase, MXNAME);
841 #endif
842 strlcpy(looknew->cmdline, lookold->cmdline, MXNAME);
843 looknew->textname[MXNAME-1] = 0;
844 looknew->rdtype = lookold->rdtype;
845 looknew->qrdtype = lookold->qrdtype;
846 looknew->rdclass = lookold->rdclass;
847 looknew->rdtypeset = lookold->rdtypeset;
848 looknew->rdclassset = lookold->rdclassset;
849 looknew->doing_xfr = lookold->doing_xfr;
850 looknew->ixfr_serial = lookold->ixfr_serial;
851 looknew->trace = lookold->trace;
852 looknew->trace_root = lookold->trace_root;
853 looknew->identify = lookold->identify;
854 looknew->identify_previous_line = lookold->identify_previous_line;
855 looknew->ignore = lookold->ignore;
856 looknew->servfail_stops = lookold->servfail_stops;
857 looknew->besteffort = lookold->besteffort;
858 looknew->dnssec = lookold->dnssec;
859 looknew->nsid = lookold->nsid;
860 #ifdef DIG_SIGCHASE
861 looknew->sigchase = lookold->sigchase;
862 #if DIG_SIGCHASE_TD
863 looknew->do_topdown = lookold->do_topdown;
864 looknew->trace_root_sigchase = lookold->trace_root_sigchase;
865 looknew->rdtype_sigchaseset = lookold->rdtype_sigchaseset;
866 looknew->rdtype_sigchase = lookold->rdtype_sigchase;
867 looknew->qrdtype_sigchase = lookold->qrdtype_sigchase;
868 looknew->rdclass_sigchase = lookold->rdclass_sigchase;
869 looknew->rdclass_sigchaseset = lookold->rdclass_sigchaseset;
870 #endif
871 #endif
872 looknew->udpsize = lookold->udpsize;
873 looknew->edns = lookold->edns;
874 looknew->recurse = lookold->recurse;
875 looknew->aaonly = lookold->aaonly;
876 looknew->adflag = lookold->adflag;
877 looknew->cdflag = lookold->cdflag;
878 looknew->ns_search_only = lookold->ns_search_only;
879 looknew->tcp_mode = lookold->tcp_mode;
880 looknew->tcp_mode_set = lookold->tcp_mode_set;
881 looknew->comments = lookold->comments;
882 looknew->stats = lookold->stats;
883 looknew->section_question = lookold->section_question;
884 looknew->section_answer = lookold->section_answer;
885 looknew->section_authority = lookold->section_authority;
886 looknew->section_additional = lookold->section_additional;
887 looknew->retries = lookold->retries;
888 looknew->tsigctx = NULL;
889 looknew->need_search = lookold->need_search;
890 looknew->done_as_is = lookold->done_as_is;
891
892 dns_name_copy(dns_fixedname_name(&lookold->fdomain),
893 dns_fixedname_name(&looknew->fdomain), NULL);
894
895 if (servers)
896 clone_server_list(lookold->my_server_list,
897 &looknew->my_server_list);
898 return (looknew);
899 }
900
901 /*%
902 * Requeue a lookup for further processing, perhaps copying the server
903 * list. The new lookup structure is returned to the caller, and is
904 * queued for processing. If servers are not cloned in the requeue, they
905 * must be added before allowing the current event to complete, since the
906 * completion of the event may result in the next entry on the lookup
907 * queue getting run.
908 */
909 dig_lookup_t *
requeue_lookup(dig_lookup_t * lookold,isc_boolean_t servers)910 requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
911 dig_lookup_t *looknew;
912
913 debug("requeue_lookup()");
914
915 lookup_counter++;
916 if (lookup_counter > LOOKUP_LIMIT)
917 fatal("too many lookups");
918
919 looknew = clone_lookup(lookold, servers);
920 INSIST(looknew != NULL);
921
922 debug("before insertion, init@%p -> %p, new@%p -> %p",
923 lookold, lookold->link.next, looknew, looknew->link.next);
924 ISC_LIST_PREPEND(lookup_list, looknew, link);
925 debug("after insertion, init -> %p, new = %p, new -> %p",
926 lookold, looknew, looknew->link.next);
927 return (looknew);
928 }
929
930
931 static void
setup_text_key(void)932 setup_text_key(void) {
933 isc_result_t result;
934 dns_name_t keyname;
935 isc_buffer_t secretbuf;
936 int secretsize;
937 unsigned char *secretstore;
938
939 debug("setup_text_key()");
940 result = isc_buffer_allocate(mctx, &namebuf, MXNAME);
941 check_result(result, "isc_buffer_allocate");
942 dns_name_init(&keyname, NULL);
943 check_result(result, "dns_name_init");
944 isc_buffer_putstr(namebuf, keynametext);
945 secretsize = strlen(keysecret) * 3 / 4;
946 secretstore = isc_mem_allocate(mctx, secretsize);
947 if (secretstore == NULL)
948 fatal("memory allocation failure in %s:%d",
949 __FILE__, __LINE__);
950 isc_buffer_init(&secretbuf, secretstore, secretsize);
951 result = isc_base64_decodestring(keysecret, &secretbuf);
952 if (result != ISC_R_SUCCESS)
953 goto failure;
954
955 secretsize = isc_buffer_usedlength(&secretbuf);
956
957 if (hmacname == NULL) {
958 result = DST_R_UNSUPPORTEDALG;
959 goto failure;
960 }
961
962 result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf);
963 if (result != ISC_R_SUCCESS)
964 goto failure;
965
966 result = dns_tsigkey_create(&keyname, hmacname, secretstore,
967 secretsize, ISC_FALSE, NULL, 0, 0, mctx,
968 NULL, &key);
969 failure:
970 if (result != ISC_R_SUCCESS)
971 printf(";; Couldn't create key %s: %s\n",
972 keynametext, isc_result_totext(result));
973 else
974 dst_key_setbits(key->key, digestbits);
975
976 isc_mem_free(mctx, secretstore);
977 dns_name_invalidate(&keyname);
978 isc_buffer_free(&namebuf);
979 }
980
981 isc_result_t
parse_uint(isc_uint32_t * uip,const char * value,isc_uint32_t max,const char * desc)982 parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max,
983 const char *desc) {
984 isc_uint32_t n;
985 isc_result_t result = isc_parse_uint32(&n, value, 10);
986 if (result == ISC_R_SUCCESS && n > max)
987 result = ISC_R_RANGE;
988 if (result != ISC_R_SUCCESS) {
989 printf("invalid %s '%s': %s\n", desc,
990 value, isc_result_totext(result));
991 return (result);
992 }
993 *uip = n;
994 return (ISC_R_SUCCESS);
995 }
996
997 static isc_uint32_t
parse_bits(char * arg,const char * desc,isc_uint32_t max)998 parse_bits(char *arg, const char *desc, isc_uint32_t max) {
999 isc_result_t result;
1000 isc_uint32_t tmp;
1001
1002 result = parse_uint(&tmp, arg, max, desc);
1003 if (result != ISC_R_SUCCESS)
1004 fatal("couldn't parse digest bits");
1005 tmp = (tmp + 7) & ~0x7U;
1006 return (tmp);
1007 }
1008
1009 /*
1010 * Parse HMAC algorithm specification
1011 */
1012 void
parse_hmac(const char * hmac)1013 parse_hmac(const char *hmac) {
1014 char buf[20];
1015 int len;
1016
1017 REQUIRE(hmac != NULL);
1018
1019 len = strlen(hmac);
1020 if (len >= (int) sizeof(buf))
1021 fatal("unknown key type '%.*s'", len, hmac);
1022 strlcpy(buf, hmac, sizeof(buf));
1023
1024 digestbits = 0;
1025
1026 if (strcasecmp(buf, "hmac-md5") == 0) {
1027 hmacname = DNS_TSIG_HMACMD5_NAME;
1028 } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
1029 hmacname = DNS_TSIG_HMACMD5_NAME;
1030 digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128);
1031 } else if (strcasecmp(buf, "hmac-sha1") == 0) {
1032 hmacname = DNS_TSIG_HMACSHA1_NAME;
1033 digestbits = 0;
1034 } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
1035 hmacname = DNS_TSIG_HMACSHA1_NAME;
1036 digestbits = parse_bits(&buf[10], "digest-bits [0..160]", 160);
1037 } else if (strcasecmp(buf, "hmac-sha224") == 0) {
1038 hmacname = DNS_TSIG_HMACSHA224_NAME;
1039 } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
1040 hmacname = DNS_TSIG_HMACSHA224_NAME;
1041 digestbits = parse_bits(&buf[12], "digest-bits [0..224]", 224);
1042 } else if (strcasecmp(buf, "hmac-sha256") == 0) {
1043 hmacname = DNS_TSIG_HMACSHA256_NAME;
1044 } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
1045 hmacname = DNS_TSIG_HMACSHA256_NAME;
1046 digestbits = parse_bits(&buf[12], "digest-bits [0..256]", 256);
1047 } else if (strcasecmp(buf, "hmac-sha384") == 0) {
1048 hmacname = DNS_TSIG_HMACSHA384_NAME;
1049 } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
1050 hmacname = DNS_TSIG_HMACSHA384_NAME;
1051 digestbits = parse_bits(&buf[12], "digest-bits [0..384]", 384);
1052 } else if (strcasecmp(buf, "hmac-sha512") == 0) {
1053 hmacname = DNS_TSIG_HMACSHA512_NAME;
1054 } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
1055 hmacname = DNS_TSIG_HMACSHA512_NAME;
1056 digestbits = parse_bits(&buf[12], "digest-bits [0..512]", 512);
1057 } else {
1058 fprintf(stderr, ";; Warning, ignoring "
1059 "invalid TSIG algorithm %s\n", buf);
1060 }
1061 }
1062
1063 /*
1064 * Get a key from a named.conf format keyfile
1065 */
1066 static isc_result_t
read_confkey(void)1067 read_confkey(void) {
1068 cfg_parser_t *pctx = NULL;
1069 cfg_obj_t *file = NULL;
1070 const cfg_obj_t *keyobj = NULL;
1071 const cfg_obj_t *secretobj = NULL;
1072 const cfg_obj_t *algorithmobj = NULL;
1073 const char *keyname;
1074 const char *secretstr;
1075 const char *algorithm;
1076 isc_result_t result;
1077
1078 if (! isc_file_exists(keyfile))
1079 return (ISC_R_FILENOTFOUND);
1080
1081 result = cfg_parser_create(mctx, NULL, &pctx);
1082 if (result != ISC_R_SUCCESS)
1083 goto cleanup;
1084
1085 result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
1086 &file);
1087 if (result != ISC_R_SUCCESS)
1088 goto cleanup;
1089
1090 result = cfg_map_get(file, "key", &keyobj);
1091 if (result != ISC_R_SUCCESS)
1092 goto cleanup;
1093
1094 (void) cfg_map_get(keyobj, "secret", &secretobj);
1095 (void) cfg_map_get(keyobj, "algorithm", &algorithmobj);
1096 if (secretobj == NULL || algorithmobj == NULL)
1097 fatal("key must have algorithm and secret");
1098
1099 keyname = cfg_obj_asstring(cfg_map_getname(keyobj));
1100 secretstr = cfg_obj_asstring(secretobj);
1101 algorithm = cfg_obj_asstring(algorithmobj);
1102
1103 strlcpy(keynametext, keyname, sizeof(keynametext));
1104 strlcpy(keysecret, secretstr, sizeof(keysecret));
1105 parse_hmac(algorithm);
1106 setup_text_key();
1107
1108 cleanup:
1109 if (pctx != NULL) {
1110 if (file != NULL)
1111 cfg_obj_destroy(pctx, &file);
1112 cfg_parser_destroy(&pctx);
1113 }
1114
1115 return (result);
1116 }
1117
1118 static void
setup_file_key(void)1119 setup_file_key(void) {
1120 isc_result_t result;
1121 dst_key_t *dstkey = NULL;
1122
1123 debug("setup_file_key()");
1124
1125 /* Try reading the key from a K* pair */
1126 result = dst_key_fromnamedfile(keyfile, NULL,
1127 DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
1128 &dstkey);
1129
1130 /* If that didn't work, try reading it as a session.key keyfile */
1131 if (result != ISC_R_SUCCESS) {
1132 result = read_confkey();
1133 if (result == ISC_R_SUCCESS)
1134 return;
1135 }
1136
1137 if (result != ISC_R_SUCCESS) {
1138 fprintf(stderr, "Couldn't read key from %s: %s\n",
1139 keyfile, isc_result_totext(result));
1140 goto failure;
1141 }
1142
1143 switch (dst_key_alg(dstkey)) {
1144 case DST_ALG_HMACMD5:
1145 hmacname = DNS_TSIG_HMACMD5_NAME;
1146 break;
1147 case DST_ALG_HMACSHA1:
1148 hmacname = DNS_TSIG_HMACSHA1_NAME;
1149 break;
1150 case DST_ALG_HMACSHA224:
1151 hmacname = DNS_TSIG_HMACSHA224_NAME;
1152 break;
1153 case DST_ALG_HMACSHA256:
1154 hmacname = DNS_TSIG_HMACSHA256_NAME;
1155 break;
1156 case DST_ALG_HMACSHA384:
1157 hmacname = DNS_TSIG_HMACSHA384_NAME;
1158 break;
1159 case DST_ALG_HMACSHA512:
1160 hmacname = DNS_TSIG_HMACSHA512_NAME;
1161 break;
1162 default:
1163 printf(";; Couldn't create key %s: bad algorithm\n",
1164 keynametext);
1165 goto failure;
1166 }
1167 result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmacname,
1168 dstkey, ISC_FALSE, NULL, 0, 0,
1169 mctx, NULL, &key);
1170 if (result != ISC_R_SUCCESS) {
1171 printf(";; Couldn't create key %s: %s\n",
1172 keynametext, isc_result_totext(result));
1173 goto failure;
1174 }
1175 failure:
1176 if (dstkey != NULL)
1177 dst_key_free(&dstkey);
1178 }
1179
1180 static dig_searchlist_t *
make_searchlist_entry(char * domain)1181 make_searchlist_entry(char *domain) {
1182 dig_searchlist_t *search;
1183 search = isc_mem_allocate(mctx, sizeof(*search));
1184 if (search == NULL)
1185 fatal("memory allocation failure in %s:%d",
1186 __FILE__, __LINE__);
1187 strlcpy(search->origin, domain, MXNAME);
1188 search->origin[MXNAME-1] = 0;
1189 ISC_LINK_INIT(search, link);
1190 return (search);
1191 }
1192
1193 static void
clear_searchlist(void)1194 clear_searchlist(void) {
1195 dig_searchlist_t *search;
1196 while ((search = ISC_LIST_HEAD(search_list)) != NULL) {
1197 ISC_LIST_UNLINK(search_list, search, link);
1198 isc_mem_free(mctx, search);
1199 }
1200 }
1201
1202 static void
create_search_list(lwres_conf_t * confdata)1203 create_search_list(lwres_conf_t *confdata) {
1204 int i;
1205 dig_searchlist_t *search;
1206
1207 debug("create_search_list()");
1208 clear_searchlist();
1209
1210 for (i = 0; i < confdata->searchnxt; i++) {
1211 search = make_searchlist_entry(confdata->search[i]);
1212 ISC_LIST_APPEND(search_list, search, link);
1213 }
1214 }
1215
1216 /*%
1217 * Setup the system as a whole, reading key information and resolv.conf
1218 * settings.
1219 */
1220 void
setup_system(void)1221 setup_system(void) {
1222 dig_searchlist_t *domain = NULL;
1223 lwres_result_t lwresult;
1224 unsigned int lwresflags;
1225
1226 debug("setup_system()");
1227
1228 lwresflags = LWRES_CONTEXT_SERVERMODE;
1229 if (have_ipv4)
1230 lwresflags |= LWRES_CONTEXT_USEIPV4;
1231 if (have_ipv6)
1232 lwresflags |= LWRES_CONTEXT_USEIPV6;
1233
1234 lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free,
1235 lwresflags);
1236 if (lwresult != LWRES_R_SUCCESS)
1237 fatal("lwres_context_create failed");
1238
1239 lwresult = lwres_conf_parse(lwctx, RESOLV_CONF);
1240 if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND)
1241 fatal("parse of %s failed", RESOLV_CONF);
1242
1243 lwconf = lwres_conf_get(lwctx);
1244
1245 /* Make the search list */
1246 if (lwconf->searchnxt > 0)
1247 create_search_list(lwconf);
1248 else { /* No search list. Use the domain name if any */
1249 if (lwconf->domainname != NULL) {
1250 domain = make_searchlist_entry(lwconf->domainname);
1251 ISC_LIST_APPEND(search_list, domain, link);
1252 domain = NULL;
1253 }
1254 }
1255
1256 if (ndots == -1) {
1257 ndots = lwconf->ndots;
1258 debug("ndots is %d.", ndots);
1259 }
1260
1261 /* If user doesn't specify server use nameservers from resolv.conf. */
1262 if (ISC_LIST_EMPTY(server_list))
1263 copy_server_list(lwconf, &server_list);
1264
1265 /* If we don't find a nameserver fall back to localhost */
1266 if (ISC_LIST_EMPTY(server_list)) {
1267 if (have_ipv4) {
1268 lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET);
1269 if (lwresult != ISC_R_SUCCESS)
1270 fatal("add_nameserver failed");
1271 }
1272 if (have_ipv6) {
1273 lwresult = add_nameserver(lwconf, "::1", AF_INET6);
1274 if (lwresult != ISC_R_SUCCESS)
1275 fatal("add_nameserver failed");
1276 }
1277
1278 copy_server_list(lwconf, &server_list);
1279 }
1280
1281 #ifdef WITH_IDN
1282 initialize_idn();
1283 #endif
1284
1285 if (keyfile[0] != 0)
1286 setup_file_key();
1287 else if (keysecret[0] != 0)
1288 setup_text_key();
1289 #ifdef DIG_SIGCHASE
1290 /* Setup the list of messages for +sigchase */
1291 ISC_LIST_INIT(chase_message_list);
1292 ISC_LIST_INIT(chase_message_list2);
1293 dns_name_init(&chase_name, NULL);
1294 #if DIG_SIGCHASE_TD
1295 dns_name_init(&chase_current_name, NULL);
1296 dns_name_init(&chase_authority_name, NULL);
1297 #endif
1298 #if DIG_SIGCHASE_BU
1299 dns_name_init(&chase_signame, NULL);
1300 #endif
1301
1302 #endif
1303
1304 }
1305
1306 /*%
1307 * Override the search list derived from resolv.conf by 'domain'.
1308 */
1309 void
set_search_domain(char * domain)1310 set_search_domain(char *domain) {
1311 dig_searchlist_t *search;
1312
1313 clear_searchlist();
1314 search = make_searchlist_entry(domain);
1315 ISC_LIST_APPEND(search_list, search, link);
1316 }
1317
1318 /*%
1319 * Setup the ISC and DNS libraries for use by the system.
1320 */
1321 void
setup_libs(void)1322 setup_libs(void) {
1323 isc_result_t result;
1324 isc_logconfig_t *logconfig = NULL;
1325
1326 debug("setup_libs()");
1327
1328 result = isc_net_probeipv4();
1329 if (result == ISC_R_SUCCESS)
1330 have_ipv4 = ISC_TRUE;
1331
1332 result = isc_net_probeipv6();
1333 if (result == ISC_R_SUCCESS)
1334 have_ipv6 = ISC_TRUE;
1335 if (!have_ipv6 && !have_ipv4)
1336 fatal("can't find either v4 or v6 networking");
1337
1338 result = isc_mem_create(0, 0, &mctx);
1339 check_result(result, "isc_mem_create");
1340 isc_mem_setname(mctx, "dig", NULL);
1341
1342 result = isc_log_create(mctx, &lctx, &logconfig);
1343 check_result(result, "isc_log_create");
1344
1345 isc_log_setcontext(lctx);
1346 dns_log_init(lctx);
1347 dns_log_setcontext(lctx);
1348
1349 result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
1350 check_result(result, "isc_log_usechannel");
1351
1352 isc_log_setdebuglevel(lctx, 0);
1353
1354 result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
1355 check_result(result, "isc_taskmgr_create");
1356
1357 result = isc_task_create(taskmgr, 0, &global_task);
1358 check_result(result, "isc_task_create");
1359 isc_task_setname(global_task, "dig", NULL);
1360
1361 result = isc_timermgr_create(mctx, &timermgr);
1362 check_result(result, "isc_timermgr_create");
1363
1364 result = isc_socketmgr_create(mctx, &socketmgr);
1365 check_result(result, "isc_socketmgr_create");
1366
1367 result = isc_entropy_create(mctx, &entp);
1368 check_result(result, "isc_entropy_create");
1369
1370 result = dst_lib_init(mctx, entp, 0);
1371 check_result(result, "dst_lib_init");
1372 is_dst_up = ISC_TRUE;
1373
1374 result = isc_mempool_create(mctx, COMMSIZE, &commctx);
1375 check_result(result, "isc_mempool_create");
1376 isc_mempool_setname(commctx, "COMMPOOL");
1377 /*
1378 * 6 and 2 set as reasonable parameters for 3 or 4 nameserver
1379 * systems.
1380 */
1381 isc_mempool_setfreemax(commctx, 6);
1382 isc_mempool_setfillcount(commctx, 2);
1383
1384 result = isc_mutex_init(&lookup_lock);
1385 check_result(result, "isc_mutex_init");
1386
1387 dns_result_register();
1388 }
1389
1390 /*%
1391 * Add EDNS0 option record to a message. Currently, the only supported
1392 * options are UDP buffer size, the DO bit, and NSID request.
1393 */
1394 static void
add_opt(dns_message_t * msg,isc_uint16_t udpsize,isc_uint16_t edns,isc_boolean_t dnssec,isc_boolean_t nsid)1395 add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns,
1396 isc_boolean_t dnssec, isc_boolean_t nsid)
1397 {
1398 dns_rdataset_t *rdataset = NULL;
1399 dns_rdatalist_t *rdatalist = NULL;
1400 dns_rdata_t *rdata = NULL;
1401 isc_result_t result;
1402
1403 debug("add_opt()");
1404 result = dns_message_gettemprdataset(msg, &rdataset);
1405 check_result(result, "dns_message_gettemprdataset");
1406 dns_rdataset_init(rdataset);
1407 result = dns_message_gettemprdatalist(msg, &rdatalist);
1408 check_result(result, "dns_message_gettemprdatalist");
1409 result = dns_message_gettemprdata(msg, &rdata);
1410 check_result(result, "dns_message_gettemprdata");
1411
1412 debug("setting udp size of %d", udpsize);
1413 rdatalist->type = dns_rdatatype_opt;
1414 rdatalist->covers = 0;
1415 rdatalist->rdclass = udpsize;
1416 rdatalist->ttl = edns << 16;
1417 if (dnssec)
1418 rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
1419 if (nsid) {
1420 isc_buffer_t *b = NULL;
1421
1422 result = isc_buffer_allocate(mctx, &b, 4);
1423 check_result(result, "isc_buffer_allocate");
1424 isc_buffer_putuint16(b, DNS_OPT_NSID);
1425 isc_buffer_putuint16(b, 0);
1426 rdata->data = isc_buffer_base(b);
1427 rdata->length = isc_buffer_usedlength(b);
1428 dns_message_takebuffer(msg, &b);
1429 } else {
1430 rdata->data = NULL;
1431 rdata->length = 0;
1432 }
1433 ISC_LIST_INIT(rdatalist->rdata);
1434 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1435 dns_rdatalist_tordataset(rdatalist, rdataset);
1436 result = dns_message_setopt(msg, rdataset);
1437 check_result(result, "dns_message_setopt");
1438 }
1439
1440 /*%
1441 * Add a question section to a message, asking for the specified name,
1442 * type, and class.
1443 */
1444 static void
add_question(dns_message_t * message,dns_name_t * name,dns_rdataclass_t rdclass,dns_rdatatype_t rdtype)1445 add_question(dns_message_t *message, dns_name_t *name,
1446 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype)
1447 {
1448 dns_rdataset_t *rdataset;
1449 isc_result_t result;
1450
1451 debug("add_question()");
1452 rdataset = NULL;
1453 result = dns_message_gettemprdataset(message, &rdataset);
1454 check_result(result, "dns_message_gettemprdataset()");
1455 dns_rdataset_init(rdataset);
1456 dns_rdataset_makequestion(rdataset, rdclass, rdtype);
1457 ISC_LIST_APPEND(name->list, rdataset, link);
1458 }
1459
1460 /*%
1461 * Check if we're done with all the queued lookups, which is true iff
1462 * all sockets, sends, and recvs are accounted for (counters == 0),
1463 * and the lookup list is empty.
1464 * If we are done, pass control back out to dighost_shutdown() (which is
1465 * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
1466 * a whole or reseed the lookup list.
1467 */
1468 static void
check_if_done(void)1469 check_if_done(void) {
1470 debug("check_if_done()");
1471 debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
1472 if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
1473 sendcount == 0) {
1474 INSIST(sockcount == 0);
1475 INSIST(recvcount == 0);
1476 debug("shutting down");
1477 dighost_shutdown();
1478 }
1479 }
1480
1481 /*%
1482 * Clear out a query when we're done with it. WARNING: This routine
1483 * WILL invalidate the query pointer.
1484 */
1485 static void
clear_query(dig_query_t * query)1486 clear_query(dig_query_t *query) {
1487 dig_lookup_t *lookup;
1488
1489 REQUIRE(query != NULL);
1490
1491 debug("clear_query(%p)", query);
1492
1493 lookup = query->lookup;
1494
1495 if (lookup->current_query == query)
1496 lookup->current_query = NULL;
1497
1498 if (ISC_LINK_LINKED(query, link))
1499 ISC_LIST_UNLINK(lookup->q, query, link);
1500 if (ISC_LINK_LINKED(query, clink))
1501 ISC_LIST_UNLINK(lookup->connecting, query, clink);
1502 if (ISC_LINK_LINKED(&query->recvbuf, link))
1503 ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf,
1504 link);
1505 if (ISC_LINK_LINKED(&query->lengthbuf, link))
1506 ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf,
1507 link);
1508 INSIST(query->recvspace != NULL);
1509
1510 if (query->sock != NULL) {
1511 isc_socket_detach(&query->sock);
1512 sockcount--;
1513 debug("sockcount=%d", sockcount);
1514 }
1515 isc_mempool_put(commctx, query->recvspace);
1516 isc_buffer_invalidate(&query->recvbuf);
1517 isc_buffer_invalidate(&query->lengthbuf);
1518 if (query->waiting_senddone)
1519 query->pending_free = ISC_TRUE;
1520 else
1521 isc_mem_free(mctx, query);
1522 }
1523
1524 /*%
1525 * Try and clear out a lookup if we're done with it. Return ISC_TRUE if
1526 * the lookup was successfully cleared. If ISC_TRUE is returned, the
1527 * lookup pointer has been invalidated.
1528 */
1529 static isc_boolean_t
try_clear_lookup(dig_lookup_t * lookup)1530 try_clear_lookup(dig_lookup_t *lookup) {
1531 dig_query_t *q;
1532
1533 REQUIRE(lookup != NULL);
1534
1535 debug("try_clear_lookup(%p)", lookup);
1536
1537 if (ISC_LIST_HEAD(lookup->q) != NULL ||
1538 ISC_LIST_HEAD(lookup->connecting) != NULL)
1539 {
1540 if (debugging) {
1541 q = ISC_LIST_HEAD(lookup->q);
1542 while (q != NULL) {
1543 debug("query to %s still pending", q->servname);
1544 q = ISC_LIST_NEXT(q, link);
1545 }
1546
1547 q = ISC_LIST_HEAD(lookup->connecting);
1548 while (q != NULL) {
1549 debug("query to %s still connecting",
1550 q->servname);
1551 q = ISC_LIST_NEXT(q, clink);
1552 }
1553 }
1554 return (ISC_FALSE);
1555 }
1556
1557 /*
1558 * At this point, we know there are no queries on the lookup,
1559 * so can make it go away also.
1560 */
1561 destroy_lookup(lookup);
1562 return (ISC_TRUE);
1563 }
1564
1565 void
destroy_lookup(dig_lookup_t * lookup)1566 destroy_lookup(dig_lookup_t *lookup) {
1567 dig_server_t *s;
1568 void *ptr;
1569
1570 debug("destroy");
1571 s = ISC_LIST_HEAD(lookup->my_server_list);
1572 while (s != NULL) {
1573 debug("freeing server %p belonging to %p", s, lookup);
1574 ptr = s;
1575 s = ISC_LIST_NEXT(s, link);
1576 ISC_LIST_DEQUEUE(lookup->my_server_list,
1577 (dig_server_t *)ptr, link);
1578 isc_mem_free(mctx, ptr);
1579 }
1580 if (lookup->sendmsg != NULL)
1581 dns_message_destroy(&lookup->sendmsg);
1582 if (lookup->querysig != NULL) {
1583 debug("freeing buffer %p", lookup->querysig);
1584 isc_buffer_free(&lookup->querysig);
1585 }
1586 if (lookup->timer != NULL)
1587 isc_timer_detach(&lookup->timer);
1588 if (lookup->sendspace != NULL)
1589 isc_mempool_put(commctx, lookup->sendspace);
1590
1591 if (lookup->tsigctx != NULL)
1592 dst_context_destroy(&lookup->tsigctx);
1593
1594 isc_mem_free(mctx, lookup);
1595 }
1596
1597 /*%
1598 * If we can, start the next lookup in the queue running.
1599 * This assumes that the lookup on the head of the queue hasn't been
1600 * started yet. It also removes the lookup from the head of the queue,
1601 * setting the current_lookup pointer pointing to it.
1602 */
1603 void
start_lookup(void)1604 start_lookup(void) {
1605 debug("start_lookup()");
1606 if (cancel_now)
1607 return;
1608
1609 /*
1610 * If there's a current lookup running, we really shouldn't get
1611 * here.
1612 */
1613 INSIST(current_lookup == NULL);
1614
1615 current_lookup = ISC_LIST_HEAD(lookup_list);
1616 /*
1617 * Put the current lookup somewhere so cancel_all can find it
1618 */
1619 if (current_lookup != NULL) {
1620 ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
1621 #if DIG_SIGCHASE_TD
1622 if (current_lookup->do_topdown &&
1623 !current_lookup->rdtype_sigchaseset) {
1624 dst_key_t *dstkey = NULL;
1625 isc_buffer_t *b = NULL;
1626 isc_region_t r;
1627 isc_result_t result;
1628 dns_name_t query_name;
1629 dns_name_t *key_name;
1630 int i;
1631
1632 result = get_trusted_key();
1633 if (result != ISC_R_SUCCESS) {
1634 printf("\n;; No trusted key, "
1635 "+sigchase option is disabled\n");
1636 current_lookup->sigchase = ISC_FALSE;
1637 goto novalidation;
1638 }
1639 dns_name_init(&query_name, NULL);
1640 nameFromString(current_lookup->textname, &query_name);
1641
1642 for (i = 0; i < tk_list.nb_tk; i++) {
1643 key_name = dst_key_name(tk_list.key[i]);
1644
1645 if (dns_name_issubdomain(&query_name,
1646 key_name) == ISC_TRUE)
1647 dstkey = tk_list.key[i];
1648 /*
1649 * Verify temp is really the lowest
1650 * WARNING
1651 */
1652 }
1653 if (dstkey == NULL) {
1654 printf("\n;; The queried zone: ");
1655 dns_name_print(&query_name, stdout);
1656 printf(" isn't a subdomain of any Trusted Keys"
1657 ": +sigchase option is disable\n");
1658 current_lookup->sigchase = ISC_FALSE;
1659 free_name(&query_name);
1660 goto novalidation;
1661 }
1662 free_name(&query_name);
1663
1664 current_lookup->rdtype_sigchase
1665 = current_lookup->rdtype;
1666 current_lookup->rdtype_sigchaseset
1667 = current_lookup->rdtypeset;
1668 current_lookup->rdtype = dns_rdatatype_ns;
1669
1670 current_lookup->qrdtype_sigchase
1671 = current_lookup->qrdtype;
1672 current_lookup->qrdtype = dns_rdatatype_ns;
1673
1674 current_lookup->rdclass_sigchase
1675 = current_lookup->rdclass;
1676 current_lookup->rdclass_sigchaseset
1677 = current_lookup->rdclassset;
1678 current_lookup->rdclass = dns_rdataclass_in;
1679
1680 strlcpy(current_lookup->textnamesigchase,
1681 current_lookup->textname, MXNAME);
1682
1683 current_lookup->trace_root_sigchase = ISC_TRUE;
1684
1685 result = isc_buffer_allocate(mctx, &b, BUFSIZE);
1686 check_result(result, "isc_buffer_allocate");
1687 result = dns_name_totext(dst_key_name(dstkey),
1688 ISC_FALSE, b);
1689 check_result(result, "dns_name_totext");
1690 isc_buffer_usedregion(b, &r);
1691 r.base[r.length] = '\0';
1692 strlcpy(current_lookup->textname, (char*)r.base,
1693 MXNAME);
1694 isc_buffer_free(&b);
1695
1696 nameFromString(current_lookup->textnamesigchase,
1697 &chase_name);
1698
1699 dns_name_init(&chase_authority_name, NULL);
1700 }
1701 novalidation:
1702 #endif
1703 if (setup_lookup(current_lookup))
1704 do_lookup(current_lookup);
1705 else if (next_origin(current_lookup))
1706 check_next_lookup(current_lookup);
1707 } else {
1708 check_if_done();
1709 }
1710 }
1711
1712 /*%
1713 * If we can, clear the current lookup and start the next one running.
1714 * This calls try_clear_lookup, so may invalidate the lookup pointer.
1715 */
1716 static void
check_next_lookup(dig_lookup_t * lookup)1717 check_next_lookup(dig_lookup_t *lookup) {
1718
1719 INSIST(!free_now);
1720
1721 debug("check_next_lookup(%p)", lookup);
1722
1723 if (ISC_LIST_HEAD(lookup->q) != NULL) {
1724 debug("still have a worker");
1725 return;
1726 }
1727 if (try_clear_lookup(lookup)) {
1728 current_lookup = NULL;
1729 start_lookup();
1730 }
1731 }
1732
1733 /*%
1734 * Create and queue a new lookup as a followup to the current lookup,
1735 * based on the supplied message and section. This is used in trace and
1736 * name server search modes to start a new lookup using servers from
1737 * NS records in a reply. Returns the number of followup lookups made.
1738 */
1739 static int
followup_lookup(dns_message_t * msg,dig_query_t * query,dns_section_t section)1740 followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section)
1741 {
1742 dig_lookup_t *lookup = NULL;
1743 dig_server_t *srv = NULL;
1744 dns_rdataset_t *rdataset = NULL;
1745 dns_rdata_t rdata = DNS_RDATA_INIT;
1746 dns_name_t *name = NULL;
1747 isc_result_t result;
1748 isc_boolean_t success = ISC_FALSE;
1749 int numLookups = 0;
1750 int num;
1751 isc_result_t lresult, addresses_result;
1752 char bad_namestr[DNS_NAME_FORMATSIZE];
1753 dns_name_t *domain;
1754 isc_boolean_t horizontal = ISC_FALSE, bad = ISC_FALSE;
1755
1756 INSIST(!free_now);
1757
1758 debug("following up %s", query->lookup->textname);
1759
1760 addresses_result = ISC_R_SUCCESS;
1761 bad_namestr[0] = '\0';
1762 for (result = dns_message_firstname(msg, section);
1763 result == ISC_R_SUCCESS;
1764 result = dns_message_nextname(msg, section)) {
1765 name = NULL;
1766 dns_message_currentname(msg, section, &name);
1767
1768 if (section == DNS_SECTION_AUTHORITY) {
1769 rdataset = NULL;
1770 result = dns_message_findtype(name, dns_rdatatype_soa,
1771 0, &rdataset);
1772 if (result == ISC_R_SUCCESS)
1773 return (0);
1774 }
1775 rdataset = NULL;
1776 result = dns_message_findtype(name, dns_rdatatype_ns, 0,
1777 &rdataset);
1778 if (result != ISC_R_SUCCESS)
1779 continue;
1780
1781 debug("found NS set");
1782
1783 if (query->lookup->trace && !query->lookup->trace_root) {
1784 dns_namereln_t namereln;
1785 unsigned int nlabels;
1786 int order;
1787
1788 domain = dns_fixedname_name(&query->lookup->fdomain);
1789 namereln = dns_name_fullcompare(name, domain,
1790 &order, &nlabels);
1791 if (namereln == dns_namereln_equal) {
1792 if (!horizontal)
1793 printf(";; BAD (HORIZONTAL) REFERRAL\n");
1794 horizontal = ISC_TRUE;
1795 } else if (namereln != dns_namereln_subdomain) {
1796 if (!bad)
1797 printf(";; BAD REFERRAL\n");
1798 bad = ISC_TRUE;
1799 continue;
1800 }
1801 }
1802
1803 for (result = dns_rdataset_first(rdataset);
1804 result == ISC_R_SUCCESS;
1805 result = dns_rdataset_next(rdataset)) {
1806 char namestr[DNS_NAME_FORMATSIZE];
1807 dns_rdata_ns_t ns;
1808
1809 if (query->lookup->trace_root &&
1810 query->lookup->nsfound >= MXSERV)
1811 break;
1812
1813 dns_rdataset_current(rdataset, &rdata);
1814
1815 query->lookup->nsfound++;
1816 result = dns_rdata_tostruct(&rdata, &ns, NULL);
1817 check_result(result, "dns_rdata_tostruct");
1818 dns_name_format(&ns.name, namestr, sizeof(namestr));
1819 dns_rdata_freestruct(&ns);
1820
1821 /* Initialize lookup if we've not yet */
1822 debug("found NS %s", namestr);
1823 if (!success) {
1824 success = ISC_TRUE;
1825 lookup_counter++;
1826 lookup = requeue_lookup(query->lookup,
1827 ISC_FALSE);
1828 cancel_lookup(query->lookup);
1829 lookup->doing_xfr = ISC_FALSE;
1830 if (!lookup->trace_root &&
1831 section == DNS_SECTION_ANSWER)
1832 lookup->trace = ISC_FALSE;
1833 else
1834 lookup->trace = query->lookup->trace;
1835 lookup->ns_search_only =
1836 query->lookup->ns_search_only;
1837 lookup->trace_root = ISC_FALSE;
1838 if (lookup->ns_search_only)
1839 lookup->recurse = ISC_FALSE;
1840 domain = dns_fixedname_name(&lookup->fdomain);
1841 dns_name_copy(name, domain, NULL);
1842 }
1843 debug("adding server %s", namestr);
1844 num = getaddresses(lookup, namestr, &lresult);
1845 if (lresult != ISC_R_SUCCESS) {
1846 debug("couldn't get address for '%s': %s",
1847 namestr, isc_result_totext(lresult));
1848 if (addresses_result == ISC_R_SUCCESS) {
1849 addresses_result = lresult;
1850 strcpy(bad_namestr, namestr);
1851 }
1852 }
1853 numLookups += num;
1854 dns_rdata_reset(&rdata);
1855 }
1856 }
1857 if (numLookups == 0 && addresses_result != ISC_R_SUCCESS) {
1858 fatal("couldn't get address for '%s': %s",
1859 bad_namestr, isc_result_totext(result));
1860 }
1861
1862 if (lookup == NULL &&
1863 section == DNS_SECTION_ANSWER &&
1864 (query->lookup->trace || query->lookup->ns_search_only))
1865 return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY));
1866
1867 /*
1868 * Randomize the order the nameserver will be tried.
1869 */
1870 if (numLookups > 1) {
1871 isc_uint32_t i, j;
1872 dig_serverlist_t my_server_list;
1873 dig_server_t *next;
1874
1875 ISC_LIST_INIT(my_server_list);
1876
1877 i = numLookups;
1878 for (srv = ISC_LIST_HEAD(lookup->my_server_list);
1879 srv != NULL;
1880 srv = ISC_LIST_HEAD(lookup->my_server_list)) {
1881 INSIST(i > 0);
1882 isc_random_get(&j);
1883 j %= i;
1884 next = ISC_LIST_NEXT(srv, link);
1885 while (j-- > 0 && next != NULL) {
1886 srv = next;
1887 next = ISC_LIST_NEXT(srv, link);
1888 }
1889 ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link);
1890 ISC_LIST_APPEND(my_server_list, srv, link);
1891 i--;
1892 }
1893 ISC_LIST_APPENDLIST(lookup->my_server_list,
1894 my_server_list, link);
1895 }
1896
1897 return (numLookups);
1898 }
1899
1900 /*%
1901 * Create and queue a new lookup using the next origin from the search
1902 * list, read in setup_system().
1903 *
1904 * Return ISC_TRUE iff there was another searchlist entry.
1905 */
1906 static isc_boolean_t
next_origin(dig_lookup_t * oldlookup)1907 next_origin(dig_lookup_t *oldlookup) {
1908 dig_lookup_t *newlookup;
1909 dig_searchlist_t *search;
1910 dns_fixedname_t fixed;
1911 dns_name_t *name;
1912 isc_result_t result;
1913
1914 INSIST(!free_now);
1915
1916 debug("next_origin()");
1917 debug("following up %s", oldlookup->textname);
1918
1919 if (!usesearch)
1920 /*
1921 * We're not using a search list, so don't even think
1922 * about finding the next entry.
1923 */
1924 return (ISC_FALSE);
1925
1926 /*
1927 * Check for a absolute name or ndots being met.
1928 */
1929 dns_fixedname_init(&fixed);
1930 name = dns_fixedname_name(&fixed);
1931 result = dns_name_fromstring2(name, oldlookup->textname, NULL,
1932 0, NULL);
1933 if (result == ISC_R_SUCCESS &&
1934 (dns_name_isabsolute(name) ||
1935 (int)dns_name_countlabels(name) > ndots))
1936 return (ISC_FALSE);
1937
1938 if (oldlookup->origin == NULL && !oldlookup->need_search)
1939 /*
1940 * Then we just did rootorg; there's nothing left.
1941 */
1942 return (ISC_FALSE);
1943 if (oldlookup->origin == NULL && oldlookup->need_search) {
1944 newlookup = requeue_lookup(oldlookup, ISC_TRUE);
1945 newlookup->origin = ISC_LIST_HEAD(search_list);
1946 newlookup->need_search = ISC_FALSE;
1947 } else {
1948 search = ISC_LIST_NEXT(oldlookup->origin, link);
1949 if (search == NULL && oldlookup->done_as_is)
1950 return (ISC_FALSE);
1951 newlookup = requeue_lookup(oldlookup, ISC_TRUE);
1952 newlookup->origin = search;
1953 }
1954 cancel_lookup(oldlookup);
1955 return (ISC_TRUE);
1956 }
1957
1958 /*%
1959 * Insert an SOA record into the sendmessage in a lookup. Used for
1960 * creating IXFR queries.
1961 */
1962 static void
insert_soa(dig_lookup_t * lookup)1963 insert_soa(dig_lookup_t *lookup) {
1964 isc_result_t result;
1965 dns_rdata_soa_t soa;
1966 dns_rdata_t *rdata = NULL;
1967 dns_rdatalist_t *rdatalist = NULL;
1968 dns_rdataset_t *rdataset = NULL;
1969 dns_name_t *soaname = NULL;
1970
1971 debug("insert_soa()");
1972 soa.mctx = mctx;
1973 soa.serial = lookup->ixfr_serial;
1974 soa.refresh = 0;
1975 soa.retry = 0;
1976 soa.expire = 0;
1977 soa.minimum = 0;
1978 soa.common.rdclass = lookup->rdclass;
1979 soa.common.rdtype = dns_rdatatype_soa;
1980
1981 dns_name_init(&soa.origin, NULL);
1982 dns_name_init(&soa.contact, NULL);
1983
1984 dns_name_clone(dns_rootname, &soa.origin);
1985 dns_name_clone(dns_rootname, &soa.contact);
1986
1987 isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
1988 sizeof(lookup->rdatastore));
1989
1990 result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
1991 check_result(result, "dns_message_gettemprdata");
1992
1993 result = dns_rdata_fromstruct(rdata, lookup->rdclass,
1994 dns_rdatatype_soa, &soa,
1995 &lookup->rdatabuf);
1996 check_result(result, "isc_rdata_fromstruct");
1997
1998 result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
1999 check_result(result, "dns_message_gettemprdatalist");
2000
2001 result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
2002 check_result(result, "dns_message_gettemprdataset");
2003
2004 dns_rdatalist_init(rdatalist);
2005 rdatalist->type = dns_rdatatype_soa;
2006 rdatalist->rdclass = lookup->rdclass;
2007 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
2008
2009 dns_rdataset_init(rdataset);
2010 dns_rdatalist_tordataset(rdatalist, rdataset);
2011
2012 result = dns_message_gettempname(lookup->sendmsg, &soaname);
2013 check_result(result, "dns_message_gettempname");
2014 dns_name_init(soaname, NULL);
2015 dns_name_clone(lookup->name, soaname);
2016 ISC_LIST_INIT(soaname->list);
2017 ISC_LIST_APPEND(soaname->list, rdataset, link);
2018 dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
2019 }
2020
2021 /*%
2022 * Setup the supplied lookup structure, making it ready to start sending
2023 * queries to servers. Create and initialize the message to be sent as
2024 * well as the query structures and buffer space for the replies. If the
2025 * server list is empty, clone it from the system default list.
2026 */
2027 isc_boolean_t
setup_lookup(dig_lookup_t * lookup)2028 setup_lookup(dig_lookup_t *lookup) {
2029 isc_result_t result;
2030 isc_uint32_t id;
2031 int len;
2032 dig_server_t *serv;
2033 dig_query_t *query;
2034 isc_buffer_t b;
2035 dns_compress_t cctx;
2036 char store[MXNAME];
2037 #ifdef WITH_IDN
2038 idn_result_t mr;
2039 char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME];
2040 #endif
2041
2042 #ifdef WITH_IDN
2043 result = dns_name_settotextfilter(output_filter);
2044 check_result(result, "dns_name_settotextfilter");
2045 #endif
2046
2047 REQUIRE(lookup != NULL);
2048 INSIST(!free_now);
2049
2050 debug("setup_lookup(%p)", lookup);
2051
2052 result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
2053 &lookup->sendmsg);
2054 check_result(result, "dns_message_create");
2055
2056 if (lookup->new_search) {
2057 debug("resetting lookup counter.");
2058 lookup_counter = 0;
2059 }
2060
2061 if (ISC_LIST_EMPTY(lookup->my_server_list)) {
2062 debug("cloning server list");
2063 clone_server_list(server_list, &lookup->my_server_list);
2064 }
2065 result = dns_message_gettempname(lookup->sendmsg, &lookup->name);
2066 check_result(result, "dns_message_gettempname");
2067 dns_name_init(lookup->name, NULL);
2068
2069 isc_buffer_init(&lookup->namebuf, lookup->namespace,
2070 sizeof(lookup->namespace));
2071 isc_buffer_init(&lookup->onamebuf, lookup->onamespace,
2072 sizeof(lookup->onamespace));
2073
2074 #ifdef WITH_IDN
2075 /*
2076 * We cannot convert `textname' and `origin' separately.
2077 * `textname' doesn't contain TLD, but local mapping needs
2078 * TLD.
2079 */
2080 mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname,
2081 utf8_textname, sizeof(utf8_textname));
2082 idn_check_result(mr, "convert textname to UTF-8");
2083 #endif
2084
2085 /*
2086 * If the name has too many dots, force the origin to be NULL
2087 * (which produces an absolute lookup). Otherwise, take the origin
2088 * we have if there's one in the struct already. If it's NULL,
2089 * take the first entry in the searchlist iff either usesearch
2090 * is TRUE or we got a domain line in the resolv.conf file.
2091 */
2092 if (lookup->new_search) {
2093 #ifdef WITH_IDN
2094 if ((count_dots(utf8_textname) >= ndots) || !usesearch) {
2095 lookup->origin = NULL; /* Force abs lookup */
2096 lookup->done_as_is = ISC_TRUE;
2097 lookup->need_search = usesearch;
2098 } else if (lookup->origin == NULL && usesearch) {
2099 lookup->origin = ISC_LIST_HEAD(search_list);
2100 lookup->need_search = ISC_FALSE;
2101 }
2102 #else
2103 if ((count_dots(lookup->textname) >= ndots) || !usesearch) {
2104 lookup->origin = NULL; /* Force abs lookup */
2105 lookup->done_as_is = ISC_TRUE;
2106 lookup->need_search = usesearch;
2107 } else if (lookup->origin == NULL && usesearch) {
2108 lookup->origin = ISC_LIST_HEAD(search_list);
2109 lookup->need_search = ISC_FALSE;
2110 }
2111 #endif
2112 }
2113
2114 #ifdef WITH_IDN
2115 if (lookup->origin != NULL) {
2116 mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP,
2117 lookup->origin->origin, utf8_origin,
2118 sizeof(utf8_origin));
2119 idn_check_result(mr, "convert origin to UTF-8");
2120 mr = append_textname(utf8_textname, utf8_origin,
2121 sizeof(utf8_textname));
2122 idn_check_result(mr, "append origin to textname");
2123 }
2124 mr = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP |
2125 IDN_IDNCONV | IDN_LENCHECK, utf8_textname,
2126 idn_textname, sizeof(idn_textname));
2127 idn_check_result(mr, "convert UTF-8 textname to IDN encoding");
2128 #else
2129 if (lookup->origin != NULL) {
2130 debug("trying origin %s", lookup->origin->origin);
2131 result = dns_message_gettempname(lookup->sendmsg,
2132 &lookup->oname);
2133 check_result(result, "dns_message_gettempname");
2134 dns_name_init(lookup->oname, NULL);
2135 /* XXX Helper funct to conv char* to name? */
2136 len = strlen(lookup->origin->origin);
2137 isc_buffer_init(&b, lookup->origin->origin, len);
2138 isc_buffer_add(&b, len);
2139 result = dns_name_fromtext(lookup->oname, &b, dns_rootname,
2140 0, &lookup->onamebuf);
2141 if (result != ISC_R_SUCCESS) {
2142 dns_message_puttempname(lookup->sendmsg,
2143 &lookup->name);
2144 dns_message_puttempname(lookup->sendmsg,
2145 &lookup->oname);
2146 fatal("'%s' is not in legal name syntax (%s)",
2147 lookup->origin->origin,
2148 isc_result_totext(result));
2149 }
2150 if (lookup->trace && lookup->trace_root) {
2151 dns_name_clone(dns_rootname, lookup->name);
2152 } else {
2153 dns_fixedname_t fixed;
2154 dns_name_t *name;
2155
2156 dns_fixedname_init(&fixed);
2157 name = dns_fixedname_name(&fixed);
2158 len = strlen(lookup->textname);
2159 isc_buffer_init(&b, lookup->textname, len);
2160 isc_buffer_add(&b, len);
2161 result = dns_name_fromtext(name, &b, NULL, 0, NULL);
2162 if (result == ISC_R_SUCCESS &&
2163 !dns_name_isabsolute(name))
2164 result = dns_name_concatenate(name,
2165 lookup->oname,
2166 lookup->name,
2167 &lookup->namebuf);
2168 else if (result == ISC_R_SUCCESS)
2169 result = dns_name_copy(name, lookup->name,
2170 &lookup->namebuf);
2171 if (result != ISC_R_SUCCESS) {
2172 dns_message_puttempname(lookup->sendmsg,
2173 &lookup->name);
2174 dns_message_puttempname(lookup->sendmsg,
2175 &lookup->oname);
2176 if (result == DNS_R_NAMETOOLONG)
2177 return (ISC_FALSE);
2178 fatal("'%s' is not in legal name syntax (%s)",
2179 lookup->textname,
2180 isc_result_totext(result));
2181 }
2182 }
2183 dns_message_puttempname(lookup->sendmsg, &lookup->oname);
2184 } else
2185 #endif
2186 {
2187 debug("using root origin");
2188 if (lookup->trace && lookup->trace_root)
2189 dns_name_clone(dns_rootname, lookup->name);
2190 else {
2191 #ifdef WITH_IDN
2192 len = strlen(idn_textname);
2193 isc_buffer_init(&b, idn_textname, len);
2194 isc_buffer_add(&b, len);
2195 result = dns_name_fromtext(lookup->name, &b,
2196 dns_rootname, 0,
2197 &lookup->namebuf);
2198 #else
2199 len = strlen(lookup->textname);
2200 isc_buffer_init(&b, lookup->textname, len);
2201 isc_buffer_add(&b, len);
2202 result = dns_name_fromtext(lookup->name, &b,
2203 dns_rootname, 0,
2204 &lookup->namebuf);
2205 #endif
2206 }
2207 if (result != ISC_R_SUCCESS) {
2208 dns_message_puttempname(lookup->sendmsg,
2209 &lookup->name);
2210 fatal("'%s' is not a legal name "
2211 "(%s)", lookup->textname,
2212 isc_result_totext(result));
2213 }
2214 }
2215 dns_name_format(lookup->name, store, sizeof(store));
2216 trying(store, lookup);
2217 INSIST(dns_name_isabsolute(lookup->name));
2218
2219 isc_random_get(&id);
2220 lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
2221 lookup->sendmsg->opcode = dns_opcode_query;
2222 lookup->msgcounter = 0;
2223 /*
2224 * If this is a trace request, completely disallow recursion, since
2225 * it's meaningless for traces.
2226 */
2227 if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root))
2228 lookup->recurse = ISC_FALSE;
2229
2230 if (lookup->recurse &&
2231 lookup->rdtype != dns_rdatatype_axfr &&
2232 lookup->rdtype != dns_rdatatype_ixfr) {
2233 debug("recursive query");
2234 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD;
2235 }
2236
2237 /* XXX aaflag */
2238 if (lookup->aaonly) {
2239 debug("AA query");
2240 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA;
2241 }
2242
2243 if (lookup->adflag) {
2244 debug("AD query");
2245 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD;
2246 }
2247
2248 if (lookup->cdflag) {
2249 debug("CD query");
2250 lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD;
2251 }
2252
2253 dns_message_addname(lookup->sendmsg, lookup->name,
2254 DNS_SECTION_QUESTION);
2255
2256 if (lookup->trace && lookup->trace_root) {
2257 lookup->qrdtype = lookup->rdtype;
2258 lookup->rdtype = dns_rdatatype_ns;
2259 }
2260
2261 if ((lookup->rdtype == dns_rdatatype_axfr) ||
2262 (lookup->rdtype == dns_rdatatype_ixfr)) {
2263 /*
2264 * Force TCP mode if we're doing an axfr.
2265 */
2266 if (lookup->rdtype == dns_rdatatype_axfr) {
2267 lookup->doing_xfr = ISC_TRUE;
2268 lookup->tcp_mode = ISC_TRUE;
2269 } else if (lookup->tcp_mode) {
2270 lookup->doing_xfr = ISC_TRUE;
2271 }
2272 }
2273
2274 add_question(lookup->sendmsg, lookup->name, lookup->rdclass,
2275 lookup->rdtype);
2276
2277 /* add_soa */
2278 if (lookup->rdtype == dns_rdatatype_ixfr)
2279 insert_soa(lookup);
2280
2281 /* XXX Insist this? */
2282 lookup->tsigctx = NULL;
2283 lookup->querysig = NULL;
2284 if (key != NULL) {
2285 debug("initializing keys");
2286 result = dns_message_settsigkey(lookup->sendmsg, key);
2287 check_result(result, "dns_message_settsigkey");
2288 }
2289
2290 lookup->sendspace = isc_mempool_get(commctx);
2291 if (lookup->sendspace == NULL)
2292 fatal("memory allocation failure");
2293
2294 result = dns_compress_init(&cctx, -1, mctx);
2295 check_result(result, "dns_compress_init");
2296
2297 debug("starting to render the message");
2298 isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE);
2299 result = dns_message_renderbegin(lookup->sendmsg, &cctx,
2300 &lookup->renderbuf);
2301 check_result(result, "dns_message_renderbegin");
2302 if (lookup->udpsize > 0 || lookup->dnssec || lookup->edns > -1) {
2303 if (lookup->udpsize == 0)
2304 lookup->udpsize = 4096;
2305 if (lookup->edns < 0)
2306 lookup->edns = 0;
2307 add_opt(lookup->sendmsg, lookup->udpsize,
2308 lookup->edns, lookup->dnssec, lookup->nsid);
2309 }
2310
2311 result = dns_message_rendersection(lookup->sendmsg,
2312 DNS_SECTION_QUESTION, 0);
2313 check_result(result, "dns_message_rendersection");
2314 result = dns_message_rendersection(lookup->sendmsg,
2315 DNS_SECTION_AUTHORITY, 0);
2316 check_result(result, "dns_message_rendersection");
2317 result = dns_message_renderend(lookup->sendmsg);
2318 check_result(result, "dns_message_renderend");
2319 debug("done rendering");
2320
2321 dns_compress_invalidate(&cctx);
2322
2323 /*
2324 * Force TCP mode if the request is larger than 512 bytes.
2325 */
2326 if (isc_buffer_usedlength(&lookup->renderbuf) > 512)
2327 lookup->tcp_mode = ISC_TRUE;
2328
2329 lookup->pending = ISC_FALSE;
2330
2331 for (serv = ISC_LIST_HEAD(lookup->my_server_list);
2332 serv != NULL;
2333 serv = ISC_LIST_NEXT(serv, link)) {
2334 query = isc_mem_allocate(mctx, sizeof(dig_query_t));
2335 if (query == NULL)
2336 fatal("memory allocation failure in %s:%d",
2337 __FILE__, __LINE__);
2338 debug("create query %p linked to lookup %p",
2339 query, lookup);
2340 query->lookup = lookup;
2341 query->waiting_connect = ISC_FALSE;
2342 query->waiting_senddone = ISC_FALSE;
2343 query->pending_free = ISC_FALSE;
2344 query->recv_made = ISC_FALSE;
2345 query->first_pass = ISC_TRUE;
2346 query->first_soa_rcvd = ISC_FALSE;
2347 query->second_rr_rcvd = ISC_FALSE;
2348 query->first_repeat_rcvd = ISC_FALSE;
2349 query->warn_id = ISC_TRUE;
2350 query->first_rr_serial = 0;
2351 query->second_rr_serial = 0;
2352 query->servname = serv->servername;
2353 query->userarg = serv->userarg;
2354 query->rr_count = 0;
2355 query->msg_count = 0;
2356 query->byte_count = 0;
2357 query->ixfr_axfr = ISC_FALSE;
2358 ISC_LIST_INIT(query->recvlist);
2359 ISC_LIST_INIT(query->lengthlist);
2360 query->sock = NULL;
2361 query->recvspace = isc_mempool_get(commctx);
2362 if (query->recvspace == NULL)
2363 fatal("memory allocation failure");
2364
2365 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
2366 isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
2367 isc_buffer_init(&query->slbuf, query->slspace, 2);
2368 query->sendbuf = lookup->renderbuf;
2369
2370 ISC_LINK_INIT(query, clink);
2371 ISC_LINK_INIT(query, link);
2372 ISC_LIST_ENQUEUE(lookup->q, query, link);
2373 }
2374 /* XXX qrflag, print_query, etc... */
2375 if (!ISC_LIST_EMPTY(lookup->q) && qr) {
2376 extrabytes = 0;
2377 printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg,
2378 ISC_TRUE);
2379 }
2380 return (ISC_TRUE);
2381 }
2382
2383 /*%
2384 * Event handler for send completion. Track send counter, and clear out
2385 * the query if the send was canceled.
2386 */
2387 static void
send_done(isc_task_t * _task,isc_event_t * event)2388 send_done(isc_task_t *_task, isc_event_t *event) {
2389 isc_socketevent_t *sevent = (isc_socketevent_t *)event;
2390 isc_buffer_t *b = NULL;
2391 dig_query_t *query, *next;
2392 dig_lookup_t *l;
2393
2394 REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
2395
2396 UNUSED(_task);
2397
2398 LOCK_LOOKUP;
2399
2400 debug("send_done()");
2401 sendcount--;
2402 debug("sendcount=%d", sendcount);
2403 INSIST(sendcount >= 0);
2404
2405 for (b = ISC_LIST_HEAD(sevent->bufferlist);
2406 b != NULL;
2407 b = ISC_LIST_HEAD(sevent->bufferlist)) {
2408 ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2409 isc_mem_free(mctx, b);
2410 }
2411
2412 query = event->ev_arg;
2413 query->waiting_senddone = ISC_FALSE;
2414 l = query->lookup;
2415
2416 if (l->ns_search_only && !l->trace_root && !l->tcp_mode) {
2417 debug("sending next, since searching");
2418 next = ISC_LIST_NEXT(query, link);
2419 if (next != NULL)
2420 send_udp(next);
2421 }
2422
2423 isc_event_free(&event);
2424
2425 if (query->pending_free)
2426 isc_mem_free(mctx, query);
2427
2428 check_if_done();
2429 UNLOCK_LOOKUP;
2430 }
2431
2432 /*%
2433 * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
2434 * IO sockets. The cancel handlers should take care of cleaning up the
2435 * query and lookup structures
2436 */
2437 static void
cancel_lookup(dig_lookup_t * lookup)2438 cancel_lookup(dig_lookup_t *lookup) {
2439 dig_query_t *query, *next;
2440
2441 debug("cancel_lookup()");
2442 query = ISC_LIST_HEAD(lookup->q);
2443 while (query != NULL) {
2444 next = ISC_LIST_NEXT(query, link);
2445 if (query->sock != NULL) {
2446 isc_socket_cancel(query->sock, global_task,
2447 ISC_SOCKCANCEL_ALL);
2448 check_if_done();
2449 } else {
2450 clear_query(query);
2451 }
2452 query = next;
2453 }
2454 if (lookup->timer != NULL)
2455 isc_timer_detach(&lookup->timer);
2456 lookup->pending = ISC_FALSE;
2457 lookup->retries = 0;
2458 }
2459
2460 static void
bringup_timer(dig_query_t * query,unsigned int default_timeout)2461 bringup_timer(dig_query_t *query, unsigned int default_timeout) {
2462 dig_lookup_t *l;
2463 unsigned int local_timeout;
2464 isc_result_t result;
2465
2466 debug("bringup_timer()");
2467 /*
2468 * If the timer already exists, that means we're calling this
2469 * a second time (for a retry). Don't need to recreate it,
2470 * just reset it.
2471 */
2472 l = query->lookup;
2473 if (ISC_LIST_NEXT(query, link) != NULL)
2474 local_timeout = SERVER_TIMEOUT;
2475 else {
2476 if (timeout == 0)
2477 local_timeout = default_timeout;
2478 else
2479 local_timeout = timeout;
2480 }
2481 debug("have local timeout of %d", local_timeout);
2482 isc_interval_set(&l->interval, local_timeout, 0);
2483 if (l->timer != NULL)
2484 isc_timer_detach(&l->timer);
2485 result = isc_timer_create(timermgr, isc_timertype_once, NULL,
2486 &l->interval, global_task, connect_timeout,
2487 l, &l->timer);
2488 check_result(result, "isc_timer_create");
2489 }
2490
2491 static void
force_timeout(dig_lookup_t * l,dig_query_t * query)2492 force_timeout(dig_lookup_t *l, dig_query_t *query) {
2493 isc_event_t *event;
2494
2495 debug("force_timeout ()");
2496 event = isc_event_allocate(mctx, query, ISC_TIMEREVENT_IDLE,
2497 connect_timeout, l,
2498 sizeof(isc_event_t));
2499 if (event == NULL) {
2500 fatal("isc_event_allocate: %s",
2501 isc_result_totext(ISC_R_NOMEMORY));
2502 }
2503 isc_task_send(global_task, &event);
2504
2505 /*
2506 * The timer may have expired if, for example, get_address() takes
2507 * long time and the timer was running on a different thread.
2508 * We need to cancel the possible timeout event not to confuse
2509 * ourselves due to the duplicate events.
2510 */
2511 if (l->timer != NULL)
2512 isc_timer_detach(&l->timer);
2513 }
2514
2515
2516 static void
2517 connect_done(isc_task_t *task, isc_event_t *event);
2518
2519 /*%
2520 * Unlike send_udp, this can't be called multiple times with the same
2521 * query. When we retry TCP, we requeue the whole lookup, which should
2522 * start anew.
2523 */
2524 static void
send_tcp_connect(dig_query_t * query)2525 send_tcp_connect(dig_query_t *query) {
2526 isc_result_t result;
2527 dig_query_t *next;
2528 dig_lookup_t *l;
2529
2530 debug("send_tcp_connect(%p)", query);
2531
2532 l = query->lookup;
2533 query->waiting_connect = ISC_TRUE;
2534 query->lookup->current_query = query;
2535 result = get_address(query->servname, port, &query->sockaddr);
2536 if (result != ISC_R_SUCCESS) {
2537 /*
2538 * This servname doesn't have an address. Try the next server
2539 * by triggering an immediate 'timeout' (we lie, but the effect
2540 * is the same).
2541 */
2542 force_timeout(l, query);
2543 return;
2544 }
2545
2546 if (specified_source &&
2547 (isc_sockaddr_pf(&query->sockaddr) !=
2548 isc_sockaddr_pf(&bind_address))) {
2549 printf(";; Skipping server %s, incompatible "
2550 "address family\n", query->servname);
2551 query->waiting_connect = ISC_FALSE;
2552 next = ISC_LIST_NEXT(query, link);
2553 l = query->lookup;
2554 clear_query(query);
2555 if (next == NULL) {
2556 printf(";; No acceptable nameservers\n");
2557 check_next_lookup(l);
2558 return;
2559 }
2560 send_tcp_connect(next);
2561 return;
2562 }
2563
2564 INSIST(query->sock == NULL);
2565
2566 if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) {
2567 sockcount++;
2568 isc_socket_attach(keep, &query->sock);
2569 query->waiting_connect = ISC_FALSE;
2570 launch_next_query(query, ISC_TRUE);
2571 goto search;
2572 }
2573
2574 result = isc_socket_create(socketmgr,
2575 isc_sockaddr_pf(&query->sockaddr),
2576 isc_sockettype_tcp, &query->sock);
2577 check_result(result, "isc_socket_create");
2578 sockcount++;
2579 debug("sockcount=%d", sockcount);
2580 if (specified_source)
2581 result = isc_socket_bind(query->sock, &bind_address,
2582 ISC_SOCKET_REUSEADDRESS);
2583 else {
2584 if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
2585 have_ipv4)
2586 isc_sockaddr_any(&bind_any);
2587 else
2588 isc_sockaddr_any6(&bind_any);
2589 result = isc_socket_bind(query->sock, &bind_any, 0);
2590 }
2591 check_result(result, "isc_socket_bind");
2592 bringup_timer(query, TCP_TIMEOUT);
2593 result = isc_socket_connect(query->sock, &query->sockaddr,
2594 global_task, connect_done, query);
2595 check_result(result, "isc_socket_connect");
2596 search:
2597 /*
2598 * If we're at the endgame of a nameserver search, we need to
2599 * immediately bring up all the queries. Do it here.
2600 */
2601 if (l->ns_search_only && !l->trace_root) {
2602 debug("sending next, since searching");
2603 next = ISC_LIST_NEXT(query, link);
2604 if (ISC_LINK_LINKED(query, link))
2605 ISC_LIST_DEQUEUE(l->q, query, link);
2606 ISC_LIST_ENQUEUE(l->connecting, query, clink);
2607 if (next != NULL)
2608 send_tcp_connect(next);
2609 }
2610 }
2611
2612 static isc_buffer_t *
clone_buffer(isc_buffer_t * source)2613 clone_buffer(isc_buffer_t *source) {
2614 isc_buffer_t *buffer;
2615 buffer = isc_mem_allocate(mctx, sizeof(*buffer));
2616 if (buffer == NULL)
2617 fatal("memory allocation failure in %s:%d",
2618 __FILE__, __LINE__);
2619 *buffer = *source;
2620 return (buffer);
2621 }
2622
2623 /*%
2624 * Send a UDP packet to the remote nameserver, possible starting the
2625 * recv action as well. Also make sure that the timer is running and
2626 * is properly reset.
2627 */
2628 static void
send_udp(dig_query_t * query)2629 send_udp(dig_query_t *query) {
2630 dig_lookup_t *l = NULL;
2631 isc_result_t result;
2632 isc_buffer_t *sendbuf;
2633
2634 debug("send_udp(%p)", query);
2635
2636 l = query->lookup;
2637 bringup_timer(query, UDP_TIMEOUT);
2638 l->current_query = query;
2639 debug("working on lookup %p, query %p", query->lookup, query);
2640 if (!query->recv_made) {
2641 /* XXX Check the sense of this, need assertion? */
2642 query->waiting_connect = ISC_FALSE;
2643 result = get_address(query->servname, port, &query->sockaddr);
2644 if (result != ISC_R_SUCCESS) {
2645 /* This servname doesn't have an address. */
2646 force_timeout(l, query);
2647 return;
2648 }
2649
2650 result = isc_socket_create(socketmgr,
2651 isc_sockaddr_pf(&query->sockaddr),
2652 isc_sockettype_udp, &query->sock);
2653 check_result(result, "isc_socket_create");
2654 sockcount++;
2655 debug("sockcount=%d", sockcount);
2656 if (specified_source) {
2657 result = isc_socket_bind(query->sock, &bind_address,
2658 ISC_SOCKET_REUSEADDRESS);
2659 } else {
2660 isc_sockaddr_anyofpf(&bind_any,
2661 isc_sockaddr_pf(&query->sockaddr));
2662 result = isc_socket_bind(query->sock, &bind_any, 0);
2663 }
2664 check_result(result, "isc_socket_bind");
2665
2666 query->recv_made = ISC_TRUE;
2667 ISC_LINK_INIT(&query->recvbuf, link);
2668 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf,
2669 link);
2670 debug("recving with lookup=%p, query=%p, sock=%p",
2671 query->lookup, query, query->sock);
2672 result = isc_socket_recvv(query->sock, &query->recvlist, 1,
2673 global_task, recv_done, query);
2674 check_result(result, "isc_socket_recvv");
2675 recvcount++;
2676 debug("recvcount=%d", recvcount);
2677 }
2678 ISC_LIST_INIT(query->sendlist);
2679 sendbuf = clone_buffer(&query->sendbuf);
2680 ISC_LIST_ENQUEUE(query->sendlist, sendbuf, link);
2681 debug("sending a request");
2682 TIME_NOW(&query->time_sent);
2683 INSIST(query->sock != NULL);
2684 query->waiting_senddone = ISC_TRUE;
2685 result = isc_socket_sendtov2(query->sock, &query->sendlist,
2686 global_task, send_done, query,
2687 &query->sockaddr, NULL,
2688 ISC_SOCKFLAG_NORETRY);
2689 check_result(result, "isc_socket_sendtov");
2690 sendcount++;
2691 }
2692
2693 /*%
2694 * IO timeout handler, used for both connect and recv timeouts. If
2695 * retries are still allowed, either resend the UDP packet or queue a
2696 * new TCP lookup. Otherwise, cancel the lookup.
2697 */
2698 static void
connect_timeout(isc_task_t * task,isc_event_t * event)2699 connect_timeout(isc_task_t *task, isc_event_t *event) {
2700 dig_lookup_t *l = NULL;
2701 dig_query_t *query = NULL, *next, *cq;
2702
2703 UNUSED(task);
2704 REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE);
2705
2706 debug("connect_timeout()");
2707
2708 LOCK_LOOKUP;
2709 l = event->ev_arg;
2710 query = l->current_query;
2711 isc_event_free(&event);
2712
2713 INSIST(!free_now);
2714
2715 if ((query != NULL) && (query->lookup->current_query != NULL) &&
2716 (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) {
2717 debug("trying next server...");
2718 cq = query->lookup->current_query;
2719 if (!l->tcp_mode)
2720 send_udp(ISC_LIST_NEXT(cq, link));
2721 else {
2722 if (query->sock != NULL)
2723 isc_socket_cancel(query->sock, NULL,
2724 ISC_SOCKCANCEL_ALL);
2725 next = ISC_LIST_NEXT(cq, link);
2726 if (next != NULL)
2727 send_tcp_connect(next);
2728 }
2729 UNLOCK_LOOKUP;
2730 return;
2731 }
2732
2733 if (l->retries > 1) {
2734 if (!l->tcp_mode) {
2735 l->retries--;
2736 debug("resending UDP request to first server");
2737 send_udp(ISC_LIST_HEAD(l->q));
2738 } else {
2739 debug("making new TCP request, %d tries left",
2740 l->retries);
2741 l->retries--;
2742 requeue_lookup(l, ISC_TRUE);
2743 cancel_lookup(l);
2744 check_next_lookup(l);
2745 }
2746 } else {
2747 fputs(l->cmdline, stdout);
2748 printf(";; connection timed out; no servers could be "
2749 "reached\n");
2750 cancel_lookup(l);
2751 check_next_lookup(l);
2752 if (exitcode < 9)
2753 exitcode = 9;
2754 }
2755 UNLOCK_LOOKUP;
2756 }
2757
2758 /*%
2759 * Event handler for the TCP recv which gets the length header of TCP
2760 * packets. Start the next recv of length bytes.
2761 */
2762 static void
tcp_length_done(isc_task_t * task,isc_event_t * event)2763 tcp_length_done(isc_task_t *task, isc_event_t *event) {
2764 isc_socketevent_t *sevent;
2765 isc_buffer_t *b = NULL;
2766 isc_result_t result;
2767 dig_query_t *query = NULL;
2768 dig_lookup_t *l;
2769 isc_uint16_t length;
2770
2771 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
2772 INSIST(!free_now);
2773
2774 UNUSED(task);
2775
2776 debug("tcp_length_done()");
2777
2778 LOCK_LOOKUP;
2779 sevent = (isc_socketevent_t *)event;
2780 query = event->ev_arg;
2781
2782 recvcount--;
2783 INSIST(recvcount >= 0);
2784
2785 b = ISC_LIST_HEAD(sevent->bufferlist);
2786 INSIST(b == &query->lengthbuf);
2787 ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
2788
2789 if (sevent->result == ISC_R_CANCELED) {
2790 isc_event_free(&event);
2791 l = query->lookup;
2792 clear_query(query);
2793 check_next_lookup(l);
2794 UNLOCK_LOOKUP;
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 l = query->lookup;
2804 isc_socket_detach(&query->sock);
2805 sockcount--;
2806 debug("sockcount=%d", sockcount);
2807 INSIST(sockcount >= 0);
2808 isc_event_free(&event);
2809 clear_query(query);
2810 check_next_lookup(l);
2811 UNLOCK_LOOKUP;
2812 return;
2813 }
2814 length = isc_buffer_getuint16(b);
2815 if (length == 0) {
2816 isc_event_free(&event);
2817 launch_next_query(query, ISC_FALSE);
2818 UNLOCK_LOOKUP;
2819 return;
2820 }
2821
2822 /*
2823 * Even though the buffer was already init'ed, we need
2824 * to redo it now, to force the length we want.
2825 */
2826 isc_buffer_invalidate(&query->recvbuf);
2827 isc_buffer_init(&query->recvbuf, query->recvspace, length);
2828 ENSURE(ISC_LIST_EMPTY(query->recvlist));
2829 ISC_LINK_INIT(&query->recvbuf, link);
2830 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
2831 debug("recving with lookup=%p, query=%p", query->lookup, query);
2832 result = isc_socket_recvv(query->sock, &query->recvlist, length, task,
2833 recv_done, query);
2834 check_result(result, "isc_socket_recvv");
2835 recvcount++;
2836 debug("resubmitted recv request with length %d, recvcount=%d",
2837 length, recvcount);
2838 isc_event_free(&event);
2839 UNLOCK_LOOKUP;
2840 }
2841
2842 /*%
2843 * For transfers that involve multiple recvs (XFR's in particular),
2844 * launch the next recv.
2845 */
2846 static void
launch_next_query(dig_query_t * query,isc_boolean_t include_question)2847 launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
2848 isc_result_t result;
2849 dig_lookup_t *l;
2850 isc_buffer_t *buffer;
2851
2852 INSIST(!free_now);
2853
2854 debug("launch_next_query()");
2855
2856 if (!query->lookup->pending) {
2857 debug("ignoring launch_next_query because !pending");
2858 isc_socket_detach(&query->sock);
2859 sockcount--;
2860 debug("sockcount=%d", sockcount);
2861 INSIST(sockcount >= 0);
2862 query->waiting_connect = ISC_FALSE;
2863 l = query->lookup;
2864 clear_query(query);
2865 check_next_lookup(l);
2866 return;
2867 }
2868
2869 isc_buffer_clear(&query->slbuf);
2870 isc_buffer_clear(&query->lengthbuf);
2871 isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->sendbuf.used);
2872 ISC_LIST_INIT(query->sendlist);
2873 ISC_LINK_INIT(&query->slbuf, link);
2874 if (!query->first_soa_rcvd) {
2875 buffer = clone_buffer(&query->slbuf);
2876 ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
2877 if (include_question) {
2878 buffer = clone_buffer(&query->sendbuf);
2879 ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
2880 }
2881 }
2882
2883 ISC_LINK_INIT(&query->lengthbuf, link);
2884 ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
2885
2886 result = isc_socket_recvv(query->sock, &query->lengthlist, 0,
2887 global_task, tcp_length_done, query);
2888 check_result(result, "isc_socket_recvv");
2889 recvcount++;
2890 debug("recvcount=%d", recvcount);
2891 if (!query->first_soa_rcvd) {
2892 debug("sending a request in launch_next_query");
2893 TIME_NOW(&query->time_sent);
2894 query->waiting_senddone = ISC_TRUE;
2895 result = isc_socket_sendv(query->sock, &query->sendlist,
2896 global_task, send_done, query);
2897 check_result(result, "isc_socket_sendv");
2898 sendcount++;
2899 debug("sendcount=%d", sendcount);
2900 }
2901 query->waiting_connect = ISC_FALSE;
2902 #if 0
2903 check_next_lookup(query->lookup);
2904 #endif
2905 return;
2906 }
2907
2908 /*%
2909 * Event handler for TCP connect complete. Make sure the connection was
2910 * successful, then pass into launch_next_query to actually send the
2911 * question.
2912 */
2913 static void
connect_done(isc_task_t * task,isc_event_t * event)2914 connect_done(isc_task_t *task, isc_event_t *event) {
2915 isc_socketevent_t *sevent = NULL;
2916 dig_query_t *query = NULL, *next;
2917 dig_lookup_t *l;
2918
2919 UNUSED(task);
2920
2921 REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
2922 INSIST(!free_now);
2923
2924 debug("connect_done()");
2925
2926 LOCK_LOOKUP;
2927 sevent = (isc_socketevent_t *)event;
2928 query = sevent->ev_arg;
2929
2930 INSIST(query->waiting_connect);
2931
2932 query->waiting_connect = ISC_FALSE;
2933
2934 if (sevent->result == ISC_R_CANCELED) {
2935 debug("in cancel handler");
2936 isc_socket_detach(&query->sock);
2937 INSIST(sockcount > 0);
2938 sockcount--;
2939 debug("sockcount=%d", sockcount);
2940 query->waiting_connect = ISC_FALSE;
2941 isc_event_free(&event);
2942 l = query->lookup;
2943 clear_query(query);
2944 check_next_lookup(l);
2945 UNLOCK_LOOKUP;
2946 return;
2947 }
2948 if (sevent->result != ISC_R_SUCCESS) {
2949 char sockstr[ISC_SOCKADDR_FORMATSIZE];
2950
2951 debug("unsuccessful connection: %s",
2952 isc_result_totext(sevent->result));
2953 isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
2954 if (sevent->result != ISC_R_CANCELED)
2955 printf(";; Connection to %s(%s) for %s failed: "
2956 "%s.\n", sockstr,
2957 query->servname, query->lookup->textname,
2958 isc_result_totext(sevent->result));
2959 isc_socket_detach(&query->sock);
2960 sockcount--;
2961 INSIST(sockcount >= 0);
2962 /* XXX Clean up exitcodes */
2963 if (exitcode < 9)
2964 exitcode = 9;
2965 debug("sockcount=%d", sockcount);
2966 query->waiting_connect = ISC_FALSE;
2967 isc_event_free(&event);
2968 l = query->lookup;
2969 if ((l->current_query != NULL) &&
2970 (ISC_LINK_LINKED(l->current_query, link)))
2971 next = ISC_LIST_NEXT(l->current_query, link);
2972 else
2973 next = NULL;
2974 clear_query(query);
2975 if (next != NULL) {
2976 bringup_timer(next, TCP_TIMEOUT);
2977 send_tcp_connect(next);
2978 } else
2979 check_next_lookup(l);
2980 UNLOCK_LOOKUP;
2981 return;
2982 }
2983 if (keep_open) {
2984 if (keep != NULL)
2985 isc_socket_detach(&keep);
2986 isc_socket_attach(query->sock, &keep);
2987 keepaddr = query->sockaddr;
2988 }
2989 launch_next_query(query, ISC_TRUE);
2990 isc_event_free(&event);
2991 UNLOCK_LOOKUP;
2992 }
2993
2994 /*%
2995 * Check if the ongoing XFR needs more data before it's complete, using
2996 * the semantics of IXFR and AXFR protocols. Much of the complexity of
2997 * this routine comes from determining when an IXFR is complete.
2998 * ISC_FALSE means more data is on the way, and the recv has been issued.
2999 */
3000 static isc_boolean_t
check_for_more_data(dig_query_t * query,dns_message_t * msg,isc_socketevent_t * sevent)3001 check_for_more_data(dig_query_t *query, dns_message_t *msg,
3002 isc_socketevent_t *sevent)
3003 {
3004 dns_rdataset_t *rdataset = NULL;
3005 dns_rdata_t rdata = DNS_RDATA_INIT;
3006 dns_rdata_soa_t soa;
3007 isc_uint32_t ixfr_serial = query->lookup->ixfr_serial, serial;
3008 isc_result_t result;
3009 isc_boolean_t ixfr = query->lookup->rdtype == dns_rdatatype_ixfr;
3010 isc_boolean_t axfr = query->lookup->rdtype == dns_rdatatype_axfr;
3011
3012 if (ixfr)
3013 axfr = query->ixfr_axfr;
3014
3015 debug("check_for_more_data()");
3016
3017 /*
3018 * By the time we're in this routine, we know we're doing
3019 * either an AXFR or IXFR. If there's no second_rr_type,
3020 * then we don't yet know which kind of answer we got back
3021 * from the server. Here, we're going to walk through the
3022 * rr's in the message, acting as necessary whenever we hit
3023 * an SOA rr.
3024 */
3025
3026 query->msg_count++;
3027 query->byte_count += sevent->n;
3028 result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
3029 if (result != ISC_R_SUCCESS) {
3030 puts("; Transfer failed.");
3031 return (ISC_TRUE);
3032 }
3033 do {
3034 dns_name_t *name;
3035 name = NULL;
3036 dns_message_currentname(msg, DNS_SECTION_ANSWER,
3037 &name);
3038 for (rdataset = ISC_LIST_HEAD(name->list);
3039 rdataset != NULL;
3040 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3041 result = dns_rdataset_first(rdataset);
3042 if (result != ISC_R_SUCCESS)
3043 continue;
3044 do {
3045 query->rr_count++;
3046 dns_rdata_reset(&rdata);
3047 dns_rdataset_current(rdataset, &rdata);
3048 /*
3049 * If this is the first rr, make sure
3050 * it's an SOA
3051 */
3052 if ((!query->first_soa_rcvd) &&
3053 (rdata.type != dns_rdatatype_soa)) {
3054 puts("; Transfer failed. "
3055 "Didn't start with SOA answer.");
3056 return (ISC_TRUE);
3057 }
3058 if ((!query->second_rr_rcvd) &&
3059 (rdata.type != dns_rdatatype_soa)) {
3060 query->second_rr_rcvd = ISC_TRUE;
3061 query->second_rr_serial = 0;
3062 debug("got the second rr as nonsoa");
3063 axfr = query->ixfr_axfr = ISC_TRUE;
3064 goto next_rdata;
3065 }
3066
3067 /*
3068 * If the record is anything except an SOA
3069 * now, just continue on...
3070 */
3071 if (rdata.type != dns_rdatatype_soa)
3072 goto next_rdata;
3073
3074 /* Now we have an SOA. Work with it. */
3075 debug("got an SOA");
3076 result = dns_rdata_tostruct(&rdata, &soa, NULL);
3077 check_result(result, "dns_rdata_tostruct");
3078 serial = soa.serial;
3079 dns_rdata_freestruct(&soa);
3080 if (!query->first_soa_rcvd) {
3081 query->first_soa_rcvd = ISC_TRUE;
3082 query->first_rr_serial = serial;
3083 debug("this is the first serial %u",
3084 serial);
3085 if (ixfr && isc_serial_ge(ixfr_serial,
3086 serial)) {
3087 debug("got up to date "
3088 "response");
3089 goto doexit;
3090 }
3091 goto next_rdata;
3092 }
3093 if (axfr) {
3094 debug("doing axfr, got second SOA");
3095 goto doexit;
3096 }
3097 if (!query->second_rr_rcvd) {
3098 if (query->first_rr_serial == serial) {
3099 debug("doing ixfr, got "
3100 "empty zone");
3101 goto doexit;
3102 }
3103 debug("this is the second serial %u",
3104 serial);
3105 query->second_rr_rcvd = ISC_TRUE;
3106 query->second_rr_serial = serial;
3107 goto next_rdata;
3108 }
3109 /*
3110 * If we get to this point, we're doing an
3111 * IXFR and have to start really looking
3112 * at serial numbers.
3113 */
3114 if (query->first_rr_serial == serial) {
3115 debug("got a match for ixfr");
3116 if (!query->first_repeat_rcvd) {
3117 query->first_repeat_rcvd =
3118 ISC_TRUE;
3119 goto next_rdata;
3120 }
3121 debug("done with ixfr");
3122 goto doexit;
3123 }
3124 debug("meaningless soa %u", serial);
3125 next_rdata:
3126 result = dns_rdataset_next(rdataset);
3127 } while (result == ISC_R_SUCCESS);
3128 }
3129 result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
3130 } while (result == ISC_R_SUCCESS);
3131 launch_next_query(query, ISC_FALSE);
3132 return (ISC_FALSE);
3133 doexit:
3134 received(sevent->n, &sevent->address, query);
3135 return (ISC_TRUE);
3136 }
3137
3138 /*%
3139 * Event handler for recv complete. Perform whatever actions are necessary,
3140 * based on the specifics of the user's request.
3141 */
3142 static void
recv_done(isc_task_t * task,isc_event_t * event)3143 recv_done(isc_task_t *task, isc_event_t *event) {
3144 isc_socketevent_t *sevent = NULL;
3145 dig_query_t *query = NULL;
3146 isc_buffer_t *b = NULL;
3147 dns_message_t *msg = NULL;
3148 #ifdef DIG_SIGCHASE
3149 dig_message_t *chase_msg = NULL;
3150 dig_message_t *chase_msg2 = NULL;
3151 #endif
3152 isc_result_t result;
3153 dig_lookup_t *n, *l;
3154 isc_boolean_t docancel = ISC_FALSE;
3155 isc_boolean_t match = ISC_TRUE;
3156 unsigned int parseflags;
3157 dns_messageid_t id;
3158 unsigned int msgflags;
3159 #ifdef DIG_SIGCHASE
3160 isc_result_t do_sigchase = ISC_FALSE;
3161
3162 dns_message_t *msg_temp = NULL;
3163 isc_region_t r;
3164 isc_buffer_t *buf = NULL;
3165 #endif
3166
3167 UNUSED(task);
3168 INSIST(!free_now);
3169
3170 debug("recv_done()");
3171
3172 LOCK_LOOKUP;
3173 recvcount--;
3174 debug("recvcount=%d", recvcount);
3175 INSIST(recvcount >= 0);
3176
3177 query = event->ev_arg;
3178 TIME_NOW(&query->time_recv);
3179 debug("lookup=%p, query=%p", query->lookup, query);
3180
3181 l = query->lookup;
3182
3183 REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
3184 sevent = (isc_socketevent_t *)event;
3185
3186 b = ISC_LIST_HEAD(sevent->bufferlist);
3187 INSIST(b == &query->recvbuf);
3188 ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link);
3189
3190 if ((l->tcp_mode) && (l->timer != NULL))
3191 isc_timer_touch(l->timer);
3192 if ((!l->pending && !l->ns_search_only) || cancel_now) {
3193 debug("no longer pending. Got %s",
3194 isc_result_totext(sevent->result));
3195 query->waiting_connect = ISC_FALSE;
3196
3197 isc_event_free(&event);
3198 clear_query(query);
3199 check_next_lookup(l);
3200 UNLOCK_LOOKUP;
3201 return;
3202 }
3203
3204 if (sevent->result != ISC_R_SUCCESS) {
3205 if (sevent->result == ISC_R_CANCELED) {
3206 debug("in recv cancel handler");
3207 query->waiting_connect = ISC_FALSE;
3208 } else {
3209 printf(";; communications error: %s\n",
3210 isc_result_totext(sevent->result));
3211 isc_socket_detach(&query->sock);
3212 sockcount--;
3213 debug("sockcount=%d", sockcount);
3214 INSIST(sockcount >= 0);
3215 }
3216 isc_event_free(&event);
3217 clear_query(query);
3218 check_next_lookup(l);
3219 UNLOCK_LOOKUP;
3220 return;
3221 }
3222
3223 if (!l->tcp_mode &&
3224 !isc_sockaddr_compare(&sevent->address, &query->sockaddr,
3225 ISC_SOCKADDR_CMPADDR|
3226 ISC_SOCKADDR_CMPPORT|
3227 ISC_SOCKADDR_CMPSCOPE|
3228 ISC_SOCKADDR_CMPSCOPEZERO)) {
3229 char buf1[ISC_SOCKADDR_FORMATSIZE];
3230 char buf2[ISC_SOCKADDR_FORMATSIZE];
3231 isc_sockaddr_t any;
3232
3233 if (isc_sockaddr_pf(&query->sockaddr) == AF_INET)
3234 isc_sockaddr_any(&any);
3235 else
3236 isc_sockaddr_any6(&any);
3237
3238 /*
3239 * We don't expect a match when the packet is
3240 * sent to 0.0.0.0, :: or to a multicast addresses.
3241 * XXXMPA broadcast needs to be handled here as well.
3242 */
3243 if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) &&
3244 !isc_sockaddr_ismulticast(&query->sockaddr)) ||
3245 isc_sockaddr_getport(&query->sockaddr) !=
3246 isc_sockaddr_getport(&sevent->address)) {
3247 isc_sockaddr_format(&sevent->address, buf1,
3248 sizeof(buf1));
3249 isc_sockaddr_format(&query->sockaddr, buf2,
3250 sizeof(buf2));
3251 printf(";; reply from unexpected source: %s,"
3252 " expected %s\n", buf1, buf2);
3253 match = ISC_FALSE;
3254 }
3255 }
3256
3257 result = dns_message_peekheader(b, &id, &msgflags);
3258 if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
3259 match = ISC_FALSE;
3260 if (l->tcp_mode) {
3261 isc_boolean_t fail = ISC_TRUE;
3262 if (result == ISC_R_SUCCESS) {
3263 if (!query->first_soa_rcvd ||
3264 query->warn_id)
3265 printf(";; %s: ID mismatch: "
3266 "expected ID %u, got %u\n",
3267 query->first_soa_rcvd ?
3268 "WARNING" : "ERROR",
3269 l->sendmsg->id, id);
3270 if (query->first_soa_rcvd)
3271 fail = ISC_FALSE;
3272 query->warn_id = ISC_FALSE;
3273 } else
3274 printf(";; ERROR: short "
3275 "(< header size) message\n");
3276 if (fail) {
3277 isc_event_free(&event);
3278 clear_query(query);
3279 check_next_lookup(l);
3280 UNLOCK_LOOKUP;
3281 return;
3282 }
3283 match = ISC_TRUE;
3284 } else if (result == ISC_R_SUCCESS)
3285 printf(";; Warning: ID mismatch: "
3286 "expected ID %u, got %u\n", l->sendmsg->id, id);
3287 else
3288 printf(";; Warning: short "
3289 "(< header size) message received\n");
3290 }
3291
3292 if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0)
3293 printf(";; Warning: query response not set\n");
3294
3295 if (!match)
3296 goto udp_mismatch;
3297
3298 result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
3299 check_result(result, "dns_message_create");
3300
3301 if (key != NULL) {
3302 if (l->querysig == NULL) {
3303 debug("getting initial querysig");
3304 result = dns_message_getquerytsig(l->sendmsg, mctx,
3305 &l->querysig);
3306 check_result(result, "dns_message_getquerytsig");
3307 }
3308 result = dns_message_setquerytsig(msg, l->querysig);
3309 check_result(result, "dns_message_setquerytsig");
3310 result = dns_message_settsigkey(msg, key);
3311 check_result(result, "dns_message_settsigkey");
3312 msg->tsigctx = l->tsigctx;
3313 l->tsigctx = NULL;
3314 if (l->msgcounter != 0)
3315 msg->tcp_continuation = 1;
3316 l->msgcounter++;
3317 }
3318
3319 debug("before parse starts");
3320 parseflags = DNS_MESSAGEPARSE_PRESERVEORDER;
3321 #ifdef DIG_SIGCHASE
3322 if (!l->sigchase) {
3323 do_sigchase = ISC_FALSE;
3324 } else {
3325 parseflags = 0;
3326 do_sigchase = ISC_TRUE;
3327 }
3328 #endif
3329 if (l->besteffort) {
3330 parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
3331 parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
3332 }
3333 result = dns_message_parse(msg, b, parseflags);
3334 if (result == DNS_R_RECOVERABLE) {
3335 printf(";; Warning: Message parser reports malformed "
3336 "message packet.\n");
3337 result = ISC_R_SUCCESS;
3338 }
3339 if (result != ISC_R_SUCCESS) {
3340 printf(";; Got bad packet: %s\n", isc_result_totext(result));
3341 hex_dump(b);
3342 query->waiting_connect = ISC_FALSE;
3343 dns_message_destroy(&msg);
3344 isc_event_free(&event);
3345 clear_query(query);
3346 cancel_lookup(l);
3347 check_next_lookup(l);
3348 UNLOCK_LOOKUP;
3349 return;
3350 }
3351 if (msg->counts[DNS_SECTION_QUESTION] != 0) {
3352 match = ISC_TRUE;
3353 for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
3354 result == ISC_R_SUCCESS && match;
3355 result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) {
3356 dns_name_t *name = NULL;
3357 dns_rdataset_t *rdataset;
3358
3359 dns_message_currentname(msg, DNS_SECTION_QUESTION,
3360 &name);
3361 for (rdataset = ISC_LIST_HEAD(name->list);
3362 rdataset != NULL;
3363 rdataset = ISC_LIST_NEXT(rdataset, link)) {
3364 if (l->rdtype != rdataset->type ||
3365 l->rdclass != rdataset->rdclass ||
3366 !dns_name_equal(l->name, name)) {
3367 char namestr[DNS_NAME_FORMATSIZE];
3368 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3369 char classbuf[DNS_RDATACLASS_FORMATSIZE];
3370 dns_name_format(name, namestr,
3371 sizeof(namestr));
3372 dns_rdatatype_format(rdataset->type,
3373 typebuf,
3374 sizeof(typebuf));
3375 dns_rdataclass_format(rdataset->rdclass,
3376 classbuf,
3377 sizeof(classbuf));
3378 printf(";; Question section mismatch: "
3379 "got %s/%s/%s\n",
3380 namestr, typebuf, classbuf);
3381 match = ISC_FALSE;
3382 }
3383 }
3384 }
3385 if (!match) {
3386 dns_message_destroy(&msg);
3387 if (l->tcp_mode) {
3388 isc_event_free(&event);
3389 clear_query(query);
3390 check_next_lookup(l);
3391 UNLOCK_LOOKUP;
3392 return;
3393 } else
3394 goto udp_mismatch;
3395 }
3396 }
3397 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 &&
3398 !l->ignore && !l->tcp_mode) {
3399 printf(";; Truncated, retrying in TCP mode.\n");
3400 n = requeue_lookup(l, ISC_TRUE);
3401 n->tcp_mode = ISC_TRUE;
3402 n->origin = query->lookup->origin;
3403 if (l->trace && l->trace_root)
3404 n->rdtype = l->qrdtype;
3405 dns_message_destroy(&msg);
3406 isc_event_free(&event);
3407 clear_query(query);
3408 cancel_lookup(l);
3409 check_next_lookup(l);
3410 UNLOCK_LOOKUP;
3411 return;
3412 }
3413 if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) ||
3414 (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse))
3415 {
3416 dig_query_t *next = ISC_LIST_NEXT(query, link);
3417 if (l->current_query == query)
3418 l->current_query = NULL;
3419 if (next != NULL) {
3420 debug("sending query %p\n", next);
3421 if (l->tcp_mode)
3422 send_tcp_connect(next);
3423 else
3424 send_udp(next);
3425 }
3426 /*
3427 * If our query is at the head of the list and there
3428 * is no next, we're the only one left, so fall
3429 * through to print the message.
3430 */
3431 if ((ISC_LIST_HEAD(l->q) != query) ||
3432 (ISC_LIST_NEXT(query, link) != NULL)) {
3433 if( l->comments == ISC_TRUE )
3434 printf(";; Got %s from %s, "
3435 "trying next server\n",
3436 msg->rcode == dns_rcode_servfail ?
3437 "SERVFAIL reply" :
3438 "recursion not available",
3439 query->servname);
3440 clear_query(query);
3441 check_next_lookup(l);
3442 dns_message_destroy(&msg);
3443 isc_event_free(&event);
3444 UNLOCK_LOOKUP;
3445 return;
3446 }
3447 }
3448
3449 if (key != NULL) {
3450 result = dns_tsig_verify(&query->recvbuf, msg, NULL, NULL);
3451 if (result != ISC_R_SUCCESS) {
3452 printf(";; Couldn't verify signature: %s\n",
3453 isc_result_totext(result));
3454 validated = ISC_FALSE;
3455 }
3456 l->tsigctx = msg->tsigctx;
3457 msg->tsigctx = NULL;
3458 if (l->querysig != NULL) {
3459 debug("freeing querysig buffer %p", l->querysig);
3460 isc_buffer_free(&l->querysig);
3461 }
3462 result = dns_message_getquerytsig(msg, mctx, &l->querysig);
3463 check_result(result,"dns_message_getquerytsig");
3464 }
3465
3466 extrabytes = isc_buffer_remaininglength(b);
3467
3468 debug("after parse");
3469 if (l->doing_xfr && l->xfr_q == NULL) {
3470 l->xfr_q = query;
3471 /*
3472 * Once we are in the XFR message, increase
3473 * the timeout to much longer, so brief network
3474 * outages won't cause the XFR to abort
3475 */
3476 if (timeout != INT_MAX && l->timer != NULL) {
3477 unsigned int local_timeout;
3478
3479 if (timeout == 0) {
3480 if (l->tcp_mode)
3481 local_timeout = TCP_TIMEOUT * 4;
3482 else
3483 local_timeout = UDP_TIMEOUT * 4;
3484 } else {
3485 if (timeout < (INT_MAX / 4))
3486 local_timeout = timeout * 4;
3487 else
3488 local_timeout = INT_MAX;
3489 }
3490 debug("have local timeout of %d", local_timeout);
3491 isc_interval_set(&l->interval, local_timeout, 0);
3492 result = isc_timer_reset(l->timer,
3493 isc_timertype_once,
3494 NULL,
3495 &l->interval,
3496 ISC_FALSE);
3497 check_result(result, "isc_timer_reset");
3498 }
3499 }
3500
3501 if (!l->doing_xfr || l->xfr_q == query) {
3502 if (msg->rcode == dns_rcode_nxdomain &&
3503 (l->origin != NULL || l->need_search)) {
3504 if (!next_origin(query->lookup) || showsearch) {
3505 printmessage(query, msg, ISC_TRUE);
3506 received(b->used, &sevent->address, query);
3507 }
3508 } else if (!l->trace && !l->ns_search_only) {
3509 #ifdef DIG_SIGCHASE
3510 if (!do_sigchase)
3511 #endif
3512 printmessage(query, msg, ISC_TRUE);
3513 } else if (l->trace) {
3514 int nl = 0;
3515 int count = msg->counts[DNS_SECTION_ANSWER];
3516
3517 debug("in TRACE code");
3518 if (!l->ns_search_only)
3519 printmessage(query, msg, ISC_TRUE);
3520
3521 l->rdtype = l->qrdtype;
3522 if (l->trace_root || (l->ns_search_only && count > 0)) {
3523 if (!l->trace_root)
3524 l->rdtype = dns_rdatatype_soa;
3525 nl = followup_lookup(msg, query,
3526 DNS_SECTION_ANSWER);
3527 l->trace_root = ISC_FALSE;
3528 } else if (count == 0)
3529 nl = followup_lookup(msg, query,
3530 DNS_SECTION_AUTHORITY);
3531 if (nl == 0)
3532 docancel = ISC_TRUE;
3533 } else {
3534 debug("in NSSEARCH code");
3535
3536 if (l->trace_root) {
3537 /*
3538 * This is the initial NS query.
3539 */
3540 int nl;
3541
3542 l->rdtype = dns_rdatatype_soa;
3543 nl = followup_lookup(msg, query,
3544 DNS_SECTION_ANSWER);
3545 if (nl == 0)
3546 docancel = ISC_TRUE;
3547 l->trace_root = ISC_FALSE;
3548 usesearch = ISC_FALSE;
3549 } else
3550 #ifdef DIG_SIGCHASE
3551 if (!do_sigchase)
3552 #endif
3553 printmessage(query, msg, ISC_TRUE);
3554 }
3555 #ifdef DIG_SIGCHASE
3556 if (do_sigchase) {
3557 chase_msg = isc_mem_allocate(mctx,
3558 sizeof(dig_message_t));
3559 if (chase_msg == NULL) {
3560 fatal("Memory allocation failure in %s:%d",
3561 __FILE__, __LINE__);
3562 }
3563 ISC_LIST_INITANDAPPEND(chase_message_list, chase_msg,
3564 link);
3565 if (dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
3566 &msg_temp) != ISC_R_SUCCESS) {
3567 fatal("dns_message_create in %s:%d",
3568 __FILE__, __LINE__);
3569 }
3570
3571 isc_buffer_usedregion(b, &r);
3572 result = isc_buffer_allocate(mctx, &buf, r.length);
3573
3574 check_result(result, "isc_buffer_allocate");
3575 result = isc_buffer_copyregion(buf, &r);
3576 check_result(result, "isc_buffer_copyregion");
3577
3578 result = dns_message_parse(msg_temp, buf, 0);
3579
3580 isc_buffer_free(&buf);
3581 chase_msg->msg = msg_temp;
3582
3583 chase_msg2 = isc_mem_allocate(mctx,
3584 sizeof(dig_message_t));
3585 if (chase_msg2 == NULL) {
3586 fatal("Memory allocation failure in %s:%d",
3587 __FILE__, __LINE__);
3588 }
3589 ISC_LIST_INITANDAPPEND(chase_message_list2, chase_msg2,
3590 link);
3591 chase_msg2->msg = msg;
3592 }
3593 #endif
3594 }
3595
3596 #ifdef DIG_SIGCHASE
3597 if (l->sigchase && ISC_LIST_EMPTY(lookup_list)) {
3598 sigchase(msg_temp);
3599 }
3600 #endif
3601
3602 if (l->pending)
3603 debug("still pending.");
3604 if (l->doing_xfr) {
3605 if (query != l->xfr_q) {
3606 dns_message_destroy(&msg);
3607 isc_event_free(&event);
3608 query->waiting_connect = ISC_FALSE;
3609 UNLOCK_LOOKUP;
3610 return;
3611 }
3612 if (!docancel)
3613 docancel = check_for_more_data(query, msg, sevent);
3614 if (docancel) {
3615 dns_message_destroy(&msg);
3616 clear_query(query);
3617 cancel_lookup(l);
3618 check_next_lookup(l);
3619 }
3620 } else {
3621
3622 if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
3623
3624 #ifdef DIG_SIGCHASE
3625 if (!l->sigchase)
3626 #endif
3627 received(b->used, &sevent->address, query);
3628 }
3629
3630 if (!query->lookup->ns_search_only)
3631 query->lookup->pending = ISC_FALSE;
3632 if (!query->lookup->ns_search_only ||
3633 query->lookup->trace_root || docancel) {
3634 #ifdef DIG_SIGCHASE
3635 if (!do_sigchase)
3636 #endif
3637 dns_message_destroy(&msg);
3638
3639 cancel_lookup(l);
3640 }
3641 clear_query(query);
3642 check_next_lookup(l);
3643 }
3644 if (msg != NULL) {
3645 #ifdef DIG_SIGCHASE
3646 if (do_sigchase)
3647 msg = NULL;
3648 else
3649 #endif
3650 dns_message_destroy(&msg);
3651 }
3652 isc_event_free(&event);
3653 UNLOCK_LOOKUP;
3654 return;
3655
3656 udp_mismatch:
3657 isc_buffer_invalidate(&query->recvbuf);
3658 isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
3659 ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
3660 result = isc_socket_recvv(query->sock, &query->recvlist, 1,
3661 global_task, recv_done, query);
3662 check_result(result, "isc_socket_recvv");
3663 recvcount++;
3664 isc_event_free(&event);
3665 UNLOCK_LOOKUP;
3666 return;
3667 }
3668
3669 /*%
3670 * Turn a name into an address, using system-supplied routines. This is
3671 * used in looking up server names, etc... and needs to use system-supplied
3672 * routines, since they may be using a non-DNS system for these lookups.
3673 */
3674 isc_result_t
get_address(char * host,in_port_t myport,isc_sockaddr_t * sockaddr)3675 get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr) {
3676 int count;
3677 isc_result_t result;
3678 isc_boolean_t is_running;
3679
3680 is_running = isc_app_isrunning();
3681 if (is_running)
3682 isc_app_block();
3683 result = bind9_getaddresses(host, myport, sockaddr, 1, &count);
3684 if (is_running)
3685 isc_app_unblock();
3686 if (result != ISC_R_SUCCESS)
3687 return (result);
3688
3689 INSIST(count == 1);
3690
3691 return (ISC_R_SUCCESS);
3692 }
3693
3694 int
getaddresses(dig_lookup_t * lookup,const char * host,isc_result_t * resultp)3695 getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) {
3696 isc_result_t result;
3697 isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
3698 isc_netaddr_t netaddr;
3699 int count, i;
3700 dig_server_t *srv;
3701 char tmp[ISC_NETADDR_FORMATSIZE];
3702
3703 result = bind9_getaddresses(host, 0, sockaddrs,
3704 DIG_MAX_ADDRESSES, &count);
3705 if (resultp != NULL)
3706 *resultp = result;
3707 if (result != ISC_R_SUCCESS) {
3708 if (resultp == NULL)
3709 fatal("couldn't get address for '%s': %s",
3710 host, isc_result_totext(result));
3711 return 0;
3712 }
3713
3714 for (i = 0; i < count; i++) {
3715 isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
3716 isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
3717 srv = make_server(tmp, host);
3718 ISC_LIST_APPEND(lookup->my_server_list, srv, link);
3719 }
3720
3721 return count;
3722 }
3723
3724 /*%
3725 * Initiate either a TCP or UDP lookup
3726 */
3727 void
do_lookup(dig_lookup_t * lookup)3728 do_lookup(dig_lookup_t *lookup) {
3729 dig_query_t *query;
3730
3731 REQUIRE(lookup != NULL);
3732
3733 debug("do_lookup()");
3734 lookup->pending = ISC_TRUE;
3735 query = ISC_LIST_HEAD(lookup->q);
3736 if (query != NULL) {
3737 if (lookup->tcp_mode)
3738 send_tcp_connect(query);
3739 else
3740 send_udp(query);
3741 }
3742 }
3743
3744 /*%
3745 * Start everything in action upon task startup.
3746 */
3747 void
onrun_callback(isc_task_t * task,isc_event_t * event)3748 onrun_callback(isc_task_t *task, isc_event_t *event) {
3749 UNUSED(task);
3750
3751 isc_event_free(&event);
3752 LOCK_LOOKUP;
3753 start_lookup();
3754 UNLOCK_LOOKUP;
3755 }
3756
3757 /*%
3758 * Make everything on the lookup queue go away. Mainly used by the
3759 * SIGINT handler.
3760 */
3761 void
cancel_all(void)3762 cancel_all(void) {
3763 dig_lookup_t *l, *n;
3764 dig_query_t *q, *nq;
3765
3766 debug("cancel_all()");
3767
3768 LOCK_LOOKUP;
3769 if (free_now) {
3770 UNLOCK_LOOKUP;
3771 return;
3772 }
3773 cancel_now = ISC_TRUE;
3774 if (current_lookup != NULL) {
3775 if (current_lookup->timer != NULL)
3776 isc_timer_detach(¤t_lookup->timer);
3777 for (q = ISC_LIST_HEAD(current_lookup->q);
3778 q != NULL;
3779 q = nq)
3780 {
3781 nq = ISC_LIST_NEXT(q, link);
3782 debug("canceling pending query %p, belonging to %p",
3783 q, current_lookup);
3784 if (q->sock != NULL)
3785 isc_socket_cancel(q->sock, NULL,
3786 ISC_SOCKCANCEL_ALL);
3787 else
3788 clear_query(q);
3789 }
3790 for (q = ISC_LIST_HEAD(current_lookup->connecting);
3791 q != NULL;
3792 q = nq)
3793 {
3794 nq = ISC_LIST_NEXT(q, clink);
3795 debug("canceling connecting query %p, belonging to %p",
3796 q, current_lookup);
3797 if (q->sock != NULL)
3798 isc_socket_cancel(q->sock, NULL,
3799 ISC_SOCKCANCEL_ALL);
3800 else
3801 clear_query(q);
3802 }
3803 }
3804 l = ISC_LIST_HEAD(lookup_list);
3805 while (l != NULL) {
3806 n = ISC_LIST_NEXT(l, link);
3807 ISC_LIST_DEQUEUE(lookup_list, l, link);
3808 try_clear_lookup(l);
3809 l = n;
3810 }
3811 UNLOCK_LOOKUP;
3812 }
3813
3814 /*%
3815 * Destroy all of the libs we are using, and get everything ready for a
3816 * clean shutdown.
3817 */
3818 void
destroy_libs(void)3819 destroy_libs(void) {
3820 #ifdef DIG_SIGCHASE
3821 void * ptr;
3822 dig_message_t *chase_msg;
3823 #endif
3824 #ifdef WITH_IDN
3825 isc_result_t result;
3826 #endif
3827
3828 if (keep != NULL)
3829 isc_socket_detach(&keep);
3830 debug("destroy_libs()");
3831 if (global_task != NULL) {
3832 debug("freeing task");
3833 isc_task_detach(&global_task);
3834 }
3835 /*
3836 * The taskmgr_destroy() call blocks until all events are cleared
3837 * from the task.
3838 */
3839 if (taskmgr != NULL) {
3840 debug("freeing taskmgr");
3841 isc_taskmgr_destroy(&taskmgr);
3842 }
3843 LOCK_LOOKUP;
3844 REQUIRE(sockcount == 0);
3845 REQUIRE(recvcount == 0);
3846 REQUIRE(sendcount == 0);
3847
3848 INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
3849 INSIST(current_lookup == NULL);
3850 INSIST(!free_now);
3851
3852 free_now = ISC_TRUE;
3853
3854 lwres_conf_clear(lwctx);
3855 lwres_context_destroy(&lwctx);
3856
3857 flush_server_list();
3858
3859 clear_searchlist();
3860
3861 #ifdef WITH_IDN
3862 result = dns_name_settotextfilter(NULL);
3863 check_result(result, "dns_name_settotextfilter");
3864 #endif
3865 dns_name_destroy();
3866
3867 if (commctx != NULL) {
3868 debug("freeing commctx");
3869 isc_mempool_destroy(&commctx);
3870 }
3871 if (socketmgr != NULL) {
3872 debug("freeing socketmgr");
3873 isc_socketmgr_destroy(&socketmgr);
3874 }
3875 if (timermgr != NULL) {
3876 debug("freeing timermgr");
3877 isc_timermgr_destroy(&timermgr);
3878 }
3879 if (key != NULL) {
3880 debug("freeing key %p", key);
3881 dns_tsigkey_detach(&key);
3882 }
3883 if (namebuf != NULL)
3884 isc_buffer_free(&namebuf);
3885
3886 if (is_dst_up) {
3887 debug("destroy DST lib");
3888 dst_lib_destroy();
3889 is_dst_up = ISC_FALSE;
3890 }
3891 if (entp != NULL) {
3892 debug("detach from entropy");
3893 isc_entropy_detach(&entp);
3894 }
3895
3896 UNLOCK_LOOKUP;
3897 DESTROYLOCK(&lookup_lock);
3898 #ifdef DIG_SIGCHASE
3899
3900 debug("Destroy the messages kept for sigchase");
3901 /* Destroy the messages kept for sigchase */
3902 chase_msg = ISC_LIST_HEAD(chase_message_list);
3903
3904 while (chase_msg != NULL) {
3905 INSIST(chase_msg->msg != NULL);
3906 dns_message_destroy(&(chase_msg->msg));
3907 ptr = chase_msg;
3908 chase_msg = ISC_LIST_NEXT(chase_msg, link);
3909 isc_mem_free(mctx, ptr);
3910 }
3911
3912 chase_msg = ISC_LIST_HEAD(chase_message_list2);
3913
3914 while (chase_msg != NULL) {
3915 INSIST(chase_msg->msg != NULL);
3916 dns_message_destroy(&(chase_msg->msg));
3917 ptr = chase_msg;
3918 chase_msg = ISC_LIST_NEXT(chase_msg, link);
3919 isc_mem_free(mctx, ptr);
3920 }
3921 if (dns_name_dynamic(&chase_name))
3922 free_name(&chase_name);
3923 #if DIG_SIGCHASE_TD
3924 if (dns_name_dynamic(&chase_current_name))
3925 free_name(&chase_current_name);
3926 if (dns_name_dynamic(&chase_authority_name))
3927 free_name(&chase_authority_name);
3928 #endif
3929 #if DIG_SIGCHASE_BU
3930 if (dns_name_dynamic(&chase_signame))
3931 free_name(&chase_signame);
3932 #endif
3933
3934 #endif
3935 debug("Removing log context");
3936 isc_log_destroy(&lctx);
3937
3938 debug("Destroy memory");
3939 if (memdebugging != 0)
3940 isc_mem_stats(mctx, stderr);
3941 if (mctx != NULL)
3942 isc_mem_destroy(&mctx);
3943 }
3944
3945 #ifdef WITH_IDN
3946 static void
initialize_idn(void)3947 initialize_idn(void) {
3948 idn_result_t r;
3949 isc_result_t result;
3950
3951 #ifdef HAVE_SETLOCALE
3952 /* Set locale */
3953 (void)setlocale(LC_ALL, "");
3954 #endif
3955 /* Create configuration context. */
3956 r = idn_nameinit(1);
3957 if (r != idn_success)
3958 fatal("idn api initialization failed: %s",
3959 idn_result_tostring(r));
3960
3961 /* Set domain name -> text post-conversion filter. */
3962 result = dns_name_settotextfilter(output_filter);
3963 check_result(result, "dns_name_settotextfilter");
3964 }
3965
3966 static isc_result_t
output_filter(isc_buffer_t * buffer,unsigned int used_org,isc_boolean_t absolute)3967 output_filter(isc_buffer_t *buffer, unsigned int used_org,
3968 isc_boolean_t absolute)
3969 {
3970 char tmp1[MAXDLEN], tmp2[MAXDLEN];
3971 size_t fromlen, tolen;
3972 isc_boolean_t end_with_dot;
3973
3974 /*
3975 * Copy contents of 'buffer' to 'tmp1', supply trailing dot
3976 * if 'absolute' is true, and terminate with NUL.
3977 */
3978 fromlen = isc_buffer_usedlength(buffer) - used_org;
3979 if (fromlen >= MAXDLEN)
3980 return (ISC_R_SUCCESS);
3981 memmove(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
3982 end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE;
3983 if (absolute && !end_with_dot) {
3984 fromlen++;
3985 if (fromlen >= MAXDLEN)
3986 return (ISC_R_SUCCESS);
3987 tmp1[fromlen - 1] = '.';
3988 }
3989 tmp1[fromlen] = '\0';
3990
3991 /*
3992 * Convert contents of 'tmp1' to local encoding.
3993 */
3994 if (idn_decodename(IDN_DECODE_APP, tmp1, tmp2, MAXDLEN) != idn_success)
3995 return (ISC_R_SUCCESS);
3996 strcpy(tmp1, tmp2);
3997
3998 /*
3999 * Copy the converted contents in 'tmp1' back to 'buffer'.
4000 * If we have appended trailing dot, remove it.
4001 */
4002 tolen = strlen(tmp1);
4003 if (absolute && !end_with_dot && tmp1[tolen - 1] == '.')
4004 tolen--;
4005
4006 if (isc_buffer_length(buffer) < used_org + tolen)
4007 return (ISC_R_NOSPACE);
4008
4009 isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org);
4010 memmove(isc_buffer_used(buffer), tmp1, tolen);
4011 isc_buffer_add(buffer, (unsigned int)tolen);
4012
4013 return (ISC_R_SUCCESS);
4014 }
4015
4016 static idn_result_t
append_textname(char * name,const char * origin,size_t namesize)4017 append_textname(char *name, const char *origin, size_t namesize) {
4018 size_t namelen = strlen(name);
4019 size_t originlen = strlen(origin);
4020
4021 /* Already absolute? */
4022 if (namelen > 0 && name[namelen - 1] == '.')
4023 return idn_success;
4024
4025 /* Append dot and origin */
4026
4027 if (namelen + 1 + originlen >= namesize)
4028 return idn_buffer_overflow;
4029
4030 if (*origin != '.')
4031 name[namelen++] = '.';
4032 (void)strcpy(name + namelen, origin);
4033 return idn_success;
4034 }
4035
4036 static void
idn_check_result(idn_result_t r,const char * msg)4037 idn_check_result(idn_result_t r, const char *msg) {
4038 if (r != idn_success) {
4039 exitcode = 1;
4040 fatal("%s: %s", msg, idn_result_tostring(r));
4041 }
4042 }
4043 #endif /* WITH_IDN */
4044
4045 #ifdef DIG_SIGCHASE
4046 void
print_type(dns_rdatatype_t type)4047 print_type(dns_rdatatype_t type)
4048 {
4049 isc_buffer_t * b = NULL;
4050 isc_result_t result;
4051 isc_region_t r;
4052
4053 result = isc_buffer_allocate(mctx, &b, 4000);
4054 check_result(result, "isc_buffer_allocate");
4055
4056 result = dns_rdatatype_totext(type, b);
4057 check_result(result, "print_type");
4058
4059 isc_buffer_usedregion(b, &r);
4060 r.base[r.length] = '\0';
4061
4062 printf("%s", r.base);
4063
4064 isc_buffer_free(&b);
4065 }
4066
4067 void
dump_database_section(dns_message_t * msg,int section)4068 dump_database_section(dns_message_t *msg, int section)
4069 {
4070 dns_name_t *msg_name=NULL;
4071
4072 dns_rdataset_t *rdataset;
4073
4074 do {
4075 dns_message_currentname(msg, section, &msg_name);
4076
4077 for (rdataset = ISC_LIST_HEAD(msg_name->list); rdataset != NULL;
4078 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4079 dns_name_print(msg_name, stdout);
4080 printf("\n");
4081 print_rdataset(msg_name, rdataset);
4082 printf("end\n");
4083 }
4084 msg_name = NULL;
4085 } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
4086 }
4087
4088 void
dump_database(void)4089 dump_database(void) {
4090 dig_message_t * msg;
4091
4092 for (msg = ISC_LIST_HEAD(chase_message_list); msg != NULL;
4093 msg = ISC_LIST_NEXT(msg, link)) {
4094 if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
4095 == ISC_R_SUCCESS)
4096 dump_database_section(msg->msg, DNS_SECTION_ANSWER);
4097
4098 if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
4099 == ISC_R_SUCCESS)
4100 dump_database_section(msg->msg, DNS_SECTION_AUTHORITY);
4101
4102 if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
4103 == ISC_R_SUCCESS)
4104 dump_database_section(msg->msg, DNS_SECTION_ADDITIONAL);
4105 }
4106 }
4107
4108
4109 dns_rdataset_t *
search_type(dns_name_t * name,dns_rdatatype_t type,dns_rdatatype_t covers)4110 search_type(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) {
4111 dns_rdataset_t *rdataset;
4112 dns_rdata_sig_t siginfo;
4113 dns_rdata_t sigrdata = DNS_RDATA_INIT;
4114 isc_result_t result;
4115
4116 for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
4117 rdataset = ISC_LIST_NEXT(rdataset, link)) {
4118 if (type == dns_rdatatype_any) {
4119 if (rdataset->type != dns_rdatatype_rrsig)
4120 return (rdataset);
4121 } else if ((type == dns_rdatatype_rrsig) &&
4122 (rdataset->type == dns_rdatatype_rrsig)) {
4123 result = dns_rdataset_first(rdataset);
4124 check_result(result, "empty rdataset");
4125 dns_rdataset_current(rdataset, &sigrdata);
4126 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4127 check_result(result, "sigrdata tostruct siginfo");
4128
4129 if ((siginfo.covered == covers) ||
4130 (covers == dns_rdatatype_any)) {
4131 dns_rdata_reset(&sigrdata);
4132 dns_rdata_freestruct(&siginfo);
4133 return (rdataset);
4134 }
4135 dns_rdata_reset(&sigrdata);
4136 dns_rdata_freestruct(&siginfo);
4137 } else if (rdataset->type == type)
4138 return (rdataset);
4139 }
4140 return (NULL);
4141 }
4142
4143 dns_rdataset_t *
chase_scanname_section(dns_message_t * msg,dns_name_t * name,dns_rdatatype_t type,dns_rdatatype_t covers,int section)4144 chase_scanname_section(dns_message_t *msg, dns_name_t *name,
4145 dns_rdatatype_t type, dns_rdatatype_t covers,
4146 int section)
4147 {
4148 dns_rdataset_t *rdataset;
4149 dns_name_t *msg_name = NULL;
4150
4151 if (msg->counts[section] == 0)
4152 return (NULL);
4153
4154 do {
4155 dns_message_currentname(msg, section, &msg_name);
4156 if (dns_name_compare(msg_name, name) == 0) {
4157 rdataset = search_type(msg_name, type, covers);
4158 if (rdataset != NULL)
4159 return (rdataset);
4160 }
4161 msg_name = NULL;
4162 } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
4163
4164 return (NULL);
4165 }
4166
4167
4168 dns_rdataset_t *
chase_scanname(dns_name_t * name,dns_rdatatype_t type,dns_rdatatype_t covers)4169 chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers)
4170 {
4171 dns_rdataset_t *rdataset = NULL;
4172 dig_message_t * msg;
4173
4174 for (msg = ISC_LIST_HEAD(chase_message_list2); msg != NULL;
4175 msg = ISC_LIST_NEXT(msg, link)) {
4176 if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
4177 == ISC_R_SUCCESS)
4178 rdataset = chase_scanname_section(msg->msg, name,
4179 type, covers,
4180 DNS_SECTION_ANSWER);
4181 if (rdataset != NULL)
4182 return (rdataset);
4183 if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
4184 == ISC_R_SUCCESS)
4185 rdataset =
4186 chase_scanname_section(msg->msg, name,
4187 type, covers,
4188 DNS_SECTION_AUTHORITY);
4189 if (rdataset != NULL)
4190 return (rdataset);
4191 if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
4192 == ISC_R_SUCCESS)
4193 rdataset =
4194 chase_scanname_section(msg->msg, name, type,
4195 covers,
4196 DNS_SECTION_ADDITIONAL);
4197 if (rdataset != NULL)
4198 return (rdataset);
4199 }
4200
4201 return (NULL);
4202 }
4203
4204 dns_rdataset_t *
sigchase_scanname(dns_rdatatype_t type,dns_rdatatype_t covers,isc_boolean_t * lookedup,dns_name_t * rdata_name)4205 sigchase_scanname(dns_rdatatype_t type, dns_rdatatype_t covers,
4206 isc_boolean_t * lookedup, dns_name_t *rdata_name)
4207 {
4208 dig_lookup_t *lookup;
4209 isc_buffer_t *b = NULL;
4210 isc_region_t r;
4211 isc_result_t result;
4212 dns_rdataset_t * temp;
4213 dns_rdatatype_t querytype;
4214
4215 temp = chase_scanname(rdata_name, type, covers);
4216 if (temp != NULL)
4217 return (temp);
4218
4219 if (*lookedup == ISC_TRUE)
4220 return (NULL);
4221
4222 lookup = clone_lookup(current_lookup, ISC_TRUE);
4223 lookup->trace_root = ISC_FALSE;
4224 lookup->new_search = ISC_TRUE;
4225
4226 result = isc_buffer_allocate(mctx, &b, BUFSIZE);
4227 check_result(result, "isc_buffer_allocate");
4228 result = dns_name_totext(rdata_name, ISC_FALSE, b);
4229 check_result(result, "dns_name_totext");
4230 isc_buffer_usedregion(b, &r);
4231 r.base[r.length] = '\0';
4232 strlcpy(lookup->textname, (char*)r.base, sizeof(lookup->textname));
4233 isc_buffer_free(&b);
4234
4235 if (type == dns_rdatatype_rrsig)
4236 querytype = covers;
4237 else
4238 querytype = type;
4239
4240 if (querytype == 0 || querytype == 255) {
4241 printf("Error in the queried type: %d\n", querytype);
4242 return (NULL);
4243 }
4244
4245 lookup->rdtype = querytype;
4246 lookup->rdtypeset = ISC_TRUE;
4247 lookup->qrdtype = querytype;
4248 *lookedup = ISC_TRUE;
4249
4250 ISC_LIST_APPEND(lookup_list, lookup, link);
4251 printf("\n\nLaunch a query to find a RRset of type ");
4252 print_type(type);
4253 printf(" for zone: %s\n", lookup->textname);
4254 return (NULL);
4255 }
4256
4257 isc_result_t
insert_trustedkey(void * arg,dns_name_t * name,dns_rdataset_t * rdataset)4258 insert_trustedkey(void *arg, dns_name_t *name, dns_rdataset_t *rdataset)
4259 {
4260 isc_result_t result;
4261 dst_key_t *dstkey;
4262
4263 UNUSED(arg);
4264
4265 if (rdataset == NULL || rdataset->type != dns_rdatatype_dnskey)
4266 return (ISC_R_SUCCESS);
4267
4268 for (result = dns_rdataset_first(rdataset);
4269 result == ISC_R_SUCCESS;
4270 result = dns_rdataset_next(rdataset)) {
4271 dns_rdata_t rdata = DNS_RDATA_INIT;
4272 isc_buffer_t b;
4273
4274 dns_rdataset_current(rdataset, &rdata);
4275 isc_buffer_init(&b, rdata.data, rdata.length);
4276 isc_buffer_add(&b, rdata.length);
4277 if (tk_list.nb_tk >= MAX_TRUSTED_KEY)
4278 return (ISC_R_SUCCESS);
4279 dstkey = NULL;
4280 result = dst_key_fromdns(name, rdata.rdclass, &b, mctx, &dstkey);
4281 if (result != ISC_R_SUCCESS)
4282 continue;
4283 tk_list.key[tk_list.nb_tk++] = dstkey;
4284 }
4285 return (ISC_R_SUCCESS);
4286 }
4287
4288 void
clean_trustedkey()4289 clean_trustedkey()
4290 {
4291 int i = 0;
4292
4293 for (i= 0; i < MAX_TRUSTED_KEY; i++) {
4294 if (tk_list.key[i] != NULL) {
4295 dst_key_free(&tk_list.key[i]);
4296 tk_list.key[i] = NULL;
4297 } else
4298 break;
4299 }
4300 tk_list.nb_tk = 0;
4301 return;
4302 }
4303
4304 char alphnum[] =
4305 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
4306
4307 isc_result_t
removetmpkey(const char * file)4308 removetmpkey(const char *file)
4309 {
4310 char *tempnamekey = NULL;
4311 int tempnamekeylen;
4312 isc_result_t result;
4313
4314 tempnamekeylen = strlen(file)+10;
4315
4316 tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
4317 if (tempnamekey == NULL)
4318 return (ISC_R_NOMEMORY);
4319
4320 memset(tempnamekey, 0, tempnamekeylen);
4321
4322 strcat(tempnamekey, file);
4323 strcat(tempnamekey,".key");
4324 isc_file_remove(tempnamekey);
4325
4326 result = isc_file_remove(tempnamekey);
4327 isc_mem_free(mctx, tempnamekey);
4328 return (result);
4329 }
4330
4331 isc_result_t
get_trusted_key(void)4332 get_trusted_key(void) {
4333 isc_result_t result;
4334 const char *filename = NULL;
4335 dns_rdatacallbacks_t callbacks;
4336
4337 result = isc_file_exists(trustedkey);
4338 if (result != ISC_TRUE) {
4339 result = isc_file_exists("/etc/trusted-key.key");
4340 if (result != ISC_TRUE) {
4341 result = isc_file_exists("./trusted-key.key");
4342 if (result != ISC_TRUE)
4343 return (ISC_R_FAILURE);
4344 else
4345 filename = "./trusted-key.key";
4346 } else
4347 filename = "/etc/trusted-key.key";
4348 } else
4349 filename = trustedkey;
4350
4351 if (filename == NULL) {
4352 printf("No trusted key\n");
4353 return (ISC_R_FAILURE);
4354 }
4355
4356 dns_rdatacallbacks_init_stdio(&callbacks);
4357 callbacks.add = insert_trustedkey;
4358 return (dns_master_loadfile(filename, dns_rootname, dns_rootname,
4359 current_lookup->rdclass, DNS_MASTER_NOTTL,
4360 &callbacks, mctx));
4361 }
4362
4363
4364 static void
nameFromString(const char * str,dns_name_t * p_ret)4365 nameFromString(const char *str, dns_name_t *p_ret) {
4366 size_t len = strlen(str);
4367 isc_result_t result;
4368 isc_buffer_t buffer;
4369 dns_fixedname_t fixedname;
4370
4371 REQUIRE(p_ret != NULL);
4372 REQUIRE(str != NULL);
4373
4374 isc_buffer_constinit(&buffer, str, len);
4375 isc_buffer_add(&buffer, len);
4376
4377 dns_fixedname_init(&fixedname);
4378 result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer,
4379 dns_rootname, DNS_NAME_DOWNCASE, NULL);
4380 check_result(result, "nameFromString");
4381
4382 if (dns_name_dynamic(p_ret))
4383 free_name(p_ret);
4384
4385 result = dns_name_dup(dns_fixedname_name(&fixedname), mctx, p_ret);
4386 check_result(result, "nameFromString");
4387 }
4388
4389
4390 #if DIG_SIGCHASE_TD
4391 isc_result_t
prepare_lookup(dns_name_t * name)4392 prepare_lookup(dns_name_t *name)
4393 {
4394 isc_result_t result;
4395 dig_lookup_t *lookup = NULL;
4396 dig_server_t *s;
4397 void *ptr;
4398
4399 lookup = clone_lookup(current_lookup, ISC_TRUE);
4400 lookup->trace_root = ISC_FALSE;
4401 lookup->new_search = ISC_TRUE;
4402 lookup->trace_root_sigchase = ISC_FALSE;
4403
4404 strlcpy(lookup->textname, lookup->textnamesigchase, MXNAME);
4405
4406 lookup->rdtype = lookup->rdtype_sigchase;
4407 lookup->rdtypeset = ISC_TRUE;
4408 lookup->qrdtype = lookup->qrdtype_sigchase;
4409
4410 s = ISC_LIST_HEAD(lookup->my_server_list);
4411 while (s != NULL) {
4412 debug("freeing server %p belonging to %p",
4413 s, lookup);
4414 ptr = s;
4415 s = ISC_LIST_NEXT(s, link);
4416 ISC_LIST_DEQUEUE(lookup->my_server_list,
4417 (dig_server_t *)ptr, link);
4418 isc_mem_free(mctx, ptr);
4419 }
4420
4421
4422 for (result = dns_rdataset_first(chase_nsrdataset);
4423 result == ISC_R_SUCCESS;
4424 result = dns_rdataset_next(chase_nsrdataset)) {
4425 char namestr[DNS_NAME_FORMATSIZE];
4426 dns_rdata_ns_t ns;
4427 dns_rdata_t rdata = DNS_RDATA_INIT;
4428 dig_server_t * srv = NULL;
4429 #define __FOLLOW_GLUE__
4430 #ifdef __FOLLOW_GLUE__
4431 isc_buffer_t *b = NULL;
4432 isc_region_t r;
4433 dns_rdataset_t *rdataset = NULL;
4434 isc_boolean_t true = ISC_TRUE;
4435 #endif
4436
4437 memset(namestr, 0, DNS_NAME_FORMATSIZE);
4438
4439 dns_rdataset_current(chase_nsrdataset, &rdata);
4440
4441 result = dns_rdata_tostruct(&rdata, &ns, NULL);
4442 check_result(result, "dns_rdata_tostruct");
4443
4444 #ifdef __FOLLOW_GLUE__
4445
4446 result = advanced_rrsearch(&rdataset, &ns.name,
4447 dns_rdatatype_aaaa,
4448 dns_rdatatype_any, &true);
4449 if (result == ISC_R_SUCCESS) {
4450 for (result = dns_rdataset_first(rdataset);
4451 result == ISC_R_SUCCESS;
4452 result = dns_rdataset_next(rdataset)) {
4453 dns_rdata_t aaaa = DNS_RDATA_INIT;
4454 dns_rdataset_current(rdataset, &aaaa);
4455
4456 result = isc_buffer_allocate(mctx, &b, 80);
4457 check_result(result, "isc_buffer_allocate");
4458
4459 dns_rdata_totext(&aaaa, &ns.name, b);
4460 isc_buffer_usedregion(b, &r);
4461 r.base[r.length] = '\0';
4462 strlcpy(namestr, (char*)r.base,
4463 DNS_NAME_FORMATSIZE);
4464 isc_buffer_free(&b);
4465 dns_rdata_reset(&aaaa);
4466
4467
4468 srv = make_server(namestr, namestr);
4469
4470 ISC_LIST_APPEND(lookup->my_server_list,
4471 srv, link);
4472 }
4473 }
4474
4475 rdataset = NULL;
4476 result = advanced_rrsearch(&rdataset, &ns.name, dns_rdatatype_a,
4477 dns_rdatatype_any, &true);
4478 if (result == ISC_R_SUCCESS) {
4479 for (result = dns_rdataset_first(rdataset);
4480 result == ISC_R_SUCCESS;
4481 result = dns_rdataset_next(rdataset)) {
4482 dns_rdata_t a = DNS_RDATA_INIT;
4483 dns_rdataset_current(rdataset, &a);
4484
4485 result = isc_buffer_allocate(mctx, &b, 80);
4486 check_result(result, "isc_buffer_allocate");
4487
4488 dns_rdata_totext(&a, &ns.name, b);
4489 isc_buffer_usedregion(b, &r);
4490 r.base[r.length] = '\0';
4491 strlcpy(namestr, (char*)r.base,
4492 DNS_NAME_FORMATSIZE);
4493 isc_buffer_free(&b);
4494 dns_rdata_reset(&a);
4495 printf("ns name: %s\n", namestr);
4496
4497
4498 srv = make_server(namestr, namestr);
4499
4500 ISC_LIST_APPEND(lookup->my_server_list,
4501 srv, link);
4502 }
4503 }
4504 #else
4505
4506 dns_name_format(&ns.name, namestr, sizeof(namestr));
4507 printf("ns name: ");
4508 dns_name_print(&ns.name, stdout);
4509 printf("\n");
4510 srv = make_server(namestr, namestr);
4511
4512 ISC_LIST_APPEND(lookup->my_server_list, srv, link);
4513
4514 #endif
4515 dns_rdata_freestruct(&ns);
4516 dns_rdata_reset(&rdata);
4517
4518 }
4519
4520 ISC_LIST_APPEND(lookup_list, lookup, link);
4521 printf("\nLaunch a query to find a RRset of type ");
4522 print_type(lookup->rdtype);
4523 printf(" for zone: %s", lookup->textname);
4524 printf(" with nameservers:");
4525 printf("\n");
4526 print_rdataset(name, chase_nsrdataset);
4527 return (ISC_R_SUCCESS);
4528 }
4529
4530
4531 isc_result_t
child_of_zone(dns_name_t * name,dns_name_t * zone_name,dns_name_t * child_name)4532 child_of_zone(dns_name_t * name, dns_name_t * zone_name,
4533 dns_name_t * child_name)
4534 {
4535 dns_namereln_t name_reln;
4536 int orderp;
4537 unsigned int nlabelsp;
4538
4539 name_reln = dns_name_fullcompare(name, zone_name, &orderp, &nlabelsp);
4540 if (name_reln != dns_namereln_subdomain ||
4541 dns_name_countlabels(name) <= dns_name_countlabels(zone_name) + 1) {
4542 printf("\n;; ERROR : ");
4543 dns_name_print(name, stdout);
4544 printf(" is not a subdomain of: ");
4545 dns_name_print(zone_name, stdout);
4546 printf(" FAILED\n\n");
4547 return (ISC_R_FAILURE);
4548 }
4549
4550 dns_name_getlabelsequence(name,
4551 dns_name_countlabels(name) -
4552 dns_name_countlabels(zone_name) -1,
4553 dns_name_countlabels(zone_name) +1,
4554 child_name);
4555 return (ISC_R_SUCCESS);
4556 }
4557
4558 isc_result_t
grandfather_pb_test(dns_name_t * zone_name,dns_rdataset_t * sigrdataset)4559 grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t *sigrdataset) {
4560 dns_rdata_sig_t siginfo;
4561 dns_rdataset_t mysigrdataset;
4562 isc_result_t result;
4563
4564 dns_rdataset_init(&mysigrdataset);
4565 dns_rdataset_clone(sigrdataset, &mysigrdataset);
4566
4567 result = dns_rdataset_first(&mysigrdataset);
4568 check_result(result, "empty RRSIG dataset");
4569
4570 do {
4571 dns_rdata_t sigrdata = DNS_RDATA_INIT;
4572
4573 dns_rdataset_current(&mysigrdataset, &sigrdata);
4574
4575 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4576 check_result(result, "sigrdata tostruct siginfo");
4577
4578 if (dns_name_compare(&siginfo.signer, zone_name) == 0) {
4579 result = ISC_R_SUCCESS;
4580 goto cleanup;
4581 }
4582 } while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS);
4583
4584 result = ISC_R_FAILURE;
4585 cleanup:
4586 dns_rdataset_disassociate(&mysigrdataset);
4587
4588 return (result);
4589 }
4590
4591
4592 isc_result_t
initialization(dns_name_t * name)4593 initialization(dns_name_t *name)
4594 {
4595 isc_result_t result;
4596 isc_boolean_t true = ISC_TRUE;
4597
4598 chase_nsrdataset = NULL;
4599 result = advanced_rrsearch(&chase_nsrdataset, name, dns_rdatatype_ns,
4600 dns_rdatatype_any, &true);
4601 if (result != ISC_R_SUCCESS) {
4602 printf("\n;; NS RRset is missing to continue validation:"
4603 " FAILED\n\n");
4604 return (ISC_R_FAILURE);
4605 }
4606 INSIST(chase_nsrdataset != NULL);
4607 prepare_lookup(name);
4608
4609 dup_name(name, &chase_current_name);
4610
4611 return (ISC_R_SUCCESS);
4612 }
4613 #endif
4614
4615 void
print_rdataset(dns_name_t * name,dns_rdataset_t * rdataset)4616 print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset)
4617 {
4618 isc_buffer_t *b = NULL;
4619 isc_result_t result;
4620 isc_region_t r;
4621
4622 result = isc_buffer_allocate(mctx, &b, 9000);
4623 check_result(result, "isc_buffer_allocate");
4624
4625 printrdataset(name, rdataset, b);
4626
4627 isc_buffer_usedregion(b, &r);
4628 r.base[r.length] = '\0';
4629
4630
4631 printf("%s\n", r.base);
4632
4633 isc_buffer_free(&b);
4634 }
4635
4636
4637 void
dup_name(dns_name_t * source,dns_name_t * target)4638 dup_name(dns_name_t *source, dns_name_t *target) {
4639 isc_result_t result;
4640
4641 if (dns_name_dynamic(target))
4642 free_name(target);
4643 result = dns_name_dup(source, mctx, target);
4644 check_result(result, "dns_name_dup");
4645 }
4646
4647 void
free_name(dns_name_t * name)4648 free_name(dns_name_t *name) {
4649 dns_name_free(name, mctx);
4650 dns_name_init(name, NULL);
4651 }
4652
4653 /*
4654 *
4655 * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter
4656 * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key
4657 * and the RRset is valid
4658 * return ISC_R_NOTFOUND if not contains trusted key
4659 or if the RRset isn't valid
4660 * return ISC_R_FAILURE if problem
4661 *
4662 */
4663 isc_result_t
contains_trusted_key(dns_name_t * name,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)4664 contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset,
4665 dns_rdataset_t *sigrdataset)
4666 {
4667 dns_rdataset_t myrdataset;
4668 dst_key_t *dnsseckey = NULL;
4669 int i;
4670 isc_result_t result;
4671
4672 if (name == NULL || rdataset == NULL)
4673 return (ISC_R_FAILURE);
4674
4675 dns_rdataset_init(&myrdataset);
4676 dns_rdataset_clone(rdataset, &myrdataset);
4677
4678 result = dns_rdataset_first(&myrdataset);
4679 check_result(result, "empty rdataset");
4680
4681 do {
4682 dns_rdata_t rdata = DNS_RDATA_INIT;
4683
4684 dns_rdataset_current(&myrdataset, &rdata);
4685 INSIST(rdata.type == dns_rdatatype_dnskey);
4686
4687 result = dns_dnssec_keyfromrdata(name, &rdata,
4688 mctx, &dnsseckey);
4689 check_result(result, "dns_dnssec_keyfromrdata");
4690
4691 for (i = 0; i < tk_list.nb_tk; i++) {
4692 if (dst_key_compare(tk_list.key[i], dnsseckey)
4693 == ISC_TRUE) {
4694 dns_rdata_reset(&rdata);
4695
4696 printf(";; Ok, find a Trusted Key in the "
4697 "DNSKEY RRset: %d\n",
4698 dst_key_id(dnsseckey));
4699 result = sigchase_verify_sig_key(name, rdataset,
4700 dnsseckey,
4701 sigrdataset);
4702 if (result == ISC_R_SUCCESS)
4703 goto cleanup;
4704 }
4705 }
4706 dst_key_free(&dnsseckey);
4707 } while (dns_rdataset_next(&myrdataset) == ISC_R_SUCCESS);
4708
4709 result = ISC_R_NOTFOUND;
4710
4711 cleanup:
4712 if (dnsseckey != NULL)
4713 dst_key_free(&dnsseckey);
4714 dns_rdataset_disassociate(&myrdataset);
4715
4716 return (result);
4717 }
4718
4719 isc_result_t
sigchase_verify_sig(dns_name_t * name,dns_rdataset_t * rdataset,dns_rdataset_t * keyrdataset,dns_rdataset_t * sigrdataset)4720 sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset,
4721 dns_rdataset_t *keyrdataset,
4722 dns_rdataset_t *sigrdataset)
4723 {
4724 dns_rdataset_t mykeyrdataset;
4725 dst_key_t *dnsseckey = NULL;
4726 isc_result_t result;
4727
4728 dns_rdataset_init(&mykeyrdataset);
4729 dns_rdataset_clone(keyrdataset, &mykeyrdataset);
4730
4731 result = dns_rdataset_first(&mykeyrdataset);
4732 check_result(result, "empty DNSKEY dataset");
4733
4734 do {
4735 dns_rdata_t keyrdata = DNS_RDATA_INIT;
4736
4737 dns_rdataset_current(&mykeyrdataset, &keyrdata);
4738 INSIST(keyrdata.type == dns_rdatatype_dnskey);
4739
4740 result = dns_dnssec_keyfromrdata(name, &keyrdata,
4741 mctx, &dnsseckey);
4742 check_result(result, "dns_dnssec_keyfromrdata");
4743
4744 result = sigchase_verify_sig_key(name, rdataset, dnsseckey,
4745 sigrdataset);
4746 if (result == ISC_R_SUCCESS)
4747 goto cleanup;
4748 dst_key_free(&dnsseckey);
4749 } while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS);
4750
4751 result = ISC_R_NOTFOUND;
4752
4753 cleanup:
4754 if (dnsseckey != NULL)
4755 dst_key_free(&dnsseckey);
4756 dns_rdataset_disassociate(&mykeyrdataset);
4757
4758 return (result);
4759 }
4760
4761 isc_result_t
sigchase_verify_sig_key(dns_name_t * name,dns_rdataset_t * rdataset,dst_key_t * dnsseckey,dns_rdataset_t * sigrdataset)4762 sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset,
4763 dst_key_t *dnsseckey, dns_rdataset_t *sigrdataset)
4764 {
4765 dns_rdata_sig_t siginfo;
4766 dns_rdataset_t myrdataset;
4767 dns_rdataset_t mysigrdataset;
4768 isc_result_t result;
4769
4770 dns_rdataset_init(&myrdataset);
4771 dns_rdataset_clone(rdataset, &myrdataset);
4772 dns_rdataset_init(&mysigrdataset);
4773 dns_rdataset_clone(sigrdataset, &mysigrdataset);
4774
4775 result = dns_rdataset_first(&mysigrdataset);
4776 check_result(result, "empty RRSIG dataset");
4777
4778 do {
4779 dns_rdata_t sigrdata = DNS_RDATA_INIT;
4780
4781 dns_rdataset_current(&mysigrdataset, &sigrdata);
4782
4783 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
4784 check_result(result, "sigrdata tostruct siginfo");
4785
4786 /*
4787 * Test if the id of the DNSKEY is
4788 * the id of the DNSKEY signer's
4789 */
4790 if (siginfo.keyid == dst_key_id(dnsseckey)) {
4791
4792 result = dns_rdataset_first(&myrdataset);
4793 check_result(result, "empty DS dataset");
4794
4795 result = dns_dnssec_verify(name, &myrdataset, dnsseckey,
4796 ISC_FALSE, mctx, &sigrdata);
4797
4798 printf(";; VERIFYING ");
4799 print_type(rdataset->type);
4800 printf(" RRset for ");
4801 dns_name_print(name, stdout);
4802 printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey),
4803 isc_result_totext(result));
4804
4805 if (result == ISC_R_SUCCESS)
4806 goto cleanup;
4807 }
4808 } while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS);
4809
4810 result = ISC_R_NOTFOUND;
4811
4812 cleanup:
4813 dns_rdataset_disassociate(&myrdataset);
4814 dns_rdataset_disassociate(&mysigrdataset);
4815
4816 return (result);
4817 }
4818
4819
4820 isc_result_t
sigchase_verify_ds(dns_name_t * name,dns_rdataset_t * keyrdataset,dns_rdataset_t * dsrdataset)4821 sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset,
4822 dns_rdataset_t *dsrdataset)
4823 {
4824 dns_rdata_ds_t dsinfo;
4825 dns_rdataset_t mydsrdataset;
4826 dns_rdataset_t mykeyrdataset;
4827 dst_key_t *dnsseckey = NULL;
4828 isc_result_t result;
4829 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
4830
4831 dns_rdataset_init(&mydsrdataset);
4832 dns_rdataset_clone(dsrdataset, &mydsrdataset);
4833 dns_rdataset_init(&mykeyrdataset);
4834 dns_rdataset_clone(keyrdataset, &mykeyrdataset);
4835
4836 result = dns_rdataset_first(&mydsrdataset);
4837 check_result(result, "empty DSset dataset");
4838 do {
4839 dns_rdata_t dsrdata = DNS_RDATA_INIT;
4840
4841 dns_rdataset_current(&mydsrdataset, &dsrdata);
4842
4843 result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL);
4844 check_result(result, "dns_rdata_tostruct for DS");
4845
4846 result = dns_rdataset_first(&mykeyrdataset);
4847 check_result(result, "empty KEY dataset");
4848
4849 do {
4850 dns_rdata_t keyrdata = DNS_RDATA_INIT;
4851
4852 dns_rdataset_current(&mykeyrdataset, &keyrdata);
4853 INSIST(keyrdata.type == dns_rdatatype_dnskey);
4854
4855 result = dns_dnssec_keyfromrdata(name, &keyrdata,
4856 mctx, &dnsseckey);
4857 check_result(result, "dns_dnssec_keyfromrdata");
4858
4859 /*
4860 * Test if the id of the DNSKEY is the
4861 * id of DNSKEY referenced by the DS
4862 */
4863 if (dsinfo.key_tag == dst_key_id(dnsseckey)) {
4864 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
4865
4866 result = dns_ds_buildrdata(name, &keyrdata,
4867 dsinfo.digest_type,
4868 dsbuf, &newdsrdata);
4869 dns_rdata_freestruct(&dsinfo);
4870
4871 if (result != ISC_R_SUCCESS) {
4872 printf("Oops: impossible to build"
4873 " new DS rdata\n");
4874 goto cleanup;
4875 }
4876
4877
4878 if (dns_rdata_compare(&dsrdata,
4879 &newdsrdata) == 0) {
4880 printf(";; OK a DS valids a DNSKEY"
4881 " in the RRset\n");
4882 printf(";; Now verify that this"
4883 " DNSKEY validates the "
4884 "DNSKEY RRset\n");
4885
4886 result = sigchase_verify_sig_key(name,
4887 keyrdataset,
4888 dnsseckey,
4889 chase_sigkeyrdataset);
4890 if (result == ISC_R_SUCCESS)
4891 goto cleanup;
4892 } else {
4893 printf(";; This DS is NOT the DS for"
4894 " the chasing KEY: FAILED\n");
4895 }
4896 }
4897 dst_key_free(&dnsseckey);
4898 } while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS);
4899 } while (dns_rdataset_next(&mydsrdataset) == ISC_R_SUCCESS);
4900
4901 result = ISC_R_NOTFOUND;
4902
4903 cleanup:
4904 if (dnsseckey != NULL)
4905 dst_key_free(&dnsseckey);
4906 dns_rdataset_disassociate(&mydsrdataset);
4907 dns_rdataset_disassociate(&mykeyrdataset);
4908
4909 return (result);
4910 }
4911
4912 /*
4913 *
4914 * take a pointer on a rdataset in parameter and try to resolv it.
4915 * the searched rrset is a rrset on 'name' with type 'type'
4916 * (and if the type is a rrsig the signature cover 'covers').
4917 * the lookedup is to known if you have already done the query on the net.
4918 * ISC_R_SUCCESS: if we found the rrset
4919 * ISC_R_NOTFOUND: we do not found the rrset in cache
4920 * and we do a query on the net
4921 * ISC_R_FAILURE: rrset not found
4922 */
4923 isc_result_t
advanced_rrsearch(dns_rdataset_t ** rdataset,dns_name_t * name,dns_rdatatype_t type,dns_rdatatype_t covers,isc_boolean_t * lookedup)4924 advanced_rrsearch(dns_rdataset_t **rdataset, dns_name_t *name,
4925 dns_rdatatype_t type, dns_rdatatype_t covers,
4926 isc_boolean_t *lookedup)
4927 {
4928 isc_boolean_t tmplookedup;
4929
4930 INSIST(rdataset != NULL);
4931
4932 if (*rdataset != NULL)
4933 return (ISC_R_SUCCESS);
4934
4935 tmplookedup = *lookedup;
4936 if ((*rdataset = sigchase_scanname(type, covers,
4937 lookedup, name)) == NULL) {
4938 if (tmplookedup)
4939 return (ISC_R_FAILURE);
4940 return (ISC_R_NOTFOUND);
4941 }
4942 *lookedup = ISC_FALSE;
4943 return (ISC_R_SUCCESS);
4944 }
4945
4946
4947
4948 #if DIG_SIGCHASE_TD
4949 void
sigchase_td(dns_message_t * msg)4950 sigchase_td(dns_message_t *msg)
4951 {
4952 isc_result_t result;
4953 dns_name_t *name = NULL;
4954 isc_boolean_t have_answer = ISC_FALSE;
4955 isc_boolean_t true = ISC_TRUE;
4956
4957 if (msg->rcode != dns_rcode_noerror &&
4958 msg->rcode != dns_rcode_nxdomain) {
4959 char buf[20];
4960 isc_buffer_t b;
4961
4962 isc_buffer_init(&b, buf, sizeof(buf));
4963 result = dns_rcode_totext(msg->rcode, &b);
4964 check_result(result, "dns_rcode_totext failed");
4965 printf("error response code %.*s\n",
4966 (int)isc_buffer_usedlength(&b), buf);
4967 error_message = msg;
4968 return;
4969 }
4970
4971 if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
4972 == ISC_R_SUCCESS) {
4973 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
4974 if (current_lookup->trace_root_sigchase) {
4975 initialization(name);
4976 return;
4977 }
4978 have_answer = true;
4979 } else {
4980 if (!current_lookup->trace_root_sigchase) {
4981 result = dns_message_firstname(msg,
4982 DNS_SECTION_AUTHORITY);
4983 if (result != ISC_R_SUCCESS) {
4984 printf("no answer or authority section\n");
4985 error_message = msg;
4986 return;
4987 }
4988 dns_message_currentname(msg, DNS_SECTION_AUTHORITY,
4989 &name);
4990 chase_nsrdataset
4991 = chase_scanname_section(msg, name,
4992 dns_rdatatype_ns,
4993 dns_rdatatype_any,
4994 DNS_SECTION_AUTHORITY);
4995 dup_name(name, &chase_authority_name);
4996 if (chase_nsrdataset != NULL) {
4997 have_delegation_ns = ISC_TRUE;
4998 printf("no response but there is a delegation"
4999 " in authority section: ");
5000 dns_name_print(name, stdout);
5001 printf("\n");
5002 } else {
5003 printf("no response and no delegation in "
5004 "authority section but a reference"
5005 " to: ");
5006 dns_name_print(name, stdout);
5007 printf("\n");
5008 error_message = msg;
5009 }
5010 } else {
5011 printf(";; NO ANSWERS: %s\n",
5012 isc_result_totext(result));
5013 free_name(&chase_name);
5014 clean_trustedkey();
5015 return;
5016 }
5017 }
5018
5019
5020 if (have_answer) {
5021 chase_rdataset
5022 = chase_scanname_section(msg, &chase_name,
5023 current_lookup
5024 ->rdtype_sigchase,
5025 dns_rdatatype_any,
5026 DNS_SECTION_ANSWER);
5027 if (chase_rdataset != NULL)
5028 have_response = ISC_TRUE;
5029 }
5030
5031 result = advanced_rrsearch(&chase_keyrdataset,
5032 &chase_current_name,
5033 dns_rdatatype_dnskey,
5034 dns_rdatatype_any,
5035 &chase_keylookedup);
5036 if (result == ISC_R_FAILURE) {
5037 printf("\n;; DNSKEY is missing to continue validation:"
5038 " FAILED\n\n");
5039 goto cleanandgo;
5040 }
5041 if (result == ISC_R_NOTFOUND)
5042 return;
5043 INSIST(chase_keyrdataset != NULL);
5044 printf("\n;; DNSKEYset:\n");
5045 print_rdataset(&chase_current_name , chase_keyrdataset);
5046
5047
5048 result = advanced_rrsearch(&chase_sigkeyrdataset,
5049 &chase_current_name,
5050 dns_rdatatype_rrsig,
5051 dns_rdatatype_dnskey,
5052 &chase_sigkeylookedup);
5053 if (result == ISC_R_FAILURE) {
5054 printf("\n;; RRSIG of DNSKEY is missing to continue validation:"
5055 " FAILED\n\n");
5056 goto cleanandgo;
5057 }
5058 if (result == ISC_R_NOTFOUND)
5059 return;
5060 INSIST(chase_sigkeyrdataset != NULL);
5061 printf("\n;; RRSIG of the DNSKEYset:\n");
5062 print_rdataset(&chase_current_name , chase_sigkeyrdataset);
5063
5064
5065 if (!chase_dslookedup && !chase_nslookedup) {
5066 if (!delegation_follow) {
5067 result = contains_trusted_key(&chase_current_name,
5068 chase_keyrdataset,
5069 chase_sigkeyrdataset);
5070 } else {
5071 INSIST(chase_dsrdataset != NULL);
5072 INSIST(chase_sigdsrdataset != NULL);
5073 result = sigchase_verify_ds(&chase_current_name,
5074 chase_keyrdataset,
5075 chase_dsrdataset);
5076 }
5077
5078 if (result != ISC_R_SUCCESS) {
5079 printf("\n;; chain of trust can't be validated:"
5080 " FAILED\n\n");
5081 goto cleanandgo;
5082 } else {
5083 chase_dsrdataset = NULL;
5084 chase_sigdsrdataset = NULL;
5085 }
5086 }
5087
5088 if (have_response || (!have_delegation_ns && !have_response)) {
5089 /* test if it's a grand father case */
5090
5091 if (have_response) {
5092 result = advanced_rrsearch(&chase_sigrdataset,
5093 &chase_name,
5094 dns_rdatatype_rrsig,
5095 current_lookup
5096 ->rdtype_sigchase,
5097 &true);
5098 if (result == ISC_R_FAILURE) {
5099 printf("\n;; RRset is missing to continue"
5100 " validation SHOULD NOT APPEND:"
5101 " FAILED\n\n");
5102 goto cleanandgo;
5103 }
5104
5105 } else {
5106 result = advanced_rrsearch(&chase_sigrdataset,
5107 &chase_authority_name,
5108 dns_rdatatype_rrsig,
5109 dns_rdatatype_any,
5110 &true);
5111 if (result == ISC_R_FAILURE) {
5112 printf("\n;; RRSIG is missing to continue"
5113 " validation SHOULD NOT APPEND:"
5114 " FAILED\n\n");
5115 goto cleanandgo;
5116 }
5117 }
5118 result = grandfather_pb_test(&chase_current_name,
5119 chase_sigrdataset);
5120 if (result != ISC_R_SUCCESS) {
5121 dns_name_t tmp_name;
5122
5123 printf("\n;; We are in a Grand Father Problem:"
5124 " See 2.2.1 in RFC 3658\n");
5125 chase_rdataset = NULL;
5126 chase_sigrdataset = NULL;
5127 have_response = ISC_FALSE;
5128 have_delegation_ns = ISC_FALSE;
5129
5130 dns_name_init(&tmp_name, NULL);
5131 result = child_of_zone(&chase_name, &chase_current_name,
5132 &tmp_name);
5133 if (dns_name_dynamic(&chase_authority_name))
5134 free_name(&chase_authority_name);
5135 dup_name(&tmp_name, &chase_authority_name);
5136 printf(";; and we try to continue chain of trust"
5137 " validation of the zone: ");
5138 dns_name_print(&chase_authority_name, stdout);
5139 printf("\n");
5140 have_delegation_ns = ISC_TRUE;
5141 } else {
5142 if (have_response)
5143 goto finalstep;
5144 else
5145 chase_sigrdataset = NULL;
5146 }
5147 }
5148
5149 if (have_delegation_ns) {
5150 chase_nsrdataset = NULL;
5151 result = advanced_rrsearch(&chase_nsrdataset,
5152 &chase_authority_name,
5153 dns_rdatatype_ns,
5154 dns_rdatatype_any,
5155 &chase_nslookedup);
5156 if (result == ISC_R_FAILURE) {
5157 printf("\n;;NSset is missing to continue validation:"
5158 " FAILED\n\n");
5159 goto cleanandgo;
5160 }
5161 if (result == ISC_R_NOTFOUND) {
5162 return;
5163 }
5164 INSIST(chase_nsrdataset != NULL);
5165
5166 result = advanced_rrsearch(&chase_dsrdataset,
5167 &chase_authority_name,
5168 dns_rdatatype_ds,
5169 dns_rdatatype_any,
5170 &chase_dslookedup);
5171 if (result == ISC_R_FAILURE) {
5172 printf("\n;; DSset is missing to continue validation:"
5173 " FAILED\n\n");
5174 goto cleanandgo;
5175 }
5176 if (result == ISC_R_NOTFOUND)
5177 return;
5178 INSIST(chase_dsrdataset != NULL);
5179 printf("\n;; DSset:\n");
5180 print_rdataset(&chase_authority_name , chase_dsrdataset);
5181
5182 result = advanced_rrsearch(&chase_sigdsrdataset,
5183 &chase_authority_name,
5184 dns_rdatatype_rrsig,
5185 dns_rdatatype_ds,
5186 &true);
5187 if (result != ISC_R_SUCCESS) {
5188 printf("\n;; DSset is missing to continue validation:"
5189 " FAILED\n\n");
5190 goto cleanandgo;
5191 }
5192 printf("\n;; RRSIGset of DSset\n");
5193 print_rdataset(&chase_authority_name, chase_sigdsrdataset);
5194 INSIST(chase_sigdsrdataset != NULL);
5195
5196 result = sigchase_verify_sig(&chase_authority_name,
5197 chase_dsrdataset,
5198 chase_keyrdataset,
5199 chase_sigdsrdataset);
5200 if (result != ISC_R_SUCCESS) {
5201 printf("\n;; Impossible to verify the DSset:"
5202 " FAILED\n\n");
5203 goto cleanandgo;
5204 }
5205 chase_keyrdataset = NULL;
5206 chase_sigkeyrdataset = NULL;
5207
5208
5209 prepare_lookup(&chase_authority_name);
5210
5211 have_response = ISC_FALSE;
5212 have_delegation_ns = ISC_FALSE;
5213 delegation_follow = ISC_TRUE;
5214 error_message = NULL;
5215 dup_name(&chase_authority_name, &chase_current_name);
5216 free_name(&chase_authority_name);
5217 return;
5218 }
5219
5220
5221 if (error_message != NULL) {
5222 dns_rdataset_t *rdataset;
5223 dns_rdataset_t *sigrdataset;
5224 dns_name_t rdata_name;
5225 isc_result_t ret = ISC_R_FAILURE;
5226
5227 dns_name_init(&rdata_name, NULL);
5228 result = prove_nx(error_message, &chase_name,
5229 current_lookup->rdclass_sigchase,
5230 current_lookup->rdtype_sigchase, &rdata_name,
5231 &rdataset, &sigrdataset);
5232 if (rdataset == NULL || sigrdataset == NULL ||
5233 dns_name_countlabels(&rdata_name) == 0) {
5234 printf("\n;; Impossible to verify the non-existence,"
5235 " the NSEC RRset can't be validated:"
5236 " FAILED\n\n");
5237 goto cleanandgo;
5238 }
5239 ret = sigchase_verify_sig(&rdata_name, rdataset,
5240 chase_keyrdataset,
5241 sigrdataset);
5242 if (ret != ISC_R_SUCCESS) {
5243 free_name(&rdata_name);
5244 printf("\n;; Impossible to verify the NSEC RR to prove"
5245 " the non-existence : FAILED\n\n");
5246 goto cleanandgo;
5247 }
5248 free_name(&rdata_name);
5249 if (result != ISC_R_SUCCESS) {
5250 printf("\n;; Impossible to verify the non-existence:"
5251 " FAILED\n\n");
5252 goto cleanandgo;
5253 } else {
5254 printf("\n;; OK the query doesn't have response but"
5255 " we have validate this fact : SUCCESS\n\n");
5256 goto cleanandgo;
5257 }
5258 }
5259
5260 cleanandgo:
5261 printf(";; cleanandgo \n");
5262 if (dns_name_dynamic(&chase_current_name))
5263 free_name(&chase_current_name);
5264 if (dns_name_dynamic(&chase_authority_name))
5265 free_name(&chase_authority_name);
5266 clean_trustedkey();
5267 return;
5268
5269 finalstep :
5270 result = advanced_rrsearch(&chase_rdataset, &chase_name,
5271 current_lookup->rdtype_sigchase,
5272 dns_rdatatype_any ,
5273 &true);
5274 if (result == ISC_R_FAILURE) {
5275 printf("\n;; RRsig of RRset is missing to continue validation"
5276 " SHOULD NOT APPEND: FAILED\n\n");
5277 goto cleanandgo;
5278 }
5279 result = sigchase_verify_sig(&chase_name, chase_rdataset,
5280 chase_keyrdataset,
5281 chase_sigrdataset);
5282 if (result != ISC_R_SUCCESS) {
5283 printf("\n;; Impossible to verify the RRset : FAILED\n\n");
5284 /*
5285 printf("RRset:\n");
5286 print_rdataset(&chase_name , chase_rdataset);
5287 printf("DNSKEYset:\n");
5288 print_rdataset(&chase_name , chase_keyrdataset);
5289 printf("RRSIG of RRset:\n");
5290 print_rdataset(&chase_name , chase_sigrdataset);
5291 printf("\n");
5292 */
5293 goto cleanandgo;
5294 } else {
5295 printf("\n;; The Answer:\n");
5296 print_rdataset(&chase_name , chase_rdataset);
5297
5298 printf("\n;; FINISH : we have validate the DNSSEC chain"
5299 " of trust: SUCCESS\n\n");
5300 goto cleanandgo;
5301 }
5302 }
5303
5304 #endif
5305
5306
5307 #if DIG_SIGCHASE_BU
5308
5309 isc_result_t
getneededrr(dns_message_t * msg)5310 getneededrr(dns_message_t *msg)
5311 {
5312 isc_result_t result;
5313 dns_name_t *name = NULL;
5314 dns_rdata_t sigrdata = DNS_RDATA_INIT;
5315 dns_rdata_sig_t siginfo;
5316 isc_boolean_t true = ISC_TRUE;
5317
5318 if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
5319 != ISC_R_SUCCESS) {
5320 printf(";; NO ANSWERS: %s\n", isc_result_totext(result));
5321
5322 if (chase_name.ndata == NULL)
5323 return (ISC_R_ADDRNOTAVAIL);
5324 } else {
5325 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
5326 }
5327
5328 /* What do we chase? */
5329 if (chase_rdataset == NULL) {
5330 result = advanced_rrsearch(&chase_rdataset, name,
5331 dns_rdatatype_any,
5332 dns_rdatatype_any, &true);
5333 if (result != ISC_R_SUCCESS) {
5334 printf("\n;; No Answers: Validation FAILED\n\n");
5335 return (ISC_R_NOTFOUND);
5336 }
5337 dup_name(name, &chase_name);
5338 printf(";; RRset to chase:\n");
5339 print_rdataset(&chase_name, chase_rdataset);
5340 }
5341 INSIST(chase_rdataset != NULL);
5342
5343
5344 if (chase_sigrdataset == NULL) {
5345 result = advanced_rrsearch(&chase_sigrdataset, name,
5346 dns_rdatatype_rrsig,
5347 chase_rdataset->type,
5348 &chase_siglookedup);
5349 if (result == ISC_R_FAILURE) {
5350 printf("\n;; RRSIG is missing for continue validation:"
5351 " FAILED\n\n");
5352 if (dns_name_dynamic(&chase_name))
5353 free_name(&chase_name);
5354 return (ISC_R_NOTFOUND);
5355 }
5356 if (result == ISC_R_NOTFOUND) {
5357 return (ISC_R_NOTFOUND);
5358 }
5359 printf("\n;; RRSIG of the RRset to chase:\n");
5360 print_rdataset(&chase_name, chase_sigrdataset);
5361 }
5362 INSIST(chase_sigrdataset != NULL);
5363
5364
5365 /* first find the DNSKEY name */
5366 result = dns_rdataset_first(chase_sigrdataset);
5367 check_result(result, "empty RRSIG dataset");
5368 dns_rdataset_current(chase_sigrdataset, &sigrdata);
5369 result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
5370 check_result(result, "sigrdata tostruct siginfo");
5371 dup_name(&siginfo.signer, &chase_signame);
5372 dns_rdata_freestruct(&siginfo);
5373 dns_rdata_reset(&sigrdata);
5374
5375 /* Do we have a key? */
5376 if (chase_keyrdataset == NULL) {
5377 result = advanced_rrsearch(&chase_keyrdataset,
5378 &chase_signame,
5379 dns_rdatatype_dnskey,
5380 dns_rdatatype_any,
5381 &chase_keylookedup);
5382 if (result == ISC_R_FAILURE) {
5383 printf("\n;; DNSKEY is missing to continue validation:"
5384 " FAILED\n\n");
5385 free_name(&chase_signame);
5386 if (dns_name_dynamic(&chase_name))
5387 free_name(&chase_name);
5388 return (ISC_R_NOTFOUND);
5389 }
5390 if (result == ISC_R_NOTFOUND) {
5391 free_name(&chase_signame);
5392 return (ISC_R_NOTFOUND);
5393 }
5394 printf("\n;; DNSKEYset that signs the RRset to chase:\n");
5395 print_rdataset(&chase_signame, chase_keyrdataset);
5396 }
5397 INSIST(chase_keyrdataset != NULL);
5398
5399 if (chase_sigkeyrdataset == NULL) {
5400 result = advanced_rrsearch(&chase_sigkeyrdataset,
5401 &chase_signame,
5402 dns_rdatatype_rrsig,
5403 dns_rdatatype_dnskey,
5404 &chase_sigkeylookedup);
5405 if (result == ISC_R_FAILURE) {
5406 printf("\n;; RRSIG for DNSKEY is missing to continue"
5407 " validation : FAILED\n\n");
5408 free_name(&chase_signame);
5409 if (dns_name_dynamic(&chase_name))
5410 free_name(&chase_name);
5411 return (ISC_R_NOTFOUND);
5412 }
5413 if (result == ISC_R_NOTFOUND) {
5414 free_name(&chase_signame);
5415 return (ISC_R_NOTFOUND);
5416 }
5417 printf("\n;; RRSIG of the DNSKEYset that signs the "
5418 "RRset to chase:\n");
5419 print_rdataset(&chase_signame, chase_sigkeyrdataset);
5420 }
5421 INSIST(chase_sigkeyrdataset != NULL);
5422
5423
5424 if (chase_dsrdataset == NULL) {
5425 result = advanced_rrsearch(&chase_dsrdataset, &chase_signame,
5426 dns_rdatatype_ds, dns_rdatatype_any,
5427 &chase_dslookedup);
5428 if (result == ISC_R_FAILURE) {
5429 printf("\n;; WARNING There is no DS for the zone: ");
5430 dns_name_print(&chase_signame, stdout);
5431 printf("\n");
5432 }
5433 if (result == ISC_R_NOTFOUND) {
5434 free_name(&chase_signame);
5435 return (ISC_R_NOTFOUND);
5436 }
5437 if (chase_dsrdataset != NULL) {
5438 printf("\n;; DSset of the DNSKEYset\n");
5439 print_rdataset(&chase_signame, chase_dsrdataset);
5440 }
5441 }
5442
5443 if (chase_dsrdataset != NULL) {
5444 /*
5445 * if there is no RRSIG of DS,
5446 * we don't want to search on the network
5447 */
5448 result = advanced_rrsearch(&chase_sigdsrdataset,
5449 &chase_signame,
5450 dns_rdatatype_rrsig,
5451 dns_rdatatype_ds, &true);
5452 if (result == ISC_R_FAILURE) {
5453 printf(";; WARNING : NO RRSIG DS : RRSIG DS"
5454 " should come with DS\n");
5455 /*
5456 * We continue even the DS couldn't be validated,
5457 * because the DNSKEY could be a Trusted Key.
5458 */
5459 chase_dsrdataset = NULL;
5460 } else {
5461 printf("\n;; RRSIG of the DSset of the DNSKEYset\n");
5462 print_rdataset(&chase_signame, chase_sigdsrdataset);
5463 }
5464 }
5465 return (1);
5466 }
5467
5468
5469
5470 void
sigchase_bu(dns_message_t * msg)5471 sigchase_bu(dns_message_t *msg)
5472 {
5473 isc_result_t result;
5474 int ret;
5475
5476 if (tk_list.nb_tk == 0) {
5477 result = get_trusted_key();
5478 if (result != ISC_R_SUCCESS) {
5479 printf("No trusted keys present\n");
5480 return;
5481 }
5482 }
5483
5484
5485 ret = getneededrr(msg);
5486 if (ret == ISC_R_NOTFOUND)
5487 return;
5488
5489 if (ret == ISC_R_ADDRNOTAVAIL) {
5490 /* We have no response */
5491 dns_rdataset_t *rdataset;
5492 dns_rdataset_t *sigrdataset;
5493 dns_name_t rdata_name;
5494 dns_name_t query_name;
5495
5496
5497 dns_name_init(&query_name, NULL);
5498 dns_name_init(&rdata_name, NULL);
5499 nameFromString(current_lookup->textname, &query_name);
5500
5501 result = prove_nx(msg, &query_name, current_lookup->rdclass,
5502 current_lookup->rdtype, &rdata_name,
5503 &rdataset, &sigrdataset);
5504 free_name(&query_name);
5505 if (rdataset == NULL || sigrdataset == NULL ||
5506 dns_name_countlabels(&rdata_name) == 0) {
5507 printf("\n;; Impossible to verify the Non-existence,"
5508 " the NSEC RRset can't be validated: "
5509 "FAILED\n\n");
5510 clean_trustedkey();
5511 return;
5512 }
5513
5514 if (result != ISC_R_SUCCESS) {
5515 printf("\n No Answers and impossible to prove the"
5516 " unsecurity : Validation FAILED\n\n");
5517 clean_trustedkey();
5518 return;
5519 }
5520 printf(";; An NSEC prove the non-existence of a answers,"
5521 " Now we want validate this NSEC\n");
5522
5523 dup_name(&rdata_name, &chase_name);
5524 free_name(&rdata_name);
5525 chase_rdataset = rdataset;
5526 chase_sigrdataset = sigrdataset;
5527 chase_keyrdataset = NULL;
5528 chase_sigkeyrdataset = NULL;
5529 chase_dsrdataset = NULL;
5530 chase_sigdsrdataset = NULL;
5531 chase_siglookedup = ISC_FALSE;
5532 chase_keylookedup = ISC_FALSE;
5533 chase_dslookedup = ISC_FALSE;
5534 chase_sigdslookedup = ISC_FALSE;
5535 sigchase(msg);
5536 clean_trustedkey();
5537 return;
5538 }
5539
5540
5541 printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n");
5542
5543 result = sigchase_verify_sig(&chase_name, chase_rdataset,
5544 chase_keyrdataset,
5545 chase_sigrdataset);
5546 if (result != ISC_R_SUCCESS) {
5547 free_name(&chase_name);
5548 free_name(&chase_signame);
5549 printf(";; No DNSKEY is valid to check the RRSIG"
5550 " of the RRset: FAILED\n");
5551 clean_trustedkey();
5552 return;
5553 }
5554 printf(";; OK We found DNSKEY (or more) to validate the RRset\n");
5555
5556 result = contains_trusted_key(&chase_signame, chase_keyrdataset,
5557 chase_sigkeyrdataset);
5558 if (result == ISC_R_SUCCESS) {
5559 free_name(&chase_name);
5560 free_name(&chase_signame);
5561 printf("\n;; Ok this DNSKEY is a Trusted Key,"
5562 " DNSSEC validation is ok: SUCCESS\n\n");
5563 clean_trustedkey();
5564 return;
5565 }
5566
5567 printf(";; Now, we are going to validate this DNSKEY by the DS\n");
5568
5569 if (chase_dsrdataset == NULL) {
5570 free_name(&chase_name);
5571 free_name(&chase_signame);
5572 printf(";; the DNSKEY isn't trusted-key and there isn't"
5573 " DS to validate the DNSKEY: FAILED\n");
5574 clean_trustedkey();
5575 return;
5576 }
5577
5578 result = sigchase_verify_ds(&chase_signame, chase_keyrdataset,
5579 chase_dsrdataset);
5580 if (result != ISC_R_SUCCESS) {
5581 free_name(&chase_signame);
5582 free_name(&chase_name);
5583 printf(";; ERROR no DS validates a DNSKEY in the"
5584 " DNSKEY RRset: FAILED\n");
5585 clean_trustedkey();
5586 return;
5587 } else
5588 printf(";; OK this DNSKEY (validated by the DS) validates"
5589 " the RRset of the DNSKEYs, thus the DNSKEY validates"
5590 " the RRset\n");
5591 INSIST(chase_sigdsrdataset != NULL);
5592
5593 dup_name(&chase_signame, &chase_name);
5594 free_name(&chase_signame);
5595 chase_rdataset = chase_dsrdataset;
5596 chase_sigrdataset = chase_sigdsrdataset;
5597 chase_keyrdataset = NULL;
5598 chase_sigkeyrdataset = NULL;
5599 chase_dsrdataset = NULL;
5600 chase_sigdsrdataset = NULL;
5601 chase_siglookedup = chase_keylookedup = ISC_FALSE;
5602 chase_dslookedup = chase_sigdslookedup = ISC_FALSE;
5603
5604 printf(";; Now, we want to validate the DS : recursive call\n");
5605 sigchase(msg);
5606 return;
5607 }
5608 #endif
5609
5610 void
sigchase(dns_message_t * msg)5611 sigchase(dns_message_t *msg) {
5612 #if DIG_SIGCHASE_TD
5613 if (current_lookup->do_topdown) {
5614 sigchase_td(msg);
5615 return;
5616 }
5617 #endif
5618 #if DIG_SIGCHASE_BU
5619 sigchase_bu(msg);
5620 return;
5621 #endif
5622 }
5623
5624
5625 /*
5626 * return 1 if name1 < name2
5627 * 0 if name1 == name2
5628 * -1 if name1 > name2
5629 * and -2 if problem
5630 */
5631 int
inf_name(dns_name_t * name1,dns_name_t * name2)5632 inf_name(dns_name_t *name1, dns_name_t *name2)
5633 {
5634 dns_label_t label1;
5635 dns_label_t label2;
5636 unsigned int nblabel1;
5637 unsigned int nblabel2;
5638 int min_lum_label;
5639 int i;
5640 int ret = -2;
5641
5642 nblabel1 = dns_name_countlabels(name1);
5643 nblabel2 = dns_name_countlabels(name2);
5644
5645 if (nblabel1 >= nblabel2)
5646 min_lum_label = nblabel2;
5647 else
5648 min_lum_label = nblabel1;
5649
5650
5651 for (i=1 ; i < min_lum_label; i++) {
5652 dns_name_getlabel(name1, nblabel1 -1 - i, &label1);
5653 dns_name_getlabel(name2, nblabel2 -1 - i, &label2);
5654 if ((ret = isc_region_compare(&label1, &label2)) != 0) {
5655 if (ret < 0)
5656 return (-1);
5657 else if (ret > 0)
5658 return (1);
5659 }
5660 }
5661 if (nblabel1 == nblabel2)
5662 return (0);
5663
5664 if (nblabel1 < nblabel2)
5665 return (-1);
5666 else
5667 return (1);
5668 }
5669
5670 /**
5671 *
5672 *
5673 *
5674 */
5675 isc_result_t
prove_nx_domain(dns_message_t * msg,dns_name_t * name,dns_name_t * rdata_name,dns_rdataset_t ** rdataset,dns_rdataset_t ** sigrdataset)5676 prove_nx_domain(dns_message_t *msg,
5677 dns_name_t *name,
5678 dns_name_t *rdata_name,
5679 dns_rdataset_t **rdataset,
5680 dns_rdataset_t **sigrdataset)
5681 {
5682 isc_result_t ret = ISC_R_FAILURE;
5683 isc_result_t result = ISC_R_NOTFOUND;
5684 dns_rdataset_t *nsecset = NULL;
5685 dns_rdataset_t *signsecset = NULL ;
5686 dns_rdata_t nsec = DNS_RDATA_INIT;
5687 dns_name_t *nsecname;
5688 dns_rdata_nsec_t nsecstruct;
5689
5690 if ((result = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
5691 != ISC_R_SUCCESS) {
5692 printf(";; nothing in authority section : impossible to"
5693 " validate the non-existence : FAILED\n");
5694 return (ISC_R_FAILURE);
5695 }
5696
5697 do {
5698 nsecname = NULL;
5699 dns_message_currentname(msg, DNS_SECTION_AUTHORITY, &nsecname);
5700 nsecset = search_type(nsecname, dns_rdatatype_nsec,
5701 dns_rdatatype_any);
5702 if (nsecset == NULL)
5703 continue;
5704
5705 printf("There is a NSEC for this zone in the"
5706 " AUTHORITY section:\n");
5707 print_rdataset(nsecname, nsecset);
5708
5709 for (result = dns_rdataset_first(nsecset);
5710 result == ISC_R_SUCCESS;
5711 result = dns_rdataset_next(nsecset)) {
5712 dns_rdataset_current(nsecset, &nsec);
5713
5714 signsecset
5715 = chase_scanname_section(msg, nsecname,
5716 dns_rdatatype_rrsig,
5717 dns_rdatatype_nsec,
5718 DNS_SECTION_AUTHORITY);
5719 if (signsecset == NULL) {
5720 printf(";; no RRSIG NSEC in authority section:"
5721 " impossible to validate the "
5722 "non-existence: FAILED\n");
5723 return (ISC_R_FAILURE);
5724 }
5725
5726 ret = dns_rdata_tostruct(&nsec, &nsecstruct, NULL);
5727 check_result(ret,"dns_rdata_tostruct");
5728
5729 if ((inf_name(nsecname, &nsecstruct.next) == 1 &&
5730 inf_name(name, &nsecstruct.next) == 1) ||
5731 (inf_name(name, nsecname) == 1 &&
5732 inf_name(&nsecstruct.next, name) == 1)) {
5733 dns_rdata_freestruct(&nsecstruct);
5734 *rdataset = nsecset;
5735 *sigrdataset = signsecset;
5736 dup_name(nsecname, rdata_name);
5737
5738 return (ISC_R_SUCCESS);
5739 }
5740
5741 dns_rdata_freestruct(&nsecstruct);
5742 dns_rdata_reset(&nsec);
5743 }
5744 } while (dns_message_nextname(msg, DNS_SECTION_AUTHORITY)
5745 == ISC_R_SUCCESS);
5746
5747 *rdataset = NULL;
5748 *sigrdataset = NULL;
5749 rdata_name = NULL;
5750 return (ISC_R_FAILURE);
5751 }
5752
5753 /**
5754 *
5755 *
5756 *
5757 *
5758 *
5759 */
5760 isc_result_t
prove_nx_type(dns_message_t * msg,dns_name_t * name,dns_rdataset_t * nsecset,dns_rdataclass_t class,dns_rdatatype_t type,dns_name_t * rdata_name,dns_rdataset_t ** rdataset,dns_rdataset_t ** sigrdataset)5761 prove_nx_type(dns_message_t *msg, dns_name_t *name, dns_rdataset_t *nsecset,
5762 dns_rdataclass_t class, dns_rdatatype_t type,
5763 dns_name_t *rdata_name, dns_rdataset_t **rdataset,
5764 dns_rdataset_t **sigrdataset)
5765 {
5766 isc_result_t ret;
5767 dns_rdataset_t *signsecset;
5768 dns_rdata_t nsec = DNS_RDATA_INIT;
5769
5770 UNUSED(class);
5771
5772 ret = dns_rdataset_first(nsecset);
5773 check_result(ret,"dns_rdataset_first");
5774
5775 dns_rdataset_current(nsecset, &nsec);
5776
5777 ret = dns_nsec_typepresent(&nsec, type);
5778 if (ret == ISC_R_SUCCESS)
5779 printf("OK the NSEC said that the type doesn't exist \n");
5780
5781 signsecset = chase_scanname_section(msg, name,
5782 dns_rdatatype_rrsig,
5783 dns_rdatatype_nsec,
5784 DNS_SECTION_AUTHORITY);
5785 if (signsecset == NULL) {
5786 printf("There isn't RRSIG NSEC for the zone \n");
5787 return (ISC_R_FAILURE);
5788 }
5789 dup_name(name, rdata_name);
5790 *rdataset = nsecset;
5791 *sigrdataset = signsecset;
5792
5793 return (ret);
5794 }
5795
5796 /**
5797 *
5798 *
5799 *
5800 *
5801 */
5802 isc_result_t
prove_nx(dns_message_t * msg,dns_name_t * name,dns_rdataclass_t class,dns_rdatatype_t type,dns_name_t * rdata_name,dns_rdataset_t ** rdataset,dns_rdataset_t ** sigrdataset)5803 prove_nx(dns_message_t *msg, dns_name_t *name, dns_rdataclass_t class,
5804 dns_rdatatype_t type, dns_name_t *rdata_name,
5805 dns_rdataset_t **rdataset, dns_rdataset_t **sigrdataset)
5806 {
5807 isc_result_t ret;
5808 dns_rdataset_t *nsecset = NULL;
5809
5810 printf("We want to prove the non-existence of a type of rdata %d"
5811 " or of the zone: \n", type);
5812
5813 if ((ret = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
5814 != ISC_R_SUCCESS) {
5815 printf(";; nothing in authority section : impossible to"
5816 " validate the non-existence : FAILED\n");
5817 return (ISC_R_FAILURE);
5818 }
5819
5820 nsecset = chase_scanname_section(msg, name, dns_rdatatype_nsec,
5821 dns_rdatatype_any,
5822 DNS_SECTION_AUTHORITY);
5823 if (nsecset != NULL) {
5824 printf("We have a NSEC for this zone :OK\n");
5825 ret = prove_nx_type(msg, name, nsecset, class,
5826 type, rdata_name, rdataset,
5827 sigrdataset);
5828 if (ret != ISC_R_SUCCESS) {
5829 printf("prove_nx: ERROR type exist\n");
5830 return (ret);
5831 } else {
5832 printf("prove_nx: OK type does not exist\n");
5833 return (ISC_R_SUCCESS);
5834 }
5835 } else {
5836 printf("there is no NSEC for this zone: validating "
5837 "that the zone doesn't exist\n");
5838 ret = prove_nx_domain(msg, name, rdata_name,
5839 rdataset, sigrdataset);
5840 return (ret);
5841 }
5842 /* Never get here */
5843 }
5844 #endif
5845