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