dig.c

来自「非常好的dns解析软件」· C语言 代码 · 共 1,806 行 · 第 1/4 页

C
1,806
字号
/* * Copyright (C) 2004-2006  Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003  Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. *//* $Id: dig.c,v 1.186.18.26 2006/07/21 23:52:21 marka Exp $ *//*! \file */#include <config.h>#include <stdlib.h>#include <time.h>#include <ctype.h>#include <isc/app.h>#include <isc/netaddr.h>#include <isc/parseint.h>#include <isc/print.h>#include <isc/string.h>#include <isc/util.h>#include <isc/task.h>#include <dns/byaddr.h>#include <dns/fixedname.h>#include <dns/masterdump.h>#include <dns/message.h>#include <dns/name.h>#include <dns/rdata.h>#include <dns/rdataset.h>#include <dns/rdatatype.h>#include <dns/rdataclass.h>#include <dns/result.h>#include <dns/tsig.h>#include <bind9/getaddresses.h>#include <dig/dig.h>#define ADD_STRING(b, s) { 				\	if (strlen(s) >= isc_buffer_availablelength(b)) \ 		return (ISC_R_NOSPACE); 		\	else 						\		isc_buffer_putstr(b, s); 		\}#define DIG_MAX_ADDRESSES 20dig_lookup_t *default_lookup = NULL;static char *batchname = NULL;static FILE *batchfp = NULL;static char *argv0;static int addresscount = 0;static char domainopt[DNS_NAME_MAXTEXT];static isc_boolean_t short_form = ISC_FALSE, printcmd = ISC_TRUE,	ip6_int = ISC_FALSE, plusquest = ISC_FALSE, pluscomm = ISC_FALSE,	multiline = ISC_FALSE, nottl = ISC_FALSE, noclass = ISC_FALSE;/*% opcode text */static const char *opcodetext[] = {	"QUERY",	"IQUERY",	"STATUS",	"RESERVED3",	"NOTIFY",	"UPDATE",	"RESERVED6",	"RESERVED7",	"RESERVED8",	"RESERVED9",	"RESERVED10",	"RESERVED11",	"RESERVED12",	"RESERVED13",	"RESERVED14",	"RESERVED15"};/*% return code text */static const char *rcodetext[] = {	"NOERROR",	"FORMERR",	"SERVFAIL",	"NXDOMAIN",	"NOTIMP",	"REFUSED",	"YXDOMAIN",	"YXRRSET",	"NXRRSET",	"NOTAUTH",	"NOTZONE",	"RESERVED11",	"RESERVED12",	"RESERVED13",	"RESERVED14",	"RESERVED15",	"BADVERS"};/*% print usage */static voidprint_usage(FILE *fp) {	fputs("Usage:  dig [@global-server] [domain] [q-type] [q-class] {q-opt}\n""            {global-d-opt} host [@local-server] {local-d-opt}\n""            [ host [@local-server] {local-d-opt} [...]]\n", fp);}static voidusage(void) {	print_usage(stderr);	fputs("\nUse \"dig -h\" (or \"dig -h | more\") "	      "for complete list of options\n", stderr);	exit(1);}/*% version */static voidversion(void) {	fputs("DiG " VERSION "\n", stderr);}/*% help */static voidhelp(void) {	print_usage(stdout);	fputs("Where:  domain	  is in the Domain Name System\n""        q-class  is one of (in,hs,ch,...) [default: in]\n""        q-type   is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default:a]\n""                 (Use ixfr=version for type ixfr)\n""        q-opt    is one of:\n""                 -x dot-notation     (shortcut for in-addr lookups)\n""                 -i                  (IP6.INT reverse IPv6 lookups)\n""                 -f filename         (batch mode)\n""                 -b address[#port]   (bind to source address/port)\n""                 -p port             (specify port number)\n""                 -q name             (specify query name)\n""                 -t type             (specify query type)\n""                 -c class            (specify query class)\n""                 -k keyfile          (specify tsig key file)\n""                 -y [hmac:]name:key  (specify named base64 tsig key)\n""                 -4                  (use IPv4 query transport only)\n""                 -6                  (use IPv6 query transport only)\n""        d-opt    is of the form +keyword[=value], where keyword is:\n""                 +[no]vc             (TCP mode)\n""                 +[no]tcp            (TCP mode, alternate syntax)\n""                 +time=###           (Set query timeout) [5]\n""                 +tries=###          (Set number of UDP attempts) [3]\n""                 +retry=###          (Set number of UDP retries) [2]\n""                 +domain=###         (Set default domainname)\n""                 +bufsize=###        (Set EDNS0 Max UDP packet size)\n""                 +ndots=###          (Set NDOTS value)\n""                 +edns=###           (Set EDNS version)\n""                 +[no]search         (Set whether to use searchlist)\n""                 +[no]showsearch     (Search with intermediate results)\n""                 +[no]defname        (Ditto)\n""                 +[no]recurse        (Recursive mode)\n""                 +[no]ignore         (Don't revert to TCP for TC responses.)""\n""                 +[no]fail           (Don't try next server on SERVFAIL)\n""                 +[no]besteffort     (Try to parse even illegal messages)\n""                 +[no]aaonly         (Set AA flag in query (+[no]aaflag))\n""                 +[no]adflag         (Set AD flag in query)\n""                 +[no]cdflag         (Set CD flag in query)\n""                 +[no]cl             (Control display of class in records)\n""                 +[no]cmd            (Control display of command line)\n""                 +[no]comments       (Control display of comment lines)\n""                 +[no]question       (Control display of question)\n""                 +[no]answer         (Control display of answer)\n""                 +[no]authority      (Control display of authority)\n""                 +[no]additional     (Control display of additional)\n""                 +[no]stats          (Control display of statistics)\n""                 +[no]short          (Disable everything except short\n""                                      form of answer)\n""                 +[no]ttlid          (Control display of ttls in records)\n""                 +[no]all            (Set or clear all display flags)\n""                 +[no]qr             (Print question before sending)\n""                 +[no]nssearch       (Search all authoritative nameservers)\n""                 +[no]identify       (ID responders in short answers)\n""                 +[no]trace          (Trace delegation down from root)\n""                 +[no]dnssec         (Request DNSSEC records)\n"#ifdef DIG_SIGCHASE"                 +[no]sigchase       (Chase DNSSEC signatures)\n""                 +trusted-key=####   (Trusted Key when chasing DNSSEC sigs)\n"#if DIG_SIGCHASE_TD"                 +[no]topdown        (Do DNSSEC validation top down mode)\n"#endif#endif"                 +[no]multiline      (Print records in an expanded format)\n""        global d-opts and servers (before host name) affect all queries.\n""        local d-opts and servers (after host name) affect only that lookup.\n""        -h                           (print help and exit)\n""        -v                           (print version and exit)\n",	stdout);}/*% * Callback from dighost.c to print the received message. */voidreceived(int bytes, isc_sockaddr_t *from, dig_query_t *query) {	isc_uint64_t diff;	isc_time_t now;	time_t tnow;	char fromtext[ISC_SOCKADDR_FORMATSIZE];	isc_sockaddr_format(from, fromtext, sizeof(fromtext));	TIME_NOW(&now);	if (query->lookup->stats && !short_form) {		diff = isc_time_microdiff(&now, &query->time_sent);		printf(";; Query time: %ld msec\n", (long int)diff/1000);		printf(";; SERVER: %s(%s)\n", fromtext, query->servname);		time(&tnow);		printf(";; WHEN: %s", ctime(&tnow));		if (query->lookup->doing_xfr) {			printf(";; XFR size: %u records (messages %u, "			       "bytes %" ISC_PRINT_QUADFORMAT "u)\n",			       query->rr_count, query->msg_count,			       query->byte_count);		} else {			printf(";; MSG SIZE  rcvd: %u\n", bytes);		}		if (key != NULL) {			if (!validated)				puts(";; WARNING -- Some TSIG could not "				     "be validated");		}		if ((key == NULL) && (keysecret[0] != 0)) {			puts(";; WARNING -- TSIG key was not used.");		}		puts("");	} else if (query->lookup->identify && !short_form) {		diff = isc_time_microdiff(&now, &query->time_sent);		printf(";; Received %" ISC_PRINT_QUADFORMAT "u bytes "		       "from %s(%s) in %d ms\n\n",		       query->lookup->doing_xfr ?				query->byte_count : (isc_uint64_t)bytes,		       fromtext, query->servname,		       (int)diff/1000);	}}/* * Callback from dighost.c to print that it is trying a server. * Not used in dig. * XXX print_trying */voidtrying(char *frm, dig_lookup_t *lookup) {	UNUSED(frm);	UNUSED(lookup);}/*% * Internal print routine used to print short form replies. */static isc_result_tsay_message(dns_rdata_t *rdata, dig_query_t *query, isc_buffer_t *buf) {	isc_result_t result;	isc_uint64_t diff;	isc_time_t now;	char store[sizeof("12345678901234567890")];	if (query->lookup->trace || query->lookup->ns_search_only) {		result = dns_rdatatype_totext(rdata->type, buf);		if (result != ISC_R_SUCCESS)			return (result);		ADD_STRING(buf, " ");	}	result = dns_rdata_totext(rdata, NULL, buf);	check_result(result, "dns_rdata_totext");	if (query->lookup->identify) {		TIME_NOW(&now);		diff = isc_time_microdiff(&now, &query->time_sent);		ADD_STRING(buf, " from server ");		ADD_STRING(buf, query->servname);		snprintf(store, 19, " in %d ms.", (int)diff/1000);		ADD_STRING(buf, store);	}	ADD_STRING(buf, "\n");	return (ISC_R_SUCCESS);}/*% * short_form message print handler.  Calls above say_message() */static isc_result_tshort_answer(dns_message_t *msg, dns_messagetextflag_t flags,	     isc_buffer_t *buf, dig_query_t *query){	dns_name_t *name;	dns_rdataset_t *rdataset;	isc_buffer_t target;	isc_result_t result, loopresult;	dns_name_t empty_name;	char t[4096];	dns_rdata_t rdata = DNS_RDATA_INIT;	UNUSED(flags);	dns_name_init(&empty_name, NULL);	result = dns_message_firstname(msg, DNS_SECTION_ANSWER);	if (result == ISC_R_NOMORE)		return (ISC_R_SUCCESS);	else if (result != ISC_R_SUCCESS)		return (result);	for (;;) {		name = NULL;		dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);		isc_buffer_init(&target, t, sizeof(t));		for (rdataset = ISC_LIST_HEAD(name->list);		     rdataset != NULL;		     rdataset = ISC_LIST_NEXT(rdataset, link)) {			loopresult = dns_rdataset_first(rdataset);			while (loopresult == ISC_R_SUCCESS) {				dns_rdataset_current(rdataset, &rdata);				result = say_message(&rdata, query,						     buf);				check_result(result, "say_message");				loopresult = dns_rdataset_next(rdataset);				dns_rdata_reset(&rdata);			}		}		result = dns_message_nextname(msg, DNS_SECTION_ANSWER);		if (result == ISC_R_NOMORE)			break;		else if (result != ISC_R_SUCCESS)			return (result);	}	return (ISC_R_SUCCESS);}#ifdef DIG_SIGCHASEisc_result_tprintrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,	      isc_buffer_t *target){	isc_result_t result;	dns_master_style_t *style = NULL;	unsigned int styleflags = 0;	if (rdataset == NULL || owner_name == NULL || target == NULL)		return(ISC_FALSE);	styleflags |= DNS_STYLEFLAG_REL_OWNER;	if (nottl)		styleflags |= DNS_STYLEFLAG_NO_TTL;	if (noclass)		styleflags |= DNS_STYLEFLAG_NO_CLASS;	if (multiline) {		styleflags |= DNS_STYLEFLAG_OMIT_OWNER;		styleflags |= DNS_STYLEFLAG_OMIT_CLASS;		styleflags |= DNS_STYLEFLAG_REL_DATA;		styleflags |= DNS_STYLEFLAG_OMIT_TTL;		styleflags |= DNS_STYLEFLAG_TTL;		styleflags |= DNS_STYLEFLAG_MULTILINE;		styleflags |= DNS_STYLEFLAG_COMMENT;	}	if (multiline || (nottl && noclass))		result = dns_master_stylecreate(&style, styleflags,						24, 24, 24, 32, 80, 8, mctx);	else if (nottl || noclass)		result = dns_master_stylecreate(&style, styleflags,						24, 24, 32, 40, 80, 8, mctx);	else 		result = dns_master_stylecreate(&style, styleflags,						24, 32, 40, 48, 80, 8, mctx);	check_result(result, "dns_master_stylecreate");	result = dns_master_rdatasettotext(owner_name, rdataset, style, target);	if (style != NULL)		dns_master_styledestroy(&style, mctx);  	return(result);}#endif/* * Callback from dighost.c to print the reply from a server */isc_result_tprintmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {	isc_result_t result;	dns_messagetextflag_t flags;	isc_buffer_t *buf = NULL;	unsigned int len = OUTPUTBUF;	dns_master_style_t *style = NULL;	unsigned int styleflags = 0;	styleflags |= DNS_STYLEFLAG_REL_OWNER;	if (nottl)		styleflags |= DNS_STYLEFLAG_NO_TTL;	if (noclass)		styleflags |= DNS_STYLEFLAG_NO_CLASS;	if (multiline) {		styleflags |= DNS_STYLEFLAG_OMIT_OWNER;		styleflags |= DNS_STYLEFLAG_OMIT_CLASS;		styleflags |= DNS_STYLEFLAG_REL_DATA;		styleflags |= DNS_STYLEFLAG_OMIT_TTL;		styleflags |= DNS_STYLEFLAG_TTL;		styleflags |= DNS_STYLEFLAG_MULTILINE;		styleflags |= DNS_STYLEFLAG_COMMENT;	}	if (multiline || (nottl && noclass))		result = dns_master_stylecreate(&style, styleflags,						24, 24, 24, 32, 80, 8, mctx);	else if (nottl || noclass)		result = dns_master_stylecreate(&style, styleflags,						24, 24, 32, 40, 80, 8, mctx);	else 		result = dns_master_stylecreate(&style, styleflags,						24, 32, 40, 48, 80, 8, mctx);	check_result(result, "dns_master_stylecreate");	if (query->lookup->cmdline[0] != 0) {		if (!short_form)			fputs(query->lookup->cmdline, stdout);		query->lookup->cmdline[0]=0;	}	debug("printmessage(%s %s %s)", headers ? "headers" : "noheaders",	      query->lookup->comments ? "comments" : "nocomments",	      short_form ? "short_form" : "long_form");	flags = 0;	if (!headers) {		flags |= DNS_MESSAGETEXTFLAG_NOHEADERS;		flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS;	}	if (!query->lookup->comments)		flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?