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