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