1 /* $NetBSD: delv.c,v 1.4 2015/07/08 17:28:54 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2014, 2015 Internet Systems Consortium, Inc. ("ISC") 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <config.h> 20 #include <bind.keys.h> 21 22 #ifndef WIN32 23 #include <sys/types.h> 24 #include <sys/socket.h> 25 #include <signal.h> 26 27 #include <netinet/in.h> 28 29 #include <arpa/inet.h> 30 31 #include <netdb.h> 32 #endif 33 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <unistd.h> 38 39 #include <isc/app.h> 40 #include <isc/base64.h> 41 #include <isc/buffer.h> 42 #include <isc/lib.h> 43 #include <isc/log.h> 44 #include <isc/mem.h> 45 #ifdef WIN32 46 #include <isc/ntpaths.h> 47 #endif 48 #include <isc/parseint.h> 49 #include <isc/print.h> 50 #include <isc/sockaddr.h> 51 #include <isc/socket.h> 52 #include <isc/string.h> 53 #include <isc/task.h> 54 #include <isc/timer.h> 55 #include <isc/util.h> 56 57 #include <irs/resconf.h> 58 #include <irs/netdb.h> 59 60 #include <isccfg/log.h> 61 #include <isccfg/namedconf.h> 62 63 #include <dns/byaddr.h> 64 #include <dns/client.h> 65 #include <dns/fixedname.h> 66 #include <dns/keytable.h> 67 #include <dns/keyvalues.h> 68 #include <dns/lib.h> 69 #include <dns/log.h> 70 #include <dns/masterdump.h> 71 #include <dns/name.h> 72 #include <dns/rdata.h> 73 #include <dns/rdataclass.h> 74 #include <dns/rdataset.h> 75 #include <dns/rdatastruct.h> 76 #include <dns/rdatatype.h> 77 #include <dns/result.h> 78 #include <dns/secalg.h> 79 #include <dns/view.h> 80 81 #include <dst/dst.h> 82 #include <dst/result.h> 83 84 #define CHECK(r) \ 85 do { \ 86 result = (r); \ 87 if (result != ISC_R_SUCCESS) \ 88 goto cleanup; \ 89 } while (/*CONSTCOND*/0) 90 91 #define MAXNAME (DNS_NAME_MAXTEXT+1) 92 93 /* Variables used internally by delv. */ 94 char *progname; 95 static isc_mem_t *mctx = NULL; 96 static isc_log_t *lctx = NULL; 97 98 /* Configurables */ 99 static char *server = NULL; 100 static const char *port = "53"; 101 static isc_sockaddr_t *srcaddr4 = NULL, *srcaddr6 = NULL; 102 static isc_sockaddr_t a4, a6; 103 static char *curqname = NULL, *qname = NULL; 104 static isc_boolean_t classset = ISC_FALSE; 105 static dns_rdatatype_t qtype = dns_rdatatype_none; 106 static isc_boolean_t typeset = ISC_FALSE; 107 108 static unsigned int styleflags = 0; 109 static isc_uint32_t splitwidth = 0xffffffff; 110 static isc_boolean_t 111 showcomments = ISC_TRUE, 112 showdnssec = ISC_TRUE, 113 showtrust = ISC_TRUE, 114 rrcomments = ISC_TRUE, 115 noclass = ISC_FALSE, 116 nocrypto = ISC_FALSE, 117 nottl = ISC_FALSE, 118 multiline = ISC_FALSE, 119 short_form = ISC_FALSE; 120 121 static isc_boolean_t 122 resolve_trace = ISC_FALSE, 123 validator_trace = ISC_FALSE, 124 message_trace = ISC_FALSE; 125 126 static isc_boolean_t 127 use_ipv4 = ISC_TRUE, 128 use_ipv6 = ISC_TRUE; 129 130 static isc_boolean_t 131 cdflag = ISC_FALSE, 132 no_sigs = ISC_FALSE, 133 root_validation = ISC_TRUE, 134 dlv_validation = ISC_TRUE; 135 136 static char *anchorfile = NULL; 137 static char *trust_anchor = NULL; 138 static char *dlv_anchor = NULL; 139 static int trusted_keys = 0; 140 141 static dns_fixedname_t afn, dfn; 142 static dns_name_t *anchor_name = NULL, *dlv_name = NULL; 143 144 /* Default bind.keys contents */ 145 static char anchortext[] = MANAGED_KEYS; 146 147 /* 148 * Static function prototypes 149 */ 150 static isc_result_t 151 get_reverse(char *reverse, size_t len, char *value, isc_boolean_t strict); 152 153 static isc_result_t 154 parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, 155 const char *desc); 156 157 static void 158 usage(void) { 159 fputs( 160 "Usage: delv [@server] {q-opt} {d-opt} [domain] [q-type] [q-class]\n" 161 "Where: domain is in the Domain Name System\n" 162 " q-class is one of (in,hs,ch,...) [default: in]\n" 163 " q-type is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default:a]\n" 164 " q-opt is one of:\n" 165 " -x dot-notation (shortcut for reverse lookups)\n" 166 " -d level (set debugging level)\n" 167 " -a anchor-file (specify root and dlv trust anchors)\n" 168 " -b address[#port] (bind to source address/port)\n" 169 " -p port (specify port number)\n" 170 " -q name (specify query name)\n" 171 " -t type (specify query type)\n" 172 " -c class (specify query class)\n" 173 " -4 (use IPv4 query transport only)\n" 174 " -6 (use IPv6 query transport only)\n" 175 " -i (disable DNSSEC validation)\n" 176 " -m (enable memory usage debugging)\n" 177 " d-opt is of the form +keyword[=value], where keyword is:\n" 178 " +[no]all (Set or clear all display flags)\n" 179 " +[no]class (Control display of class)\n" 180 " +[no]crypto (Control display of cryptographic\n" 181 " fields in records)\n" 182 " +[no]multiline (Print records in an expanded format)\n" 183 " +[no]comments (Control display of comment lines)\n" 184 " +[no]rrcomments (Control display of per-record " 185 "comments)\n" 186 " +[no]short (Short form answer)\n" 187 " +[no]split=## (Split hex/base64 fields into chunks)\n" 188 " +[no]ttl (Control display of ttls in records)\n" 189 " +[no]trust (Control display of trust level)\n" 190 " +[no]rtrace (Trace resolver fetches)\n" 191 " +[no]mtrace (Trace messages received)\n" 192 " +[no]vtrace (Trace validation process)\n" 193 " +[no]dlv (DNSSEC lookaside validation anchor)\n" 194 " +[no]root (DNSSEC validation trust anchor)\n" 195 " +[no]dnssec (Display DNSSEC records)\n" 196 " -h (print help and exit)\n" 197 " -v (print version and exit)\n", 198 stderr); 199 exit(1); 200 } 201 202 ISC_PLATFORM_NORETURN_PRE static void 203 fatal(const char *format, ...) 204 ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST; 205 206 static void 207 fatal(const char *format, ...) { 208 va_list args; 209 210 fflush(stdout); 211 fprintf(stderr, "%s: ", progname); 212 va_start(args, format); 213 vfprintf(stderr, format, args); 214 va_end(args); 215 fprintf(stderr, "\n"); 216 exit(1); 217 } 218 219 static void 220 warn(const char *format, ...) ISC_FORMAT_PRINTF(1, 2); 221 222 static void 223 warn(const char *format, ...) { 224 va_list args; 225 226 fflush(stdout); 227 fprintf(stderr, "%s: warning: ", progname); 228 va_start(args, format); 229 vfprintf(stderr, format, args); 230 va_end(args); 231 fprintf(stderr, "\n"); 232 } 233 234 static isc_logcategory_t categories[] = { 235 { "delv", 0 }, 236 { NULL, 0 } 237 }; 238 #define LOGCATEGORY_DEFAULT (&categories[0]) 239 #define LOGMODULE_DEFAULT (&modules[0]) 240 241 static isc_logmodule_t modules[] = { 242 { "delv", 0 }, 243 { NULL, 0 } 244 }; 245 246 static void 247 delv_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3); 248 249 static void 250 delv_log(int level, const char *fmt, ...) { 251 va_list ap; 252 char msgbuf[2048]; 253 254 if (! isc_log_wouldlog(lctx, level)) 255 return; 256 257 va_start(ap, fmt); 258 259 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); 260 isc_log_write(lctx, LOGCATEGORY_DEFAULT, LOGMODULE_DEFAULT, 261 level, "%s", msgbuf); 262 va_end(ap); 263 } 264 265 static int loglevel = 0; 266 267 static void 268 setup_logging(FILE *errout) { 269 isc_result_t result; 270 isc_logdestination_t destination; 271 isc_logconfig_t *logconfig = NULL; 272 273 result = isc_log_create(mctx, &lctx, &logconfig); 274 if (result != ISC_R_SUCCESS) 275 fatal("Couldn't set up logging"); 276 277 isc_log_registercategories(lctx, categories); 278 isc_log_registermodules(lctx, modules); 279 isc_log_setcontext(lctx); 280 dns_log_init(lctx); 281 dns_log_setcontext(lctx); 282 cfg_log_init(lctx); 283 284 destination.file.stream = errout; 285 destination.file.name = NULL; 286 destination.file.versions = ISC_LOG_ROLLNEVER; 287 destination.file.maximum_size = 0; 288 289 result = isc_log_createchannel(logconfig, "stderr", 290 ISC_LOG_TOFILEDESC, ISC_LOG_DYNAMIC, 291 &destination, ISC_LOG_PRINTPREFIX); 292 if (result != ISC_R_SUCCESS) 293 fatal("Couldn't set up log channel 'stderr'"); 294 295 isc_log_setdebuglevel(lctx, loglevel); 296 297 result = isc_log_settag(logconfig, ";; "); 298 if (result != ISC_R_SUCCESS) 299 fatal("Couldn't set log tag"); 300 301 result = isc_log_usechannel(logconfig, "stderr", 302 ISC_LOGCATEGORY_DEFAULT, NULL); 303 if (result != ISC_R_SUCCESS) 304 fatal("Couldn't attach to log channel 'stderr'"); 305 306 if (resolve_trace && loglevel < 1) { 307 result = isc_log_createchannel(logconfig, "resolver", 308 ISC_LOG_TOFILEDESC, 309 ISC_LOG_DEBUG(1), 310 &destination, 311 ISC_LOG_PRINTPREFIX); 312 if (result != ISC_R_SUCCESS) 313 fatal("Couldn't set up log channel 'resolver'"); 314 315 result = isc_log_usechannel(logconfig, "resolver", 316 DNS_LOGCATEGORY_RESOLVER, 317 DNS_LOGMODULE_RESOLVER); 318 if (result != ISC_R_SUCCESS) 319 fatal("Couldn't attach to log channel 'resolver'"); 320 } 321 322 if (validator_trace && loglevel < 3) { 323 result = isc_log_createchannel(logconfig, "validator", 324 ISC_LOG_TOFILEDESC, 325 ISC_LOG_DEBUG(3), 326 &destination, 327 ISC_LOG_PRINTPREFIX); 328 if (result != ISC_R_SUCCESS) 329 fatal("Couldn't set up log channel 'validator'"); 330 331 result = isc_log_usechannel(logconfig, "validator", 332 DNS_LOGCATEGORY_DNSSEC, 333 DNS_LOGMODULE_VALIDATOR); 334 if (result != ISC_R_SUCCESS) 335 fatal("Couldn't attach to log channel 'validator'"); 336 } 337 338 if (message_trace && loglevel < 10) { 339 result = isc_log_createchannel(logconfig, "messages", 340 ISC_LOG_TOFILEDESC, 341 ISC_LOG_DEBUG(10), 342 &destination, 343 ISC_LOG_PRINTPREFIX); 344 if (result != ISC_R_SUCCESS) 345 fatal("Couldn't set up log channel 'messages'"); 346 347 result = isc_log_usechannel(logconfig, "messages", 348 DNS_LOGCATEGORY_RESOLVER, 349 DNS_LOGMODULE_PACKETS); 350 if (result != ISC_R_SUCCESS) 351 fatal("Couldn't attach to log channel 'messagse'"); 352 } 353 } 354 355 static void 356 print_status(dns_rdataset_t *rdataset) { 357 const char *astr = "", *tstr = ""; 358 359 REQUIRE(rdataset != NULL); 360 361 if (!showtrust || !dns_rdataset_isassociated(rdataset)) 362 return; 363 364 if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) 365 astr = "negative response, "; 366 367 switch (rdataset->trust) { 368 case dns_trust_none: 369 tstr = "untrusted"; 370 break; 371 case dns_trust_pending_additional: 372 tstr = "signed additional data, pending validation"; 373 break; 374 case dns_trust_pending_answer: 375 tstr = "signed answer, pending validation"; 376 break; 377 case dns_trust_additional: 378 tstr = "unsigned additional data"; 379 break; 380 case dns_trust_glue: 381 tstr = "glue data"; 382 break; 383 case dns_trust_answer: 384 if (root_validation || dlv_validation) 385 tstr = "unsigned answer"; 386 else 387 tstr = "answer not validated"; 388 break; 389 case dns_trust_authauthority: 390 tstr = "authority data"; 391 break; 392 case dns_trust_authanswer: 393 tstr = "authoritative"; 394 break; 395 case dns_trust_secure: 396 tstr = "fully validated"; 397 break; 398 case dns_trust_ultimate: 399 tstr = "ultimate trust"; 400 break; 401 } 402 403 printf("; %s%s\n", astr, tstr); 404 } 405 406 static isc_result_t 407 printdata(dns_rdataset_t *rdataset, dns_name_t *owner, 408 dns_master_style_t *style) 409 { 410 isc_result_t result = ISC_R_SUCCESS; 411 static dns_trust_t trust; 412 static isc_boolean_t first = ISC_TRUE; 413 isc_buffer_t target; 414 isc_region_t r; 415 char *t = NULL; 416 int len = 2048; 417 418 if (!dns_rdataset_isassociated(rdataset)) { 419 char namebuf[DNS_NAME_FORMATSIZE]; 420 dns_name_format(owner, namebuf, sizeof(namebuf)); 421 delv_log(ISC_LOG_DEBUG(4), 422 "WARN: empty rdataset %s", namebuf); 423 return (ISC_R_SUCCESS); 424 } 425 426 if (!showdnssec && rdataset->type == dns_rdatatype_rrsig) 427 return (ISC_R_SUCCESS); 428 429 if (first || rdataset->trust != trust) { 430 if (!first && showtrust && !short_form) 431 putchar('\n'); 432 print_status(rdataset); 433 trust = rdataset->trust; 434 first = ISC_FALSE; 435 } 436 437 do { 438 t = isc_mem_get(mctx, len); 439 if (t == NULL) 440 return (ISC_R_NOMEMORY); 441 442 isc_buffer_init(&target, t, len); 443 if (short_form) { 444 dns_rdata_t rdata = DNS_RDATA_INIT; 445 for (result = dns_rdataset_first(rdataset); 446 result == ISC_R_SUCCESS; 447 result = dns_rdataset_next(rdataset)) 448 { 449 if ((rdataset->attributes & 450 DNS_RDATASETATTR_NEGATIVE) != 0) 451 continue; 452 453 dns_rdataset_current(rdataset, &rdata); 454 result = dns_rdata_tofmttext(&rdata, 455 dns_rootname, 456 styleflags, 457 0, 60, " ", 458 &target); 459 if (result != ISC_R_SUCCESS) 460 break; 461 462 if (isc_buffer_availablelength(&target) < 1) { 463 result = ISC_R_NOSPACE; 464 break; 465 } 466 467 isc_buffer_putstr(&target, "\n"); 468 469 dns_rdata_reset(&rdata); 470 } 471 } else { 472 if ((rdataset->attributes & 473 DNS_RDATASETATTR_NEGATIVE) != 0) 474 isc_buffer_putstr(&target, "; "); 475 476 result = dns_master_rdatasettotext(owner, rdataset, 477 style, &target); 478 } 479 480 if (result == ISC_R_NOSPACE) { 481 isc_mem_put(mctx, t, len); 482 len += 1024; 483 } else if (result == ISC_R_NOMORE) 484 result = ISC_R_SUCCESS; 485 else 486 CHECK(result); 487 } while (result == ISC_R_NOSPACE); 488 489 isc_buffer_usedregion(&target, &r); 490 printf("%.*s", (int)r.length, (char *)r.base); 491 492 cleanup: 493 if (t != NULL) 494 isc_mem_put(mctx, t, len); 495 496 return (ISC_R_SUCCESS); 497 } 498 499 static isc_result_t 500 setup_style(dns_master_style_t **stylep) { 501 isc_result_t result; 502 dns_master_style_t *style = NULL; 503 504 REQUIRE(stylep != NULL || *stylep == NULL); 505 506 styleflags |= DNS_STYLEFLAG_REL_OWNER; 507 if (showcomments) 508 styleflags |= DNS_STYLEFLAG_COMMENT; 509 if (rrcomments) 510 styleflags |= DNS_STYLEFLAG_RRCOMMENT; 511 if (nottl) 512 styleflags |= DNS_STYLEFLAG_NO_TTL; 513 if (noclass) 514 styleflags |= DNS_STYLEFLAG_NO_CLASS; 515 if (nocrypto) 516 styleflags |= DNS_STYLEFLAG_NOCRYPTO; 517 if (multiline) { 518 styleflags |= DNS_STYLEFLAG_MULTILINE; 519 styleflags |= DNS_STYLEFLAG_COMMENT; 520 } 521 522 if (multiline || (nottl && noclass)) 523 result = dns_master_stylecreate2(&style, styleflags, 524 24, 24, 24, 32, 80, 8, 525 splitwidth, mctx); 526 else if (nottl || noclass) 527 result = dns_master_stylecreate2(&style, styleflags, 528 24, 24, 32, 40, 80, 8, 529 splitwidth, mctx); 530 else 531 result = dns_master_stylecreate2(&style, styleflags, 532 24, 32, 40, 48, 80, 8, 533 splitwidth, mctx); 534 535 if (result == ISC_R_SUCCESS) 536 *stylep = style; 537 return (result); 538 } 539 540 static isc_result_t 541 convert_name(dns_fixedname_t *fn, dns_name_t **name, const char *text) { 542 isc_result_t result; 543 isc_buffer_t b; 544 dns_name_t *n; 545 unsigned int len; 546 547 REQUIRE(fn != NULL && name != NULL && text != NULL); 548 len = strlen(text); 549 550 isc_buffer_constinit(&b, text, len); 551 isc_buffer_add(&b, len); 552 dns_fixedname_init(fn); 553 n = dns_fixedname_name(fn); 554 555 result = dns_name_fromtext(n, &b, dns_rootname, 0, NULL); 556 if (result != ISC_R_SUCCESS) { 557 delv_log(ISC_LOG_ERROR, "failed to convert QNAME %s: %s", 558 text, isc_result_totext(result)); 559 return (result); 560 } 561 562 *name = n; 563 return (ISC_R_SUCCESS); 564 } 565 566 static isc_result_t 567 key_fromconfig(const cfg_obj_t *key, dns_client_t *client) { 568 dns_rdata_dnskey_t keystruct; 569 isc_uint32_t flags, proto, alg; 570 const char *keystr, *keynamestr; 571 unsigned char keydata[4096]; 572 isc_buffer_t keydatabuf; 573 unsigned char rrdata[4096]; 574 isc_buffer_t rrdatabuf; 575 isc_region_t r; 576 dns_fixedname_t fkeyname; 577 dns_name_t *keyname; 578 isc_result_t result; 579 isc_boolean_t match_root, match_dlv; 580 581 keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); 582 CHECK(convert_name(&fkeyname, &keyname, keynamestr)); 583 584 if (!root_validation && !dlv_validation) 585 return (ISC_R_SUCCESS); 586 587 match_root = dns_name_equal(keyname, anchor_name); 588 match_dlv = dns_name_equal(keyname, dlv_name); 589 590 if (!match_root && !match_dlv) 591 return (ISC_R_SUCCESS); 592 if ((!root_validation && match_root) || (!dlv_validation && match_dlv)) 593 return (ISC_R_SUCCESS); 594 595 if (match_root) 596 delv_log(ISC_LOG_DEBUG(3), "adding trust anchor %s", 597 trust_anchor); 598 if (match_dlv) 599 delv_log(ISC_LOG_DEBUG(3), "adding DLV trust anchor %s", 600 dlv_anchor); 601 602 flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); 603 proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol")); 604 alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm")); 605 606 keystruct.common.rdclass = dns_rdataclass_in; 607 keystruct.common.rdtype = dns_rdatatype_dnskey; 608 /* 609 * The key data in keystruct is not dynamically allocated. 610 */ 611 keystruct.mctx = NULL; 612 613 ISC_LINK_INIT(&keystruct.common, link); 614 615 if (flags > 0xffff) 616 CHECK(ISC_R_RANGE); 617 if (proto > 0xff) 618 CHECK(ISC_R_RANGE); 619 if (alg > 0xff) 620 CHECK(ISC_R_RANGE); 621 622 keystruct.flags = (isc_uint16_t)flags; 623 keystruct.protocol = (isc_uint8_t)proto; 624 keystruct.algorithm = (isc_uint8_t)alg; 625 626 isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); 627 isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); 628 629 keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); 630 CHECK(isc_base64_decodestring(keystr, &keydatabuf)); 631 isc_buffer_usedregion(&keydatabuf, &r); 632 keystruct.datalen = r.length; 633 keystruct.data = r.base; 634 635 CHECK(dns_rdata_fromstruct(NULL, 636 keystruct.common.rdclass, 637 keystruct.common.rdtype, 638 &keystruct, &rrdatabuf)); 639 640 CHECK(dns_client_addtrustedkey(client, dns_rdataclass_in, 641 keyname, &rrdatabuf)); 642 trusted_keys++; 643 644 cleanup: 645 if (result == DST_R_NOCRYPTO) 646 cfg_obj_log(key, lctx, ISC_LOG_ERROR, "no crypto support"); 647 else if (result == DST_R_UNSUPPORTEDALG) { 648 cfg_obj_log(key, lctx, ISC_LOG_WARNING, 649 "skipping trusted key '%s': %s", 650 keynamestr, isc_result_totext(result)); 651 result = ISC_R_SUCCESS; 652 } else if (result != ISC_R_SUCCESS) { 653 cfg_obj_log(key, lctx, ISC_LOG_ERROR, 654 "failed to add trusted key '%s': %s", 655 keynamestr, isc_result_totext(result)); 656 result = ISC_R_FAILURE; 657 } 658 659 return (result); 660 } 661 662 static isc_result_t 663 load_keys(const cfg_obj_t *keys, dns_client_t *client) { 664 const cfg_listelt_t *elt, *elt2; 665 const cfg_obj_t *key, *keylist; 666 isc_result_t result = ISC_R_SUCCESS; 667 668 for (elt = cfg_list_first(keys); 669 elt != NULL; 670 elt = cfg_list_next(elt)) 671 { 672 keylist = cfg_listelt_value(elt); 673 674 for (elt2 = cfg_list_first(keylist); 675 elt2 != NULL; 676 elt2 = cfg_list_next(elt2)) 677 { 678 key = cfg_listelt_value(elt2); 679 CHECK(key_fromconfig(key, client)); 680 } 681 } 682 683 cleanup: 684 if (result == DST_R_NOCRYPTO) 685 result = ISC_R_SUCCESS; 686 return (result); 687 } 688 689 static isc_result_t 690 setup_dnsseckeys(dns_client_t *client) { 691 isc_result_t result; 692 cfg_parser_t *parser = NULL; 693 const cfg_obj_t *keys = NULL; 694 const cfg_obj_t *managed_keys = NULL; 695 cfg_obj_t *bindkeys = NULL; 696 const char *filename = anchorfile; 697 698 if (!root_validation && !dlv_validation) 699 return (ISC_R_SUCCESS); 700 701 if (filename == NULL) { 702 #ifndef WIN32 703 filename = NS_SYSCONFDIR "/bind.keys"; 704 #else 705 static char buf[MAX_PATH]; 706 strlcpy(buf, isc_ntpaths_get(SYS_CONF_DIR), sizeof(buf)); 707 strlcat(buf, "\\bind.keys", sizeof(buf)); 708 filename = buf; 709 #endif 710 } 711 712 if (trust_anchor == NULL) { 713 trust_anchor = isc_mem_strdup(mctx, "."); 714 if (trust_anchor == NULL) 715 fatal("out of memory"); 716 } 717 718 if (dlv_anchor == NULL) { 719 dlv_anchor = isc_mem_strdup(mctx, "dlv.isc.org"); 720 if (dlv_anchor == NULL) 721 fatal("out of memory"); 722 } 723 724 CHECK(convert_name(&afn, &anchor_name, trust_anchor)); 725 CHECK(convert_name(&dfn, &dlv_name, dlv_anchor)); 726 727 CHECK(cfg_parser_create(mctx, dns_lctx, &parser)); 728 729 if (access(filename, R_OK) != 0) { 730 if (anchorfile != NULL) 731 fatal("Unable to read key file '%s'", anchorfile); 732 } else { 733 result = cfg_parse_file(parser, filename, 734 &cfg_type_bindkeys, &bindkeys); 735 if (result != ISC_R_SUCCESS) 736 if (anchorfile != NULL) 737 fatal("Unable to load keys from '%s'", 738 anchorfile); 739 } 740 741 if (bindkeys == NULL) { 742 isc_buffer_t b; 743 744 isc_buffer_init(&b, anchortext, sizeof(anchortext) - 1); 745 isc_buffer_add(&b, sizeof(anchortext) - 1); 746 result = cfg_parse_buffer(parser, &b, &cfg_type_bindkeys, 747 &bindkeys); 748 if (result != ISC_R_SUCCESS) 749 fatal("Unable to parse built-in keys"); 750 } 751 752 INSIST(bindkeys != NULL); 753 cfg_map_get(bindkeys, "trusted-keys", &keys); 754 cfg_map_get(bindkeys, "managed-keys", &managed_keys); 755 756 if (keys != NULL) 757 CHECK(load_keys(keys, client)); 758 if (managed_keys != NULL) 759 CHECK(load_keys(managed_keys, client)); 760 result = ISC_R_SUCCESS; 761 762 if (trusted_keys == 0) 763 fatal("No trusted keys were loaded"); 764 765 if (dlv_validation) 766 dns_client_setdlv(client, dns_rdataclass_in, dlv_anchor); 767 768 cleanup: 769 if (result != ISC_R_SUCCESS) 770 delv_log(ISC_LOG_ERROR, "setup_dnsseckeys: %s", 771 isc_result_totext(result)); 772 return (result); 773 } 774 775 static isc_result_t 776 addserver(dns_client_t *client) { 777 struct addrinfo hints, *res, *cur; 778 int gai_error; 779 struct in_addr in4; 780 struct in6_addr in6; 781 isc_sockaddr_t *sa; 782 isc_sockaddrlist_t servers; 783 isc_uint32_t destport; 784 isc_result_t result; 785 dns_name_t *name = NULL; 786 787 result = parse_uint(&destport, port, 0xffff, "port"); 788 if (result != ISC_R_SUCCESS) 789 fatal("Couldn't parse port number"); 790 791 ISC_LIST_INIT(servers); 792 793 if (use_ipv4 && inet_pton(AF_INET, server, &in4) == 1) { 794 sa = isc_mem_get(mctx, sizeof(*sa)); 795 if (sa == NULL) 796 return (ISC_R_NOMEMORY); 797 ISC_LINK_INIT(sa, link); 798 isc_sockaddr_fromin(sa, &in4, destport); 799 ISC_LIST_APPEND(servers, sa, link); 800 } else if (use_ipv6 && inet_pton(AF_INET6, server, &in6) == 1) { 801 sa = isc_mem_get(mctx, sizeof(*sa)); 802 if (sa == NULL) 803 return (ISC_R_NOMEMORY); 804 ISC_LINK_INIT(sa, link); 805 isc_sockaddr_fromin6(sa, &in6, destport); 806 ISC_LIST_APPEND(servers, sa, link); 807 } else { 808 memset(&hints, 0, sizeof(hints)); 809 if (!use_ipv6) 810 hints.ai_family = AF_INET; 811 else if (!use_ipv4) 812 hints.ai_family = AF_INET6; 813 else 814 hints.ai_family = AF_UNSPEC; 815 hints.ai_socktype = SOCK_DGRAM; 816 hints.ai_protocol = IPPROTO_UDP; 817 gai_error = getaddrinfo(server, port, &hints, &res); 818 if (gai_error != 0) { 819 delv_log(ISC_LOG_ERROR, 820 "getaddrinfo failed: %s", 821 gai_strerror(gai_error)); 822 return (ISC_R_FAILURE); 823 } 824 825 result = ISC_R_SUCCESS; 826 for (cur = res; cur != NULL; cur = cur->ai_next) { 827 if (cur->ai_family != AF_INET && 828 cur->ai_family != AF_INET6) 829 continue; 830 sa = isc_mem_get(mctx, sizeof(*sa)); 831 if (sa == NULL) { 832 result = ISC_R_NOMEMORY; 833 break; 834 } 835 memset(sa, 0, sizeof(*sa)); 836 ISC_LINK_INIT(sa, link); 837 memmove(&sa->type, cur->ai_addr, cur->ai_addrlen); 838 sa->length = (unsigned int)cur->ai_addrlen; 839 ISC_LIST_APPEND(servers, sa, link); 840 } 841 freeaddrinfo(res); 842 CHECK(result); 843 } 844 845 846 CHECK(dns_client_setservers(client, dns_rdataclass_in, name, &servers)); 847 848 cleanup: 849 while (!ISC_LIST_EMPTY(servers)) { 850 sa = ISC_LIST_HEAD(servers); 851 ISC_LIST_UNLINK(servers, sa, link); 852 isc_mem_put(mctx, sa, sizeof(*sa)); 853 } 854 855 if (result != ISC_R_SUCCESS) 856 delv_log(ISC_LOG_ERROR, "addserver: %s", 857 isc_result_totext(result)); 858 859 return (result); 860 } 861 862 static isc_result_t 863 findserver(dns_client_t *client) { 864 isc_result_t result; 865 irs_resconf_t *resconf = NULL; 866 isc_sockaddrlist_t *nameservers; 867 isc_sockaddr_t *sa, *next; 868 isc_uint32_t destport; 869 870 result = parse_uint(&destport, port, 0xffff, "port"); 871 if (result != ISC_R_SUCCESS) 872 fatal("Couldn't parse port number"); 873 874 result = irs_resconf_load(mctx, "/etc/resolv.conf", &resconf); 875 if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) { 876 delv_log(ISC_LOG_ERROR, "irs_resconf_load: %s", 877 isc_result_totext(result)); 878 goto cleanup; 879 } 880 881 /* Get nameservers from resolv.conf */ 882 nameservers = irs_resconf_getnameservers(resconf); 883 for (sa = ISC_LIST_HEAD(*nameservers); sa != NULL; sa = next) { 884 next = ISC_LIST_NEXT(sa, link); 885 886 /* Set destination port */ 887 if (sa->type.sa.sa_family == AF_INET && use_ipv4) { 888 sa->type.sin.sin_port = htons(destport); 889 continue; 890 } 891 if (sa->type.sa.sa_family == AF_INET6 && use_ipv6) { 892 sa->type.sin6.sin6_port = htons(destport); 893 continue; 894 } 895 896 /* Incompatible protocol family */ 897 ISC_LIST_UNLINK(*nameservers, sa, link); 898 isc_mem_put(mctx, sa, sizeof(*sa)); 899 } 900 901 /* None found, use localhost */ 902 if (ISC_LIST_EMPTY(*nameservers)) { 903 if (use_ipv4) { 904 struct in_addr localhost; 905 localhost.s_addr = htonl(INADDR_LOOPBACK); 906 sa = isc_mem_get(mctx, sizeof(*sa)); 907 if (sa == NULL) { 908 result = ISC_R_NOMEMORY; 909 goto cleanup; 910 } 911 isc_sockaddr_fromin(sa, &localhost, destport); 912 913 ISC_LINK_INIT(sa, link); 914 ISC_LIST_APPEND(*nameservers, sa, link); 915 } 916 917 if (use_ipv6) { 918 sa = isc_mem_get(mctx, sizeof(*sa)); 919 if (sa == NULL) { 920 result = ISC_R_NOMEMORY; 921 goto cleanup; 922 } 923 isc_sockaddr_fromin6(sa, &in6addr_loopback, destport); 924 925 ISC_LINK_INIT(sa, link); 926 ISC_LIST_APPEND(*nameservers, sa, link); 927 } 928 } 929 930 result = dns_client_setservers(client, dns_rdataclass_in, NULL, 931 nameservers); 932 if (result != ISC_R_SUCCESS) 933 delv_log(ISC_LOG_ERROR, "dns_client_setservers: %s", 934 isc_result_totext(result)); 935 936 cleanup: 937 if (resconf != NULL) 938 irs_resconf_destroy(&resconf); 939 return (result); 940 } 941 942 static char * 943 next_token(char **stringp, const char *delim) { 944 char *res; 945 946 do { 947 res = strsep(stringp, delim); 948 if (res == NULL) 949 break; 950 } while (*res == '\0'); 951 return (res); 952 } 953 954 static isc_result_t 955 parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max, 956 const char *desc) { 957 isc_uint32_t n; 958 isc_result_t result = isc_parse_uint32(&n, value, 10); 959 if (result == ISC_R_SUCCESS && n > max) 960 result = ISC_R_RANGE; 961 if (result != ISC_R_SUCCESS) { 962 printf("invalid %s '%s': %s\n", desc, 963 value, isc_result_totext(result)); 964 return (result); 965 } 966 *uip = n; 967 return (ISC_R_SUCCESS); 968 } 969 970 static void 971 plus_option(char *option) { 972 isc_result_t result; 973 char option_store[256]; 974 char *cmd, *value, *ptr; 975 isc_boolean_t state = ISC_TRUE; 976 977 strncpy(option_store, option, sizeof(option_store)); 978 option_store[sizeof(option_store)-1]=0; 979 ptr = option_store; 980 cmd = next_token(&ptr,"="); 981 if (cmd == NULL) { 982 printf(";; Invalid option %s\n", option_store); 983 return; 984 } 985 value = ptr; 986 if (strncasecmp(cmd, "no", 2)==0) { 987 cmd += 2; 988 state = ISC_FALSE; 989 } 990 991 #define FULLCHECK(A) \ 992 do { \ 993 size_t _l = strlen(cmd); \ 994 if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \ 995 goto invalid_option; \ 996 } while (/*CONSTCOND*/0) 997 998 switch (cmd[0]) { 999 case 'a': /* all */ 1000 FULLCHECK("all"); 1001 showcomments = state; 1002 rrcomments = state; 1003 showtrust = state; 1004 break; 1005 case 'c': 1006 switch (cmd[1]) { 1007 case 'd': /* cdflag */ 1008 FULLCHECK("cdflag"); 1009 cdflag = state; 1010 break; 1011 case 'l': /* class */ 1012 FULLCHECK("class"); 1013 noclass = ISC_TF(!state); 1014 break; 1015 case 'o': /* comments */ 1016 FULLCHECK("comments"); 1017 showcomments = state; 1018 break; 1019 case 'r': /* crypto */ 1020 FULLCHECK("crypto"); 1021 nocrypto = ISC_TF(!state); 1022 break; 1023 default: 1024 goto invalid_option; 1025 } 1026 break; 1027 case 'd': 1028 switch (cmd[1]) { 1029 case 'l': /* dlv */ 1030 FULLCHECK("dlv"); 1031 if (state && no_sigs) 1032 break; 1033 dlv_validation = state; 1034 if (value != NULL) { 1035 dlv_anchor = isc_mem_strdup(mctx, value); 1036 if (dlv_anchor == NULL) 1037 fatal("out of memory"); 1038 } 1039 break; 1040 case 'n': /* dnssec */ 1041 FULLCHECK("dnssec"); 1042 showdnssec = state; 1043 break; 1044 default: 1045 goto invalid_option; 1046 } 1047 break; 1048 case 'm': 1049 switch (cmd[1]) { 1050 case 't': /* mtrace */ 1051 message_trace = state; 1052 if (state) 1053 resolve_trace = state; 1054 break; 1055 case 'u': /* multiline */ 1056 FULLCHECK("multiline"); 1057 multiline = state; 1058 break; 1059 default: 1060 goto invalid_option; 1061 } 1062 break; 1063 case 'r': 1064 switch (cmd[1]) { 1065 case 'o': /* root */ 1066 FULLCHECK("root"); 1067 if (state && no_sigs) 1068 break; 1069 root_validation = state; 1070 if (value != NULL) { 1071 trust_anchor = isc_mem_strdup(mctx, value); 1072 if (trust_anchor == NULL) 1073 fatal("out of memory"); 1074 } 1075 break; 1076 case 'r': /* rrcomments */ 1077 FULLCHECK("rrcomments"); 1078 rrcomments = state; 1079 break; 1080 case 't': /* rtrace */ 1081 FULLCHECK("rtrace"); 1082 resolve_trace = state; 1083 break; 1084 default: 1085 goto invalid_option; 1086 } 1087 break; 1088 case 's': 1089 switch (cmd[1]) { 1090 case 'h': /* short */ 1091 FULLCHECK("short"); 1092 short_form = state; 1093 if (short_form) { 1094 multiline = ISC_FALSE; 1095 showcomments = ISC_FALSE; 1096 showtrust = ISC_FALSE; 1097 showdnssec = ISC_FALSE; 1098 } 1099 break; 1100 case 'p': /* split */ 1101 FULLCHECK("split"); 1102 if (value != NULL && !state) 1103 goto invalid_option; 1104 if (!state) { 1105 splitwidth = 0; 1106 break; 1107 } else if (value == NULL) 1108 break; 1109 1110 result = parse_uint(&splitwidth, value, 1111 1023, "split"); 1112 if (splitwidth % 4 != 0) { 1113 splitwidth = ((splitwidth + 3) / 4) * 4; 1114 warn("split must be a multiple of 4; " 1115 "adjusting to %d", splitwidth); 1116 } 1117 /* 1118 * There is an adjustment done in the 1119 * totext_<rrtype>() functions which causes 1120 * splitwidth to shrink. This is okay when we're 1121 * using the default width but incorrect in this 1122 * case, so we correct for it 1123 */ 1124 if (splitwidth) 1125 splitwidth += 3; 1126 if (result != ISC_R_SUCCESS) 1127 fatal("Couldn't parse split"); 1128 break; 1129 default: 1130 goto invalid_option; 1131 } 1132 break; 1133 case 't': 1134 switch (cmd[1]) { 1135 case 'r': /* trust */ 1136 FULLCHECK("trust"); 1137 showtrust = state; 1138 break; 1139 case 't': /* ttl */ 1140 FULLCHECK("ttl"); 1141 nottl = ISC_TF(!state); 1142 break; 1143 default: 1144 goto invalid_option; 1145 } 1146 break; 1147 case 'v': /* vtrace */ 1148 FULLCHECK("vtrace"); 1149 validator_trace = state; 1150 if (state) 1151 resolve_trace = state; 1152 break; 1153 default: 1154 invalid_option: 1155 /* 1156 * We can also add a "need_value:" case here if we ever 1157 * add a plus-option that requires a specified value 1158 */ 1159 fprintf(stderr, "Invalid option: +%s\n", option); 1160 usage(); 1161 } 1162 return; 1163 } 1164 1165 /* 1166 * options: "46a:b:c:d:himp:q:t:vx:"; 1167 */ 1168 static const char *single_dash_opts = "46himv"; 1169 static isc_boolean_t 1170 dash_option(char *option, char *next, isc_boolean_t *open_type_class) { 1171 char opt, *value; 1172 isc_result_t result; 1173 isc_boolean_t value_from_next; 1174 isc_textregion_t tr; 1175 dns_rdatatype_t rdtype; 1176 dns_rdataclass_t rdclass; 1177 char textname[MAXNAME]; 1178 struct in_addr in4; 1179 struct in6_addr in6; 1180 in_port_t srcport; 1181 isc_uint32_t num; 1182 char *hash; 1183 1184 while (strpbrk(option, single_dash_opts) == &option[0]) { 1185 /* 1186 * Since the -[46himv] options do not take an argument, 1187 * account for them (in any number and/or combination) 1188 * if they appear as the first character(s) of a q-opt. 1189 */ 1190 opt = option[0]; 1191 switch (opt) { 1192 case '4': 1193 if (isc_net_probeipv4() != ISC_R_SUCCESS) 1194 fatal("IPv4 networking not available"); 1195 if (use_ipv6) { 1196 isc_net_disableipv6(); 1197 use_ipv6 = ISC_FALSE; 1198 } 1199 break; 1200 case '6': 1201 if (isc_net_probeipv6() != ISC_R_SUCCESS) 1202 fatal("IPv6 networking not available"); 1203 if (use_ipv4) { 1204 isc_net_disableipv4(); 1205 use_ipv4 = ISC_FALSE; 1206 } 1207 break; 1208 case 'h': 1209 usage(); 1210 exit(0); 1211 /* NOTREACHED */ 1212 case 'i': 1213 no_sigs = ISC_TRUE; 1214 dlv_validation = ISC_FALSE; 1215 root_validation = ISC_FALSE; 1216 break; 1217 case 'm': 1218 /* handled in preparse_args() */ 1219 break; 1220 case 'v': 1221 fputs("delv " VERSION "\n", stderr); 1222 exit(0); 1223 /* NOTREACHED */ 1224 default: 1225 INSIST(0); 1226 } 1227 if (strlen(option) > 1U) 1228 option = &option[1]; 1229 else 1230 return (ISC_FALSE); 1231 } 1232 opt = option[0]; 1233 if (strlen(option) > 1U) { 1234 value_from_next = ISC_FALSE; 1235 value = &option[1]; 1236 } else { 1237 value_from_next = ISC_TRUE; 1238 value = next; 1239 } 1240 if (value == NULL) 1241 goto invalid_option; 1242 switch (opt) { 1243 case 'a': 1244 anchorfile = isc_mem_strdup(mctx, value); 1245 if (anchorfile == NULL) 1246 fatal("out of memory"); 1247 return (value_from_next); 1248 case 'b': 1249 hash = strchr(value, '#'); 1250 if (hash != NULL) { 1251 result = parse_uint(&num, hash + 1, 0xffff, "port"); 1252 if (result != ISC_R_SUCCESS) 1253 fatal("Couldn't parse port number"); 1254 srcport = num; 1255 *hash = '\0'; 1256 } else 1257 srcport = 0; 1258 1259 if (inet_pton(AF_INET, value, &in4) == 1) { 1260 if (srcaddr4 != NULL) 1261 fatal("Only one local address per family " 1262 "can be specified\n"); 1263 isc_sockaddr_fromin(&a4, &in4, srcport); 1264 srcaddr4 = &a4; 1265 } else if (inet_pton(AF_INET6, value, &in6) == 1) { 1266 if (srcaddr6 != NULL) 1267 fatal("Only one local address per family " 1268 "can be specified\n"); 1269 isc_sockaddr_fromin6(&a6, &in6, srcport); 1270 srcaddr6 = &a6; 1271 } else { 1272 if (hash != NULL) 1273 *hash = '#'; 1274 fatal("Invalid address %s", value); 1275 } 1276 if (hash != NULL) 1277 *hash = '#'; 1278 return (value_from_next); 1279 case 'c': 1280 if (classset) 1281 warn("extra query class"); 1282 1283 *open_type_class = ISC_FALSE; 1284 tr.base = value; 1285 tr.length = strlen(value); 1286 result = dns_rdataclass_fromtext(&rdclass, 1287 (isc_textregion_t *)&tr); 1288 if (result == ISC_R_SUCCESS) 1289 classset = ISC_TRUE; 1290 else if (rdclass != dns_rdataclass_in) 1291 warn("ignoring non-IN query class"); 1292 else 1293 warn("ignoring invalid class"); 1294 return (value_from_next); 1295 case 'd': 1296 result = parse_uint(&num, value, 99, "debug level"); 1297 if (result != ISC_R_SUCCESS) 1298 fatal("Couldn't parse debug level"); 1299 loglevel = num; 1300 return (value_from_next); 1301 case 'p': 1302 port = value; 1303 return (value_from_next); 1304 case 'q': 1305 if (curqname != NULL) { 1306 warn("extra query name"); 1307 isc_mem_free(mctx, curqname); 1308 } 1309 curqname = isc_mem_strdup(mctx, value); 1310 if (curqname == NULL) 1311 fatal("out of memory"); 1312 return (value_from_next); 1313 case 't': 1314 *open_type_class = ISC_FALSE; 1315 tr.base = value; 1316 tr.length = strlen(value); 1317 result = dns_rdatatype_fromtext(&rdtype, 1318 (isc_textregion_t *)&tr); 1319 if (result == ISC_R_SUCCESS) { 1320 if (typeset) 1321 warn("extra query type"); 1322 if (rdtype == dns_rdatatype_ixfr || 1323 rdtype == dns_rdatatype_axfr) 1324 fatal("Transfer not supported"); 1325 qtype = rdtype; 1326 typeset = ISC_TRUE; 1327 } else 1328 warn("ignoring invalid type"); 1329 return (value_from_next); 1330 case 'x': 1331 result = get_reverse(textname, sizeof(textname), value, 1332 ISC_FALSE); 1333 if (result == ISC_R_SUCCESS) { 1334 if (curqname != NULL) { 1335 isc_mem_free(mctx, curqname); 1336 warn("extra query name"); 1337 } 1338 curqname = isc_mem_strdup(mctx, textname); 1339 if (curqname == NULL) 1340 fatal("out of memory"); 1341 if (typeset) 1342 warn("extra query type"); 1343 qtype = dns_rdatatype_ptr; 1344 typeset = ISC_TRUE; 1345 } else { 1346 fprintf(stderr, "Invalid IP address %s\n", value); 1347 exit(1); 1348 } 1349 return (value_from_next); 1350 invalid_option: 1351 default: 1352 fprintf(stderr, "Invalid option: -%s\n", option); 1353 usage(); 1354 } 1355 /* NOTREACHED */ 1356 return (ISC_FALSE); 1357 } 1358 1359 /* 1360 * Check for -m first to determine whether to enable 1361 * memory debugging when setting up the memory context. 1362 */ 1363 static void 1364 preparse_args(int argc, char **argv) { 1365 char *option; 1366 1367 for (argc--, argv++; argc > 0; argc--, argv++) { 1368 if (argv[0][0] != '-') 1369 continue; 1370 option = &argv[0][1]; 1371 while (strpbrk(option, single_dash_opts) == &option[0]) { 1372 if (option[0] == 'm') { 1373 isc_mem_debugging = ISC_MEM_DEBUGTRACE | 1374 ISC_MEM_DEBUGRECORD; 1375 return; 1376 } 1377 option = &option[1]; 1378 } 1379 } 1380 } 1381 1382 /* 1383 * Argument parsing is based on dig, but simplified: only one 1384 * QNAME/QCLASS/QTYPE tuple can be specified, and options have 1385 * been removed that aren't applicable to delv. The interface 1386 * should be familiar to dig users, however. 1387 */ 1388 static void 1389 parse_args(int argc, char **argv) { 1390 isc_result_t result; 1391 isc_textregion_t tr; 1392 dns_rdatatype_t rdtype; 1393 dns_rdataclass_t rdclass; 1394 isc_boolean_t open_type_class = ISC_TRUE; 1395 1396 for (; argc > 0; argc--, argv++) { 1397 if (argv[0][0] == '@') { 1398 server = &argv[0][1]; 1399 } else if (argv[0][0] == '+') { 1400 plus_option(&argv[0][1]); 1401 } else if (argv[0][0] == '-') { 1402 if (argc <= 1) { 1403 if (dash_option(&argv[0][1], NULL, 1404 &open_type_class)) 1405 { 1406 argc--; 1407 argv++; 1408 } 1409 } else { 1410 if (dash_option(&argv[0][1], argv[1], 1411 &open_type_class)) 1412 { 1413 argc--; 1414 argv++; 1415 } 1416 } 1417 } else { 1418 /* 1419 * Anything which isn't an option 1420 */ 1421 if (open_type_class) { 1422 tr.base = argv[0]; 1423 tr.length = strlen(argv[0]); 1424 result = dns_rdatatype_fromtext(&rdtype, 1425 (isc_textregion_t *)&tr); 1426 if (result == ISC_R_SUCCESS) { 1427 if (typeset) 1428 warn("extra query type"); 1429 if (rdtype == dns_rdatatype_ixfr || 1430 rdtype == dns_rdatatype_axfr) 1431 fatal("Transfer not supported"); 1432 qtype = rdtype; 1433 typeset = ISC_TRUE; 1434 continue; 1435 } 1436 result = dns_rdataclass_fromtext(&rdclass, 1437 (isc_textregion_t *)&tr); 1438 if (result == ISC_R_SUCCESS) { 1439 if (classset) 1440 warn("extra query class"); 1441 else if (rdclass != dns_rdataclass_in) 1442 warn("ignoring non-IN " 1443 "query class"); 1444 continue; 1445 } 1446 } 1447 1448 if (curqname == NULL) { 1449 curqname = isc_mem_strdup(mctx, argv[0]); 1450 if (curqname == NULL) 1451 fatal("out of memory"); 1452 } 1453 } 1454 } 1455 1456 /* 1457 * If no qname or qtype specified, search for root/NS 1458 * If no qtype specified, use A 1459 */ 1460 if (!typeset) 1461 qtype = dns_rdatatype_a; 1462 1463 if (curqname == NULL) { 1464 qname = isc_mem_strdup(mctx, "."); 1465 if (qname == NULL) 1466 fatal("out of memory"); 1467 1468 if (!typeset) 1469 qtype = dns_rdatatype_ns; 1470 } else 1471 qname = curqname; 1472 } 1473 1474 static isc_result_t 1475 append_str(const char *text, int len, char **p, char *end) { 1476 if (len > end - *p) 1477 return (ISC_R_NOSPACE); 1478 memmove(*p, text, len); 1479 *p += len; 1480 return (ISC_R_SUCCESS); 1481 } 1482 1483 static isc_result_t 1484 reverse_octets(const char *in, char **p, char *end) { 1485 char *dot = strchr(in, '.'); 1486 int len; 1487 if (dot != NULL) { 1488 isc_result_t result; 1489 result = reverse_octets(dot + 1, p, end); 1490 if (result != ISC_R_SUCCESS) 1491 return (result); 1492 result = append_str(".", 1, p, end); 1493 if (result != ISC_R_SUCCESS) 1494 return (result); 1495 len = (int)(dot - in); 1496 } else 1497 len = strlen(in); 1498 return (append_str(in, len, p, end)); 1499 } 1500 1501 static isc_result_t 1502 get_reverse(char *reverse, size_t len, char *value, isc_boolean_t strict) { 1503 int r; 1504 isc_result_t result; 1505 isc_netaddr_t addr; 1506 1507 addr.family = AF_INET6; 1508 r = inet_pton(AF_INET6, value, &addr.type.in6); 1509 if (r > 0) { 1510 /* This is a valid IPv6 address. */ 1511 dns_fixedname_t fname; 1512 dns_name_t *name; 1513 unsigned int options = 0; 1514 1515 dns_fixedname_init(&fname); 1516 name = dns_fixedname_name(&fname); 1517 result = dns_byaddr_createptrname2(&addr, options, name); 1518 if (result != ISC_R_SUCCESS) 1519 return (result); 1520 dns_name_format(name, reverse, (unsigned int)len); 1521 return (ISC_R_SUCCESS); 1522 } else { 1523 /* 1524 * Not a valid IPv6 address. Assume IPv4. 1525 * If 'strict' is not set, construct the 1526 * in-addr.arpa name by blindly reversing 1527 * octets whether or not they look like integers, 1528 * so that this can be used for RFC2317 names 1529 * and such. 1530 */ 1531 char *p = reverse; 1532 char *end = reverse + len; 1533 if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1) 1534 return (DNS_R_BADDOTTEDQUAD); 1535 result = reverse_octets(value, &p, end); 1536 if (result != ISC_R_SUCCESS) 1537 return (result); 1538 result = append_str(".in-addr.arpa.", 15, &p, end); 1539 if (result != ISC_R_SUCCESS) 1540 return (result); 1541 return (ISC_R_SUCCESS); 1542 } 1543 } 1544 1545 int 1546 main(int argc, char *argv[]) { 1547 dns_client_t *client = NULL; 1548 isc_result_t result; 1549 dns_fixedname_t qfn; 1550 dns_name_t *query_name, *response_name; 1551 dns_rdataset_t *rdataset; 1552 dns_namelist_t namelist; 1553 unsigned int resopt, clopt; 1554 isc_appctx_t *actx = NULL; 1555 isc_taskmgr_t *taskmgr = NULL; 1556 isc_socketmgr_t *socketmgr = NULL; 1557 isc_timermgr_t *timermgr = NULL; 1558 dns_master_style_t *style = NULL; 1559 #ifndef WIN32 1560 struct sigaction sa; 1561 #endif 1562 1563 preparse_args(argc, argv); 1564 progname = argv[0]; 1565 1566 argc--; 1567 argv++; 1568 1569 isc_lib_register(); 1570 result = dns_lib_init(); 1571 if (result != ISC_R_SUCCESS) 1572 fatal("dns_lib_init failed: %d", result); 1573 1574 result = isc_mem_create(0, 0, &mctx); 1575 if (result != ISC_R_SUCCESS) 1576 fatal("failed to create mctx"); 1577 1578 CHECK(isc_appctx_create(mctx, &actx)); 1579 CHECK(isc_taskmgr_createinctx(mctx, actx, 1, 0, &taskmgr)); 1580 CHECK(isc_socketmgr_createinctx(mctx, actx, &socketmgr)); 1581 CHECK(isc_timermgr_createinctx(mctx, actx, &timermgr)); 1582 1583 parse_args(argc, argv); 1584 1585 CHECK(setup_style(&style)); 1586 1587 setup_logging(stderr); 1588 1589 CHECK(isc_app_ctxstart(actx)); 1590 1591 #ifndef WIN32 1592 /* Unblock SIGINT if it's been blocked by isc_app_ctxstart() */ 1593 memset(&sa, 0, sizeof(sa)); 1594 sa.sa_handler = SIG_DFL; 1595 if (sigfillset(&sa.sa_mask) != 0 || sigaction(SIGINT, &sa, NULL) < 0) 1596 fatal("Couldn't set up signal handler"); 1597 #endif 1598 1599 /* Create client */ 1600 clopt = DNS_CLIENTCREATEOPT_USECACHE; 1601 result = dns_client_createx2(mctx, actx, taskmgr, socketmgr, timermgr, 1602 clopt, &client, srcaddr4, srcaddr6); 1603 if (result != ISC_R_SUCCESS) { 1604 delv_log(ISC_LOG_ERROR, "dns_client_create: %s", 1605 isc_result_totext(result)); 1606 goto cleanup; 1607 } 1608 1609 /* Set the nameserver */ 1610 if (server != NULL) 1611 addserver(client); 1612 else 1613 findserver(client); 1614 1615 CHECK(setup_dnsseckeys(client)); 1616 1617 /* Construct QNAME */ 1618 CHECK(convert_name(&qfn, &query_name, qname)); 1619 1620 /* Set up resolution options */ 1621 resopt = DNS_CLIENTRESOPT_ALLOWRUN | DNS_CLIENTRESOPT_NOCDFLAG; 1622 if (no_sigs) 1623 resopt |= DNS_CLIENTRESOPT_NODNSSEC; 1624 if (!root_validation && !dlv_validation) 1625 resopt |= DNS_CLIENTRESOPT_NOVALIDATE; 1626 if (cdflag) 1627 resopt &= ~DNS_CLIENTRESOPT_NOCDFLAG; 1628 1629 /* Perform resolution */ 1630 ISC_LIST_INIT(namelist); 1631 result = dns_client_resolve(client, query_name, dns_rdataclass_in, 1632 qtype, resopt, &namelist); 1633 if (result != ISC_R_SUCCESS) 1634 delv_log(ISC_LOG_ERROR, "resolution failed: %s", 1635 isc_result_totext(result)); 1636 1637 for (response_name = ISC_LIST_HEAD(namelist); 1638 response_name != NULL; 1639 response_name = ISC_LIST_NEXT(response_name, link)) { 1640 for (rdataset = ISC_LIST_HEAD(response_name->list); 1641 rdataset != NULL; 1642 rdataset = ISC_LIST_NEXT(rdataset, link)) { 1643 result = printdata(rdataset, response_name, style); 1644 if (result != ISC_R_SUCCESS) 1645 delv_log(ISC_LOG_ERROR, "print data failed"); 1646 } 1647 } 1648 1649 dns_client_freeresanswer(client, &namelist); 1650 1651 cleanup: 1652 if (dlv_anchor != NULL) 1653 isc_mem_free(mctx, dlv_anchor); 1654 if (trust_anchor != NULL) 1655 isc_mem_free(mctx, trust_anchor); 1656 if (anchorfile != NULL) 1657 isc_mem_free(mctx, anchorfile); 1658 if (qname != NULL) 1659 isc_mem_free(mctx, qname); 1660 if (style != NULL) 1661 dns_master_styledestroy(&style, mctx); 1662 if (client != NULL) 1663 dns_client_destroy(&client); 1664 if (taskmgr != NULL) 1665 isc_taskmgr_destroy(&taskmgr); 1666 if (timermgr != NULL) 1667 isc_timermgr_destroy(&timermgr); 1668 if (socketmgr != NULL) 1669 isc_socketmgr_destroy(&socketmgr); 1670 if (actx != NULL) 1671 isc_appctx_destroy(&actx); 1672 if (lctx != NULL) 1673 isc_log_destroy(&lctx); 1674 isc_mem_detach(&mctx); 1675 1676 dns_lib_shutdown(); 1677 1678 return (0); 1679 } 1680