nslookup.c revision 225361
1135446Strhodes/* 2225361Sdougb * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") 3135446Strhodes * Copyright (C) 2000-2003 Internet Software Consortium. 4135446Strhodes * 5174187Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6135446Strhodes * purpose with or without fee is hereby granted, provided that the above 7135446Strhodes * copyright notice and this permission notice appear in all copies. 8135446Strhodes * 9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11135446Strhodes * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15135446Strhodes * PERFORMANCE OF THIS SOFTWARE. 16135446Strhodes */ 17135446Strhodes 18225361Sdougb/* $Id: nslookup.c,v 1.127.38.2 2011-02-28 01:19:58 tbox Exp $ */ 19135446Strhodes 20135446Strhodes#include <config.h> 21135446Strhodes 22135446Strhodes#include <stdlib.h> 23135446Strhodes 24135446Strhodes#include <isc/app.h> 25135446Strhodes#include <isc/buffer.h> 26135446Strhodes#include <isc/commandline.h> 27135446Strhodes#include <isc/event.h> 28135446Strhodes#include <isc/parseint.h> 29193149Sdougb#include <isc/print.h> 30135446Strhodes#include <isc/string.h> 31135446Strhodes#include <isc/timer.h> 32135446Strhodes#include <isc/util.h> 33135446Strhodes#include <isc/task.h> 34135446Strhodes#include <isc/netaddr.h> 35135446Strhodes 36135446Strhodes#include <dns/message.h> 37135446Strhodes#include <dns/name.h> 38135446Strhodes#include <dns/fixedname.h> 39135446Strhodes#include <dns/rdata.h> 40135446Strhodes#include <dns/rdataclass.h> 41135446Strhodes#include <dns/rdataset.h> 42135446Strhodes#include <dns/rdatastruct.h> 43135446Strhodes#include <dns/rdatatype.h> 44135446Strhodes#include <dns/byaddr.h> 45135446Strhodes 46135446Strhodes#include <dig/dig.h> 47135446Strhodes 48135446Strhodesstatic isc_boolean_t short_form = ISC_TRUE, 49135446Strhodes tcpmode = ISC_FALSE, 50135446Strhodes identify = ISC_FALSE, stats = ISC_TRUE, 51135446Strhodes comments = ISC_TRUE, section_question = ISC_TRUE, 52135446Strhodes section_answer = ISC_TRUE, section_authority = ISC_TRUE, 53135446Strhodes section_additional = ISC_TRUE, recurse = ISC_TRUE, 54170222Sdougb aaonly = ISC_FALSE, nofail = ISC_TRUE; 55170222Sdougb 56135446Strhodesstatic isc_boolean_t in_use = ISC_FALSE; 57135446Strhodesstatic char defclass[MXRD] = "IN"; 58135446Strhodesstatic char deftype[MXRD] = "A"; 59135446Strhodesstatic isc_event_t *global_event = NULL; 60135446Strhodes 61135446Strhodesstatic char domainopt[DNS_NAME_MAXTEXT]; 62135446Strhodes 63135446Strhodesstatic const char *rcodetext[] = { 64135446Strhodes "NOERROR", 65135446Strhodes "FORMERR", 66135446Strhodes "SERVFAIL", 67135446Strhodes "NXDOMAIN", 68135446Strhodes "NOTIMP", 69135446Strhodes "REFUSED", 70135446Strhodes "YXDOMAIN", 71135446Strhodes "YXRRSET", 72135446Strhodes "NXRRSET", 73135446Strhodes "NOTAUTH", 74135446Strhodes "NOTZONE", 75135446Strhodes "RESERVED11", 76135446Strhodes "RESERVED12", 77135446Strhodes "RESERVED13", 78135446Strhodes "RESERVED14", 79135446Strhodes "RESERVED15", 80135446Strhodes "BADVERS" 81135446Strhodes}; 82135446Strhodes 83135446Strhodesstatic const char *rtypetext[] = { 84135446Strhodes "rtype_0 = ", /* 0 */ 85135446Strhodes "internet address = ", /* 1 */ 86135446Strhodes "nameserver = ", /* 2 */ 87135446Strhodes "md = ", /* 3 */ 88135446Strhodes "mf = ", /* 4 */ 89135446Strhodes "canonical name = ", /* 5 */ 90135446Strhodes "soa = ", /* 6 */ 91135446Strhodes "mb = ", /* 7 */ 92135446Strhodes "mg = ", /* 8 */ 93135446Strhodes "mr = ", /* 9 */ 94135446Strhodes "rtype_10 = ", /* 10 */ 95135446Strhodes "protocol = ", /* 11 */ 96135446Strhodes "name = ", /* 12 */ 97135446Strhodes "hinfo = ", /* 13 */ 98135446Strhodes "minfo = ", /* 14 */ 99135446Strhodes "mail exchanger = ", /* 15 */ 100135446Strhodes "text = ", /* 16 */ 101135446Strhodes "rp = ", /* 17 */ 102135446Strhodes "afsdb = ", /* 18 */ 103135446Strhodes "x25 address = ", /* 19 */ 104135446Strhodes "isdn address = ", /* 20 */ 105135446Strhodes "rt = ", /* 21 */ 106135446Strhodes "nsap = ", /* 22 */ 107135446Strhodes "nsap_ptr = ", /* 23 */ 108135446Strhodes "signature = ", /* 24 */ 109135446Strhodes "key = ", /* 25 */ 110135446Strhodes "px = ", /* 26 */ 111135446Strhodes "gpos = ", /* 27 */ 112135446Strhodes "has AAAA address ", /* 28 */ 113135446Strhodes "loc = ", /* 29 */ 114135446Strhodes "next = ", /* 30 */ 115135446Strhodes "rtype_31 = ", /* 31 */ 116135446Strhodes "rtype_32 = ", /* 32 */ 117135446Strhodes "service = ", /* 33 */ 118135446Strhodes "rtype_34 = ", /* 34 */ 119135446Strhodes "naptr = ", /* 35 */ 120135446Strhodes "kx = ", /* 36 */ 121135446Strhodes "cert = ", /* 37 */ 122135446Strhodes "v6 address = ", /* 38 */ 123135446Strhodes "dname = ", /* 39 */ 124135446Strhodes "rtype_40 = ", /* 40 */ 125135446Strhodes "optional = " /* 41 */ 126135446Strhodes}; 127135446Strhodes 128135446Strhodes#define N_KNOWN_RRTYPES (sizeof(rtypetext) / sizeof(rtypetext[0])) 129135446Strhodes 130135446Strhodesstatic void flush_lookup_list(void); 131135446Strhodesstatic void getinput(isc_task_t *task, isc_event_t *event); 132135446Strhodes 133193149Sdougbstatic char * 134193149Sdougbrcode_totext(dns_rcode_t rcode) 135193149Sdougb{ 136193149Sdougb static char buf[sizeof("?65535")]; 137193149Sdougb union { 138193149Sdougb const char *consttext; 139193149Sdougb char *deconsttext; 140193149Sdougb } totext; 141193149Sdougb 142193149Sdougb if (rcode >= (sizeof(rcodetext)/sizeof(rcodetext[0]))) { 143193149Sdougb snprintf(buf, sizeof(buf), "?%u", rcode); 144193149Sdougb totext.deconsttext = buf; 145193149Sdougb } else 146193149Sdougb totext.consttext = rcodetext[rcode]; 147193149Sdougb return totext.deconsttext; 148193149Sdougb} 149193149Sdougb 150135446Strhodesvoid 151135446Strhodesdighost_shutdown(void) { 152135446Strhodes isc_event_t *event = global_event; 153135446Strhodes 154135446Strhodes flush_lookup_list(); 155135446Strhodes debug("dighost_shutdown()"); 156135446Strhodes 157135446Strhodes if (!in_use) { 158135446Strhodes isc_app_shutdown(); 159135446Strhodes return; 160135446Strhodes } 161135446Strhodes 162135446Strhodes isc_task_send(global_task, &event); 163135446Strhodes} 164135446Strhodes 165135446Strhodesstatic void 166135446Strhodesprintsoa(dns_rdata_t *rdata) { 167135446Strhodes dns_rdata_soa_t soa; 168135446Strhodes isc_result_t result; 169135446Strhodes char namebuf[DNS_NAME_FORMATSIZE]; 170135446Strhodes 171135446Strhodes result = dns_rdata_tostruct(rdata, &soa, NULL); 172135446Strhodes check_result(result, "dns_rdata_tostruct"); 173135446Strhodes 174135446Strhodes dns_name_format(&soa.origin, namebuf, sizeof(namebuf)); 175135446Strhodes printf("\torigin = %s\n", namebuf); 176135446Strhodes dns_name_format(&soa.contact, namebuf, sizeof(namebuf)); 177135446Strhodes printf("\tmail addr = %s\n", namebuf); 178135446Strhodes printf("\tserial = %u\n", soa.serial); 179135446Strhodes printf("\trefresh = %u\n", soa.refresh); 180135446Strhodes printf("\tretry = %u\n", soa.retry); 181135446Strhodes printf("\texpire = %u\n", soa.expire); 182135446Strhodes printf("\tminimum = %u\n", soa.minimum); 183135446Strhodes dns_rdata_freestruct(&soa); 184135446Strhodes} 185135446Strhodes 186135446Strhodesstatic void 187135446Strhodesprinta(dns_rdata_t *rdata) { 188135446Strhodes isc_result_t result; 189135446Strhodes char text[sizeof("255.255.255.255")]; 190135446Strhodes isc_buffer_t b; 191135446Strhodes 192135446Strhodes isc_buffer_init(&b, text, sizeof(text)); 193135446Strhodes result = dns_rdata_totext(rdata, NULL, &b); 194135446Strhodes check_result(result, "dns_rdata_totext"); 195135446Strhodes printf("Address: %.*s\n", (int)isc_buffer_usedlength(&b), 196135446Strhodes (char *)isc_buffer_base(&b)); 197135446Strhodes} 198135446Strhodes#ifdef DIG_SIGCHASE 199135446Strhodes/* Just for compatibility : not use in host program */ 200135446Strhodesisc_result_t 201135446Strhodesprintrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset, 202135446Strhodes isc_buffer_t *target) 203135446Strhodes{ 204135446Strhodes UNUSED(owner_name); 205135446Strhodes UNUSED(rdataset); 206135446Strhodes UNUSED(target); 207135446Strhodes return(ISC_FALSE); 208135446Strhodes} 209135446Strhodes#endif 210135446Strhodesstatic void 211135446Strhodesprintrdata(dns_rdata_t *rdata) { 212135446Strhodes isc_result_t result; 213135446Strhodes isc_buffer_t *b = NULL; 214135446Strhodes unsigned int size = 1024; 215135446Strhodes isc_boolean_t done = ISC_FALSE; 216135446Strhodes 217135446Strhodes if (rdata->type < N_KNOWN_RRTYPES) 218135446Strhodes printf("%s", rtypetext[rdata->type]); 219135446Strhodes else 220135446Strhodes printf("rdata_%d = ", rdata->type); 221135446Strhodes 222135446Strhodes while (!done) { 223135446Strhodes result = isc_buffer_allocate(mctx, &b, size); 224135446Strhodes if (result != ISC_R_SUCCESS) 225135446Strhodes check_result(result, "isc_buffer_allocate"); 226135446Strhodes result = dns_rdata_totext(rdata, NULL, b); 227135446Strhodes if (result == ISC_R_SUCCESS) { 228135446Strhodes printf("%.*s\n", (int)isc_buffer_usedlength(b), 229135446Strhodes (char *)isc_buffer_base(b)); 230135446Strhodes done = ISC_TRUE; 231135446Strhodes } else if (result != ISC_R_NOSPACE) 232135446Strhodes check_result(result, "dns_rdata_totext"); 233135446Strhodes isc_buffer_free(&b); 234135446Strhodes size *= 2; 235135446Strhodes } 236135446Strhodes} 237135446Strhodes 238135446Strhodesstatic isc_result_t 239135446Strhodesprintsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers, 240135446Strhodes dns_section_t section) { 241135446Strhodes isc_result_t result, loopresult; 242135446Strhodes dns_name_t *name; 243135446Strhodes dns_rdataset_t *rdataset = NULL; 244135446Strhodes dns_rdata_t rdata = DNS_RDATA_INIT; 245135446Strhodes char namebuf[DNS_NAME_FORMATSIZE]; 246135446Strhodes 247135446Strhodes UNUSED(query); 248135446Strhodes UNUSED(headers); 249135446Strhodes 250135446Strhodes debug("printsection()"); 251135446Strhodes 252135446Strhodes result = dns_message_firstname(msg, section); 253135446Strhodes if (result == ISC_R_NOMORE) 254135446Strhodes return (ISC_R_SUCCESS); 255135446Strhodes else if (result != ISC_R_SUCCESS) 256135446Strhodes return (result); 257135446Strhodes for (;;) { 258135446Strhodes name = NULL; 259135446Strhodes dns_message_currentname(msg, section, 260135446Strhodes &name); 261135446Strhodes for (rdataset = ISC_LIST_HEAD(name->list); 262135446Strhodes rdataset != NULL; 263135446Strhodes rdataset = ISC_LIST_NEXT(rdataset, link)) { 264135446Strhodes loopresult = dns_rdataset_first(rdataset); 265135446Strhodes while (loopresult == ISC_R_SUCCESS) { 266135446Strhodes dns_rdataset_current(rdataset, &rdata); 267135446Strhodes switch (rdata.type) { 268135446Strhodes case dns_rdatatype_a: 269135446Strhodes if (section != DNS_SECTION_ANSWER) 270135446Strhodes goto def_short_section; 271135446Strhodes dns_name_format(name, namebuf, 272135446Strhodes sizeof(namebuf)); 273135446Strhodes printf("Name:\t%s\n", namebuf); 274135446Strhodes printa(&rdata); 275135446Strhodes break; 276135446Strhodes case dns_rdatatype_soa: 277135446Strhodes dns_name_format(name, namebuf, 278135446Strhodes sizeof(namebuf)); 279135446Strhodes printf("%s\n", namebuf); 280135446Strhodes printsoa(&rdata); 281135446Strhodes break; 282135446Strhodes default: 283135446Strhodes def_short_section: 284135446Strhodes dns_name_format(name, namebuf, 285135446Strhodes sizeof(namebuf)); 286135446Strhodes printf("%s\t", namebuf); 287135446Strhodes printrdata(&rdata); 288135446Strhodes break; 289135446Strhodes } 290135446Strhodes dns_rdata_reset(&rdata); 291135446Strhodes loopresult = dns_rdataset_next(rdataset); 292135446Strhodes } 293135446Strhodes } 294135446Strhodes result = dns_message_nextname(msg, section); 295135446Strhodes if (result == ISC_R_NOMORE) 296135446Strhodes break; 297135446Strhodes else if (result != ISC_R_SUCCESS) { 298135446Strhodes return (result); 299135446Strhodes } 300135446Strhodes } 301135446Strhodes return (ISC_R_SUCCESS); 302135446Strhodes} 303135446Strhodes 304135446Strhodesstatic isc_result_t 305135446Strhodesdetailsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers, 306135446Strhodes dns_section_t section) { 307135446Strhodes isc_result_t result, loopresult; 308135446Strhodes dns_name_t *name; 309135446Strhodes dns_rdataset_t *rdataset = NULL; 310135446Strhodes dns_rdata_t rdata = DNS_RDATA_INIT; 311135446Strhodes char namebuf[DNS_NAME_FORMATSIZE]; 312135446Strhodes 313135446Strhodes UNUSED(query); 314135446Strhodes 315135446Strhodes debug("detailsection()"); 316135446Strhodes 317135446Strhodes if (headers) { 318135446Strhodes switch (section) { 319135446Strhodes case DNS_SECTION_QUESTION: 320135446Strhodes puts(" QUESTIONS:"); 321135446Strhodes break; 322135446Strhodes case DNS_SECTION_ANSWER: 323135446Strhodes puts(" ANSWERS:"); 324135446Strhodes break; 325135446Strhodes case DNS_SECTION_AUTHORITY: 326135446Strhodes puts(" AUTHORITY RECORDS:"); 327135446Strhodes break; 328135446Strhodes case DNS_SECTION_ADDITIONAL: 329135446Strhodes puts(" ADDITIONAL RECORDS:"); 330135446Strhodes break; 331135446Strhodes } 332135446Strhodes } 333135446Strhodes 334135446Strhodes result = dns_message_firstname(msg, section); 335135446Strhodes if (result == ISC_R_NOMORE) 336135446Strhodes return (ISC_R_SUCCESS); 337135446Strhodes else if (result != ISC_R_SUCCESS) 338135446Strhodes return (result); 339135446Strhodes for (;;) { 340135446Strhodes name = NULL; 341135446Strhodes dns_message_currentname(msg, section, 342135446Strhodes &name); 343135446Strhodes for (rdataset = ISC_LIST_HEAD(name->list); 344135446Strhodes rdataset != NULL; 345135446Strhodes rdataset = ISC_LIST_NEXT(rdataset, link)) { 346135446Strhodes if (section == DNS_SECTION_QUESTION) { 347135446Strhodes dns_name_format(name, namebuf, 348135446Strhodes sizeof(namebuf)); 349135446Strhodes printf("\t%s, ", namebuf); 350135446Strhodes dns_rdatatype_format(rdataset->type, 351135446Strhodes namebuf, 352135446Strhodes sizeof(namebuf)); 353135446Strhodes printf("type = %s, ", namebuf); 354135446Strhodes dns_rdataclass_format(rdataset->rdclass, 355135446Strhodes namebuf, 356135446Strhodes sizeof(namebuf)); 357135446Strhodes printf("class = %s\n", namebuf); 358135446Strhodes } 359135446Strhodes loopresult = dns_rdataset_first(rdataset); 360135446Strhodes while (loopresult == ISC_R_SUCCESS) { 361135446Strhodes dns_rdataset_current(rdataset, &rdata); 362135446Strhodes 363135446Strhodes dns_name_format(name, namebuf, 364135446Strhodes sizeof(namebuf)); 365135446Strhodes printf(" -> %s\n", namebuf); 366135446Strhodes 367135446Strhodes switch (rdata.type) { 368135446Strhodes case dns_rdatatype_soa: 369135446Strhodes printsoa(&rdata); 370135446Strhodes break; 371135446Strhodes default: 372135446Strhodes printf("\t"); 373135446Strhodes printrdata(&rdata); 374135446Strhodes } 375135446Strhodes dns_rdata_reset(&rdata); 376204619Sdougb printf("\tttl = %u\n", rdataset->ttl); 377135446Strhodes loopresult = dns_rdataset_next(rdataset); 378135446Strhodes } 379135446Strhodes } 380135446Strhodes result = dns_message_nextname(msg, section); 381135446Strhodes if (result == ISC_R_NOMORE) 382135446Strhodes break; 383135446Strhodes else if (result != ISC_R_SUCCESS) { 384135446Strhodes return (result); 385135446Strhodes } 386135446Strhodes } 387135446Strhodes return (ISC_R_SUCCESS); 388135446Strhodes} 389135446Strhodes 390135446Strhodesvoid 391135446Strhodesreceived(int bytes, isc_sockaddr_t *from, dig_query_t *query) 392135446Strhodes{ 393135446Strhodes UNUSED(bytes); 394135446Strhodes UNUSED(from); 395135446Strhodes UNUSED(query); 396135446Strhodes} 397135446Strhodes 398135446Strhodesvoid 399135446Strhodestrying(char *frm, dig_lookup_t *lookup) { 400135446Strhodes UNUSED(frm); 401135446Strhodes UNUSED(lookup); 402135446Strhodes 403135446Strhodes} 404135446Strhodes 405135446Strhodesisc_result_t 406135446Strhodesprintmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { 407193149Sdougb char servtext[ISC_SOCKADDR_FORMATSIZE]; 408135446Strhodes 409135446Strhodes debug("printmessage()"); 410135446Strhodes 411135446Strhodes isc_sockaddr_format(&query->sockaddr, servtext, sizeof(servtext)); 412143731Sdougb printf("Server:\t\t%s\n", query->userarg); 413135446Strhodes printf("Address:\t%s\n", servtext); 414193149Sdougb 415135446Strhodes puts(""); 416135446Strhodes 417135446Strhodes if (!short_form) { 418135446Strhodes isc_boolean_t headers = ISC_TRUE; 419135446Strhodes puts("------------"); 420135446Strhodes /* detailheader(query, msg);*/ 421135446Strhodes detailsection(query, msg, headers, DNS_SECTION_QUESTION); 422135446Strhodes detailsection(query, msg, headers, DNS_SECTION_ANSWER); 423135446Strhodes detailsection(query, msg, headers, DNS_SECTION_AUTHORITY); 424135446Strhodes detailsection(query, msg, headers, DNS_SECTION_ADDITIONAL); 425135446Strhodes puts("------------"); 426135446Strhodes } 427135446Strhodes 428135446Strhodes if (msg->rcode != 0) { 429135446Strhodes char nametext[DNS_NAME_FORMATSIZE]; 430135446Strhodes dns_name_format(query->lookup->name, 431135446Strhodes nametext, sizeof(nametext)); 432174187Sdougb printf("** server can't find %s: %s\n", 433174187Sdougb (msg->rcode != dns_rcode_nxdomain) ? nametext : 434193149Sdougb query->lookup->textname, rcode_totext(msg->rcode)); 435135446Strhodes debug("returning with rcode == 0"); 436135446Strhodes return (ISC_R_SUCCESS); 437135446Strhodes } 438135446Strhodes 439135446Strhodes if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) 440135446Strhodes puts("Non-authoritative answer:"); 441135446Strhodes if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) 442135446Strhodes printsection(query, msg, headers, DNS_SECTION_ANSWER); 443135446Strhodes else 444135446Strhodes printf("*** Can't find %s: No answer\n", 445135446Strhodes query->lookup->textname); 446135446Strhodes 447135446Strhodes if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) && 448135446Strhodes (query->lookup->rdtype != dns_rdatatype_a)) { 449135446Strhodes puts("\nAuthoritative answers can be found from:"); 450135446Strhodes printsection(query, msg, headers, 451135446Strhodes DNS_SECTION_AUTHORITY); 452135446Strhodes printsection(query, msg, headers, 453135446Strhodes DNS_SECTION_ADDITIONAL); 454135446Strhodes } 455135446Strhodes return (ISC_R_SUCCESS); 456135446Strhodes} 457135446Strhodes 458135446Strhodesstatic void 459135446Strhodesshow_settings(isc_boolean_t full, isc_boolean_t serv_only) { 460135446Strhodes dig_server_t *srv; 461135446Strhodes isc_sockaddr_t sockaddr; 462135446Strhodes dig_searchlist_t *listent; 463193149Sdougb isc_result_t result; 464135446Strhodes 465135446Strhodes srv = ISC_LIST_HEAD(server_list); 466135446Strhodes 467135446Strhodes while (srv != NULL) { 468135446Strhodes char sockstr[ISC_SOCKADDR_FORMATSIZE]; 469135446Strhodes 470193149Sdougb result = get_address(srv->servername, port, &sockaddr); 471193149Sdougb check_result(result, "get_address"); 472193149Sdougb 473135446Strhodes isc_sockaddr_format(&sockaddr, sockstr, sizeof(sockstr)); 474135446Strhodes printf("Default server: %s\nAddress: %s\n", 475143731Sdougb srv->userarg, sockstr); 476135446Strhodes if (!full) 477135446Strhodes return; 478135446Strhodes srv = ISC_LIST_NEXT(srv, link); 479135446Strhodes } 480135446Strhodes if (serv_only) 481135446Strhodes return; 482135446Strhodes printf("\nSet options:\n"); 483135446Strhodes printf(" %s\t\t\t%s\t\t%s\n", 484135446Strhodes tcpmode ? "vc" : "novc", 485135446Strhodes short_form ? "nodebug" : "debug", 486135446Strhodes debugging ? "d2" : "nod2"); 487135446Strhodes printf(" %s\t\t%s\n", 488135446Strhodes usesearch ? "search" : "nosearch", 489135446Strhodes recurse ? "recurse" : "norecurse"); 490135446Strhodes printf(" timeout = %d\t\tretry = %d\tport = %d\n", 491135446Strhodes timeout, tries, port); 492135446Strhodes printf(" querytype = %-8s\tclass = %s\n", deftype, defclass); 493135446Strhodes printf(" srchlist = "); 494135446Strhodes for (listent = ISC_LIST_HEAD(search_list); 495135446Strhodes listent != NULL; 496135446Strhodes listent = ISC_LIST_NEXT(listent, link)) { 497135446Strhodes printf("%s", listent->origin); 498135446Strhodes if (ISC_LIST_NEXT(listent, link) != NULL) 499135446Strhodes printf("/"); 500135446Strhodes } 501135446Strhodes printf("\n"); 502135446Strhodes} 503135446Strhodes 504135446Strhodesstatic isc_boolean_t 505135446Strhodestesttype(char *typetext) { 506135446Strhodes isc_result_t result; 507135446Strhodes isc_textregion_t tr; 508135446Strhodes dns_rdatatype_t rdtype; 509135446Strhodes 510135446Strhodes tr.base = typetext; 511135446Strhodes tr.length = strlen(typetext); 512135446Strhodes result = dns_rdatatype_fromtext(&rdtype, &tr); 513135446Strhodes if (result == ISC_R_SUCCESS) 514135446Strhodes return (ISC_TRUE); 515135446Strhodes else { 516135446Strhodes printf("unknown query type: %s\n", typetext); 517135446Strhodes return (ISC_FALSE); 518135446Strhodes } 519135446Strhodes} 520135446Strhodes 521135446Strhodesstatic isc_boolean_t 522135446Strhodestestclass(char *typetext) { 523135446Strhodes isc_result_t result; 524135446Strhodes isc_textregion_t tr; 525135446Strhodes dns_rdataclass_t rdclass; 526135446Strhodes 527135446Strhodes tr.base = typetext; 528135446Strhodes tr.length = strlen(typetext); 529135446Strhodes result = dns_rdataclass_fromtext(&rdclass, &tr); 530193149Sdougb if (result == ISC_R_SUCCESS) 531135446Strhodes return (ISC_TRUE); 532135446Strhodes else { 533135446Strhodes printf("unknown query class: %s\n", typetext); 534135446Strhodes return (ISC_FALSE); 535135446Strhodes } 536135446Strhodes} 537135446Strhodes 538135446Strhodesstatic void 539135446Strhodesset_port(const char *value) { 540135446Strhodes isc_uint32_t n; 541135446Strhodes isc_result_t result = parse_uint(&n, value, 65535, "port"); 542135446Strhodes if (result == ISC_R_SUCCESS) 543135446Strhodes port = (isc_uint16_t) n; 544135446Strhodes} 545135446Strhodes 546135446Strhodesstatic void 547135446Strhodesset_timeout(const char *value) { 548135446Strhodes isc_uint32_t n; 549135446Strhodes isc_result_t result = parse_uint(&n, value, UINT_MAX, "timeout"); 550135446Strhodes if (result == ISC_R_SUCCESS) 551135446Strhodes timeout = n; 552135446Strhodes} 553135446Strhodes 554135446Strhodesstatic void 555135446Strhodesset_tries(const char *value) { 556135446Strhodes isc_uint32_t n; 557135446Strhodes isc_result_t result = parse_uint(&n, value, INT_MAX, "tries"); 558135446Strhodes if (result == ISC_R_SUCCESS) 559135446Strhodes tries = n; 560135446Strhodes} 561135446Strhodes 562135446Strhodesstatic void 563135446Strhodessetoption(char *opt) { 564135446Strhodes if (strncasecmp(opt, "all", 4) == 0) { 565135446Strhodes show_settings(ISC_TRUE, ISC_FALSE); 566135446Strhodes } else if (strncasecmp(opt, "class=", 6) == 0) { 567135446Strhodes if (testclass(&opt[6])) 568225361Sdougb strlcpy(defclass, &opt[6], sizeof(defclass)); 569135446Strhodes } else if (strncasecmp(opt, "cl=", 3) == 0) { 570135446Strhodes if (testclass(&opt[3])) 571225361Sdougb strlcpy(defclass, &opt[3], sizeof(defclass)); 572135446Strhodes } else if (strncasecmp(opt, "type=", 5) == 0) { 573135446Strhodes if (testtype(&opt[5])) 574225361Sdougb strlcpy(deftype, &opt[5], sizeof(deftype)); 575135446Strhodes } else if (strncasecmp(opt, "ty=", 3) == 0) { 576135446Strhodes if (testtype(&opt[3])) 577225361Sdougb strlcpy(deftype, &opt[3], sizeof(deftype)); 578135446Strhodes } else if (strncasecmp(opt, "querytype=", 10) == 0) { 579135446Strhodes if (testtype(&opt[10])) 580225361Sdougb strlcpy(deftype, &opt[10], sizeof(deftype)); 581135446Strhodes } else if (strncasecmp(opt, "query=", 6) == 0) { 582135446Strhodes if (testtype(&opt[6])) 583225361Sdougb strlcpy(deftype, &opt[6], sizeof(deftype)); 584135446Strhodes } else if (strncasecmp(opt, "qu=", 3) == 0) { 585135446Strhodes if (testtype(&opt[3])) 586225361Sdougb strlcpy(deftype, &opt[3], sizeof(deftype)); 587135446Strhodes } else if (strncasecmp(opt, "q=", 2) == 0) { 588135446Strhodes if (testtype(&opt[2])) 589225361Sdougb strlcpy(deftype, &opt[2], sizeof(deftype)); 590135446Strhodes } else if (strncasecmp(opt, "domain=", 7) == 0) { 591225361Sdougb strlcpy(domainopt, &opt[7], sizeof(domainopt)); 592135446Strhodes set_search_domain(domainopt); 593135446Strhodes usesearch = ISC_TRUE; 594135446Strhodes } else if (strncasecmp(opt, "do=", 3) == 0) { 595225361Sdougb strlcpy(domainopt, &opt[3], sizeof(domainopt)); 596135446Strhodes set_search_domain(domainopt); 597135446Strhodes usesearch = ISC_TRUE; 598135446Strhodes } else if (strncasecmp(opt, "port=", 5) == 0) { 599135446Strhodes set_port(&opt[5]); 600135446Strhodes } else if (strncasecmp(opt, "po=", 3) == 0) { 601135446Strhodes set_port(&opt[3]); 602135446Strhodes } else if (strncasecmp(opt, "timeout=", 8) == 0) { 603135446Strhodes set_timeout(&opt[8]); 604135446Strhodes } else if (strncasecmp(opt, "t=", 2) == 0) { 605135446Strhodes set_timeout(&opt[2]); 606193149Sdougb } else if (strncasecmp(opt, "rec", 3) == 0) { 607135446Strhodes recurse = ISC_TRUE; 608135446Strhodes } else if (strncasecmp(opt, "norec", 5) == 0) { 609135446Strhodes recurse = ISC_FALSE; 610135446Strhodes } else if (strncasecmp(opt, "retry=", 6) == 0) { 611135446Strhodes set_tries(&opt[6]); 612135446Strhodes } else if (strncasecmp(opt, "ret=", 4) == 0) { 613135446Strhodes set_tries(&opt[4]); 614193149Sdougb } else if (strncasecmp(opt, "def", 3) == 0) { 615135446Strhodes usesearch = ISC_TRUE; 616135446Strhodes } else if (strncasecmp(opt, "nodef", 5) == 0) { 617135446Strhodes usesearch = ISC_FALSE; 618193149Sdougb } else if (strncasecmp(opt, "vc", 3) == 0) { 619135446Strhodes tcpmode = ISC_TRUE; 620135446Strhodes } else if (strncasecmp(opt, "novc", 5) == 0) { 621135446Strhodes tcpmode = ISC_FALSE; 622193149Sdougb } else if (strncasecmp(opt, "deb", 3) == 0) { 623135446Strhodes short_form = ISC_FALSE; 624170222Sdougb showsearch = ISC_TRUE; 625135446Strhodes } else if (strncasecmp(opt, "nodeb", 5) == 0) { 626135446Strhodes short_form = ISC_TRUE; 627170222Sdougb showsearch = ISC_FALSE; 628193149Sdougb } else if (strncasecmp(opt, "d2", 2) == 0) { 629135446Strhodes debugging = ISC_TRUE; 630135446Strhodes } else if (strncasecmp(opt, "nod2", 4) == 0) { 631135446Strhodes debugging = ISC_FALSE; 632135446Strhodes } else if (strncasecmp(opt, "search", 3) == 0) { 633135446Strhodes usesearch = ISC_TRUE; 634135446Strhodes } else if (strncasecmp(opt, "nosearch", 5) == 0) { 635135446Strhodes usesearch = ISC_FALSE; 636135446Strhodes } else if (strncasecmp(opt, "sil", 3) == 0) { 637135446Strhodes /* deprecation_msg = ISC_FALSE; */ 638170222Sdougb } else if (strncasecmp(opt, "fail", 3) == 0) { 639170222Sdougb nofail=ISC_FALSE; 640170222Sdougb } else if (strncasecmp(opt, "nofail", 3) == 0) { 641170222Sdougb nofail=ISC_TRUE; 642135446Strhodes } else { 643193149Sdougb printf("*** Invalid option: %s\n", opt); 644135446Strhodes } 645135446Strhodes} 646135446Strhodes 647135446Strhodesstatic void 648135446Strhodesaddlookup(char *opt) { 649135446Strhodes dig_lookup_t *lookup; 650135446Strhodes isc_result_t result; 651135446Strhodes isc_textregion_t tr; 652135446Strhodes dns_rdatatype_t rdtype; 653135446Strhodes dns_rdataclass_t rdclass; 654135446Strhodes char store[MXNAME]; 655135446Strhodes 656135446Strhodes debug("addlookup()"); 657135446Strhodes tr.base = deftype; 658135446Strhodes tr.length = strlen(deftype); 659135446Strhodes result = dns_rdatatype_fromtext(&rdtype, &tr); 660135446Strhodes if (result != ISC_R_SUCCESS) { 661135446Strhodes printf("unknown query type: %s\n", deftype); 662135446Strhodes rdclass = dns_rdatatype_a; 663135446Strhodes } 664135446Strhodes tr.base = defclass; 665135446Strhodes tr.length = strlen(defclass); 666135446Strhodes result = dns_rdataclass_fromtext(&rdclass, &tr); 667135446Strhodes if (result != ISC_R_SUCCESS) { 668135446Strhodes printf("unknown query class: %s\n", defclass); 669135446Strhodes rdclass = dns_rdataclass_in; 670135446Strhodes } 671135446Strhodes lookup = make_empty_lookup(); 672135446Strhodes if (get_reverse(store, sizeof(store), opt, lookup->ip6_int, ISC_TRUE) 673135446Strhodes == ISC_R_SUCCESS) { 674225361Sdougb strlcpy(lookup->textname, store, sizeof(lookup->textname)); 675135446Strhodes lookup->rdtype = dns_rdatatype_ptr; 676135446Strhodes lookup->rdtypeset = ISC_TRUE; 677135446Strhodes } else { 678225361Sdougb strlcpy(lookup->textname, opt, sizeof(lookup->textname)); 679135446Strhodes lookup->rdtype = rdtype; 680135446Strhodes lookup->rdtypeset = ISC_TRUE; 681135446Strhodes } 682135446Strhodes lookup->rdclass = rdclass; 683135446Strhodes lookup->rdclassset = ISC_TRUE; 684135446Strhodes lookup->trace = ISC_FALSE; 685135446Strhodes lookup->trace_root = lookup->trace; 686135446Strhodes lookup->ns_search_only = ISC_FALSE; 687135446Strhodes lookup->identify = identify; 688135446Strhodes lookup->recurse = recurse; 689135446Strhodes lookup->aaonly = aaonly; 690135446Strhodes lookup->retries = tries; 691135446Strhodes lookup->udpsize = 0; 692135446Strhodes lookup->comments = comments; 693135446Strhodes lookup->tcp_mode = tcpmode; 694135446Strhodes lookup->stats = stats; 695135446Strhodes lookup->section_question = section_question; 696135446Strhodes lookup->section_answer = section_answer; 697135446Strhodes lookup->section_authority = section_authority; 698135446Strhodes lookup->section_additional = section_additional; 699135446Strhodes lookup->new_search = ISC_TRUE; 700170222Sdougb if (nofail) 701170222Sdougb lookup->servfail_stops = ISC_FALSE; 702135446Strhodes ISC_LIST_INIT(lookup->q); 703135446Strhodes ISC_LINK_INIT(lookup, link); 704135446Strhodes ISC_LIST_APPEND(lookup_list, lookup, link); 705135446Strhodes lookup->origin = NULL; 706135446Strhodes ISC_LIST_INIT(lookup->my_server_list); 707135446Strhodes debug("looking up %s", lookup->textname); 708135446Strhodes} 709135446Strhodes 710135446Strhodesstatic void 711135446Strhodesget_next_command(void) { 712135446Strhodes char *buf; 713135446Strhodes char *ptr, *arg; 714135446Strhodes char *input; 715135446Strhodes 716135446Strhodes fflush(stdout); 717135446Strhodes buf = isc_mem_allocate(mctx, COMMSIZE); 718135446Strhodes if (buf == NULL) 719135446Strhodes fatal("memory allocation failure"); 720135446Strhodes fputs("> ", stderr); 721165071Sdougb fflush(stderr); 722135446Strhodes isc_app_block(); 723135446Strhodes ptr = fgets(buf, COMMSIZE, stdin); 724135446Strhodes isc_app_unblock(); 725135446Strhodes if (ptr == NULL) { 726135446Strhodes in_use = ISC_FALSE; 727135446Strhodes goto cleanup; 728135446Strhodes } 729135446Strhodes input = buf; 730135446Strhodes ptr = next_token(&input, " \t\r\n"); 731135446Strhodes if (ptr == NULL) 732135446Strhodes goto cleanup; 733135446Strhodes arg = next_token(&input, " \t\r\n"); 734135446Strhodes if ((strcasecmp(ptr, "set") == 0) && 735135446Strhodes (arg != NULL)) 736135446Strhodes setoption(arg); 737135446Strhodes else if ((strcasecmp(ptr, "server") == 0) || 738135446Strhodes (strcasecmp(ptr, "lserver") == 0)) { 739143731Sdougb isc_app_block(); 740135446Strhodes set_nameserver(arg); 741170222Sdougb check_ra = ISC_FALSE; 742143731Sdougb isc_app_unblock(); 743135446Strhodes show_settings(ISC_TRUE, ISC_TRUE); 744135446Strhodes } else if (strcasecmp(ptr, "exit") == 0) { 745135446Strhodes in_use = ISC_FALSE; 746135446Strhodes goto cleanup; 747135446Strhodes } else if (strcasecmp(ptr, "help") == 0 || 748135446Strhodes strcasecmp(ptr, "?") == 0) { 749135446Strhodes printf("The '%s' command is not yet implemented.\n", ptr); 750135446Strhodes goto cleanup; 751135446Strhodes } else if (strcasecmp(ptr, "finger") == 0 || 752135446Strhodes strcasecmp(ptr, "root") == 0 || 753135446Strhodes strcasecmp(ptr, "ls") == 0 || 754135446Strhodes strcasecmp(ptr, "view") == 0) { 755135446Strhodes printf("The '%s' command is not implemented.\n", ptr); 756135446Strhodes goto cleanup; 757135446Strhodes } else 758135446Strhodes addlookup(ptr); 759135446Strhodes cleanup: 760135446Strhodes isc_mem_free(mctx, buf); 761135446Strhodes} 762135446Strhodes 763135446Strhodesstatic void 764135446Strhodesparse_args(int argc, char **argv) { 765135446Strhodes isc_boolean_t have_lookup = ISC_FALSE; 766135446Strhodes 767135446Strhodes usesearch = ISC_TRUE; 768135446Strhodes for (argc--, argv++; argc > 0; argc--, argv++) { 769135446Strhodes debug("main parsing %s", argv[0]); 770135446Strhodes if (argv[0][0] == '-') { 771135446Strhodes if (argv[0][1] != 0) 772135446Strhodes setoption(&argv[0][1]); 773135446Strhodes else 774135446Strhodes have_lookup = ISC_TRUE; 775135446Strhodes } else { 776135446Strhodes if (!have_lookup) { 777135446Strhodes have_lookup = ISC_TRUE; 778135446Strhodes in_use = ISC_TRUE; 779135446Strhodes addlookup(argv[0]); 780170222Sdougb } else { 781170222Sdougb set_nameserver(argv[0]); 782170222Sdougb check_ra = ISC_FALSE; 783135446Strhodes } 784135446Strhodes } 785135446Strhodes } 786135446Strhodes} 787135446Strhodes 788135446Strhodesstatic void 789135446Strhodesflush_lookup_list(void) { 790135446Strhodes dig_lookup_t *l, *lp; 791135446Strhodes dig_query_t *q, *qp; 792135446Strhodes dig_server_t *s, *sp; 793135446Strhodes 794135446Strhodes lookup_counter = 0; 795135446Strhodes l = ISC_LIST_HEAD(lookup_list); 796135446Strhodes while (l != NULL) { 797135446Strhodes q = ISC_LIST_HEAD(l->q); 798135446Strhodes while (q != NULL) { 799135446Strhodes if (q->sock != NULL) { 800135446Strhodes isc_socket_cancel(q->sock, NULL, 801135446Strhodes ISC_SOCKCANCEL_ALL); 802135446Strhodes isc_socket_detach(&q->sock); 803135446Strhodes } 804135446Strhodes if (ISC_LINK_LINKED(&q->recvbuf, link)) 805135446Strhodes ISC_LIST_DEQUEUE(q->recvlist, &q->recvbuf, 806135446Strhodes link); 807135446Strhodes if (ISC_LINK_LINKED(&q->lengthbuf, link)) 808135446Strhodes ISC_LIST_DEQUEUE(q->lengthlist, &q->lengthbuf, 809135446Strhodes link); 810135446Strhodes isc_buffer_invalidate(&q->recvbuf); 811135446Strhodes isc_buffer_invalidate(&q->lengthbuf); 812135446Strhodes qp = q; 813135446Strhodes q = ISC_LIST_NEXT(q, link); 814135446Strhodes ISC_LIST_DEQUEUE(l->q, qp, link); 815135446Strhodes isc_mem_free(mctx, qp); 816135446Strhodes } 817135446Strhodes s = ISC_LIST_HEAD(l->my_server_list); 818135446Strhodes while (s != NULL) { 819135446Strhodes sp = s; 820135446Strhodes s = ISC_LIST_NEXT(s, link); 821135446Strhodes ISC_LIST_DEQUEUE(l->my_server_list, sp, link); 822135446Strhodes isc_mem_free(mctx, sp); 823135446Strhodes 824135446Strhodes } 825135446Strhodes if (l->sendmsg != NULL) 826135446Strhodes dns_message_destroy(&l->sendmsg); 827135446Strhodes if (l->timer != NULL) 828135446Strhodes isc_timer_detach(&l->timer); 829135446Strhodes lp = l; 830135446Strhodes l = ISC_LIST_NEXT(l, link); 831135446Strhodes ISC_LIST_DEQUEUE(lookup_list, lp, link); 832135446Strhodes isc_mem_free(mctx, lp); 833135446Strhodes } 834135446Strhodes} 835135446Strhodes 836135446Strhodesstatic void 837135446Strhodesgetinput(isc_task_t *task, isc_event_t *event) { 838135446Strhodes UNUSED(task); 839135446Strhodes if (global_event == NULL) 840135446Strhodes global_event = event; 841135446Strhodes while (in_use) { 842135446Strhodes get_next_command(); 843135446Strhodes if (ISC_LIST_HEAD(lookup_list) != NULL) { 844135446Strhodes start_lookup(); 845135446Strhodes return; 846135446Strhodes } 847135446Strhodes } 848135446Strhodes isc_app_shutdown(); 849135446Strhodes} 850135446Strhodes 851135446Strhodesint 852135446Strhodesmain(int argc, char **argv) { 853135446Strhodes isc_result_t result; 854135446Strhodes 855135446Strhodes ISC_LIST_INIT(lookup_list); 856135446Strhodes ISC_LIST_INIT(server_list); 857135446Strhodes ISC_LIST_INIT(search_list); 858135446Strhodes 859170222Sdougb check_ra = ISC_TRUE; 860170222Sdougb 861135446Strhodes result = isc_app_start(); 862135446Strhodes check_result(result, "isc_app_start"); 863135446Strhodes 864135446Strhodes setup_libs(); 865135446Strhodes progname = argv[0]; 866135446Strhodes 867135446Strhodes parse_args(argc, argv); 868135446Strhodes 869135446Strhodes setup_system(); 870135446Strhodes if (domainopt[0] != '\0') 871135446Strhodes set_search_domain(domainopt); 872135446Strhodes if (in_use) 873135446Strhodes result = isc_app_onrun(mctx, global_task, onrun_callback, 874135446Strhodes NULL); 875135446Strhodes else 876135446Strhodes result = isc_app_onrun(mctx, global_task, getinput, NULL); 877135446Strhodes check_result(result, "isc_app_onrun"); 878135446Strhodes in_use = ISC_TF(!in_use); 879135446Strhodes 880135446Strhodes (void)isc_app_run(); 881135446Strhodes 882135446Strhodes puts(""); 883135446Strhodes debug("done, and starting to shut down"); 884135446Strhodes if (global_event != NULL) 885135446Strhodes isc_event_free(&global_event); 886135446Strhodes cancel_all(); 887135446Strhodes destroy_libs(); 888135446Strhodes isc_app_finish(); 889135446Strhodes 890135446Strhodes return (0); 891135446Strhodes} 892