⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 host.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Rest means fully qualified. */	result = get_domaininfo(name, (char *)NULL);	/* restore nodata status from search */	if (!result && bindcompat && nodata)	{		realname = strcpy(realnamebuf, oldname);		h_errno = nodata;	}	return(result);}/*** GET_DOMAININFO -- Fetch and print desired info about name in domain** -------------------------------------------------------------------****	Returns:**		TRUE if requested info was obtained successfully.**		FALSE otherwise.****	Side effects:**		Sets global variable realname to actual name queried.****	This is the equivalent of the resolver module res_querydomain().****	Things get a little complicated in case RES_DNSRCH is on.**	If we get an answer but the data is corrupted, an error will be**	returned and NO_RECOVERY will be set. This will terminate the**	extra search loop, but a compound name will still be tried as-is.**	The same holds if the query times out or we have a server failure,**	in which case an error will be returned and TRY_AGAIN will be set.**	For now we take this for granted. Normally RES_DNSRCH is disabled.**	In this default case we do only one query and we have no problem.*/boolget_domaininfo(name, domain)input char *name;			/* name to query about */input char *domain;			/* domain to which name is relative */{	char namebuf[2*MAXDNAME+2];	/* buffer to store full domain name */	querybuf answer;	int anslen;	bool result;			/* result status of action taken *//* * Show what we are about to query. */	if (verbose)	{		if (domain == NULL || domain[0] == '\0')			printf("Trying %s", name);		else			printf("Trying %s within %s", name, domain);		if (server && (verbose > 1))			printf(" at server %s", server);		printf(" ...\n");	}/* * Construct the actual domain name. * A null domain means the given name is already fully qualified. * If the composite name is too long, res_mkquery() will fail. */	if (domain == NULL || domain[0] == '\0')		(void) sprintf(namebuf, "%.*s", MAXDNAME, name);	else		(void) sprintf(namebuf, "%.*s.%.*s",				MAXDNAME, name, MAXDNAME, domain);	name = namebuf;/* * Fetch the desired info. */	anslen = get_info(&answer, name, querytype, queryclass);	result = anslen < 0 ? FALSE : TRUE;/* * Print the relevant data. * If we got a positive answer, the data may still be corrupted. */	if (result)		result = print_info(&answer, anslen, name, FALSE);/* * Remember the actual name that was queried. * Must be at the end to avoid clobbering during recursive calls. */	realname = strcpy(realnamebuf, name);	return(result);}/*** GET_INFO -- Basic routine to issue a nameserver query** -----------------------------------------------------****	Returns:**		Length of nameserver answer buffer, if obtained.**		-1 if an error occurred (h_errno is set appropriately).****	This is the equivalent of the resolver module res_query().*/intget_info(answerbuf, name, type, class)output querybuf *answerbuf;		/* address of buffer to store answer */input char *name;			/* full name to query about */input int type;				/* specific resource record type */input int class;			/* specific resource record class */{	querybuf query;	HEADER *bp;	int ancount;	register int n;/* * Construct query, and send it to the nameserver. * res_send() will fail if no nameserver responded. In this case the possible * values for errno are ECONNREFUSED and ETIMEDOUT. If we did get an answer, * errno should be reset, since res_send() may have left an errno in case it * has used datagrams. Our private version of res_send() will leave also other * error statuses, and will clear errno if an answer was obtained. */	errno = 0;	/* reset before querying nameserver */	n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0,			(rrec_data_t *)NULL, (char *)&query, sizeof(querybuf));	if (n < 0)	{		if (debug)			(void) fprintf(stderr, "res_mkquery failed\n");		h_errno = NO_RECOVERY;		return(-1);	}	n = res_send((char *)&query, n, (char *)answerbuf, sizeof(querybuf));	if (n < 0)	{		if (debug)			(void) fprintf(stderr, "res_send failed\n");		h_errno = TRY_AGAIN;		return(-1);	}	errno = 0;	/* reset after we got an answer */	if (n < sizeof(HEADER))	{		pr_error("answer length %s too short", itoa(n));		h_errno = NO_RECOVERY;		return(-1);	}/* * Analyze the status of the answer from the nameserver. */	if (debug || verbose)		print_status(answerbuf);	bp = (HEADER *)answerbuf;	ancount = ntohs(bp->ancount);	if (bp->rcode != NOERROR || ancount == 0)	{		switch (bp->rcode)		{		    case NXDOMAIN:			/* distinguish between authoritative or not */			h_errno = bp->aa ? HOST_NOT_FOUND : NO_HOST;			break;		    case NOERROR:			/* distinguish between authoritative or not */			h_errno = bp->aa ? NO_DATA : NO_RREC;			break;		    case SERVFAIL:			h_errno = TRY_AGAIN;			break;		    case FORMERR:		    case NOTIMP:		    case REFUSED:		    case NOCHANGE:			h_errno = NO_RECOVERY;			break;		    default:			h_errno = NO_RECOVERY;			break;		}		return(-1);	}	h_errno = 0;	return(n);}/*** PRINT_INFO -- Check resource records in answer and print relevant data** ----------------------------------------------------------------------****	Returns:**		TRUE if answer buffer was processed successfully.**		FALSE otherwise.****	Side effects:**		Will recurse on MAILB records if appropriate.**		See also side effects of the print_rrec() routine.*/boolprint_info(answerbuf, answerlen, name, listing)input querybuf *answerbuf;		/* address of answer buffer */input int answerlen;			/* length of answer buffer */input char *name;			/* full name we are querying about */input bool listing;			/* set if this is a zone listing */{	HEADER *bp;	int qdcount, ancount, nscount, arcount;	u_char *msg, *eom;	register u_char *cp;	bp = (HEADER *)answerbuf;	qdcount = ntohs(bp->qdcount);	ancount = ntohs(bp->ancount);	nscount = ntohs(bp->nscount);	arcount = ntohs(bp->arcount);	msg = (u_char *)answerbuf;	eom = (u_char *)answerbuf + answerlen;	cp  = (u_char *)answerbuf + sizeof(HEADER);/* * Skip the query section in the response (present only in normal queries). */	if (qdcount)	{		while (qdcount > 0 && cp < eom)		{			/* cp += dn_skipname(cp, eom) + QFIXEDSZ; */			cp = skip_qrec(name, cp, msg, eom);			if (cp == NULL)				return(FALSE);			qdcount--;		}		if (qdcount)		{			pr_error("invalid qdcount in response");			h_errno = NO_RECOVERY;			return(FALSE);		}	}/* * Process the actual answer section in the response. * During zone transfers, this is the only section available. */	if (ancount)	{		if (!listing && verbose && !bp->aa)			printf("The following answer is not authoritative:\n");		while (ancount > 0 && cp < eom)		{			cp = print_rrec(name, cp, msg, eom, listing);			if (cp == NULL)				return(FALSE);			ancount--;		/*		 * When we ask for address and there is a CNAME, it returns		 * both the CNAME and the address.  Since we trace down the		 * CNAME chain ourselves, we don't really want to print the		 * address at this point.		 */			if (!listmode && !verbose && cname)				return(TRUE);		/*		 * Recursively expand MR or MG records into MB records.		 */			if (!listmode && mailmode && mname)			{				char newnamebuf[MAXDNAME+1];				char *newname;				newname = strcpy(newnamebuf, mname);				mname = NULL;				(void) get_hostinfo(newname);			}		}		if (ancount)		{			pr_error("invalid ancount in response");			h_errno = NO_RECOVERY;			return(FALSE);		}	}/* * The nameserver and additional info section are normally not processed. * Both sections shouldn't exist in zone transfers. */	if (!verbose || exclusive)		return(TRUE);	if (nscount)	{		printf("Authoritative nameservers:\n");		while (nscount > 0 && cp < eom)		{			cp = print_rrec(name, cp, msg, eom, FALSE);			if (cp == NULL)				return(FALSE);			nscount--;		}		if (nscount)		{			pr_error("invalid nscount in response");			h_errno = NO_RECOVERY;			return(FALSE);		}	}	if (arcount)	{		printf("Additional information:\n");		while (arcount > 0 && cp < eom)		{			cp = print_rrec(name, cp, msg, eom, FALSE);			if (cp == NULL)				return(FALSE);			arcount--;		}		if (arcount)		{			pr_error("invalid arcount in response");			h_errno = NO_RECOVERY;			return(FALSE);		}	}	return(TRUE);}/*** DOPRINTF -- Output resource record data if this record is wanted** ----------------------------------------------------------------****	Returns:**		None.****	Inputs:**		The global variable doprint is set by print_rrec()**		if we need to print the data.*/static bool doprint;		/* indicates whether or not to print */void /*VARARGS1*/doprintf(fmt, a, b, c, d)input char *fmt;			/* format of message */input char *a, *b, *c, *d;		/* optional arguments */{	if (doprint)	{		if (!suppress)			printf(fmt, a, b, c, d);		if (logfile != NULL)			(void) fprintf(logfile, fmt, a, b, c, d);	}}/*** PRINT_RREC -- Decode single resource record and output relevant data** --------------------------------------------------------------------****	Returns:**		Pointer to position in answer buffer after current record.**		NULL if there was a format error in the current record.****	Outputs:**		The global variable doprint is set appropriately**		for use by doprintf().****	Side effects:**		Updates resource record statistics in record_stats[].**		Sets soaname if this is an SOA record.**		Sets subname if this is an NS record.**		Sets adrname if this is an A record.**		Sets address if this is an A record.**		Sets cname if this is a valid CNAME record.**		Sets mname if this is a valid MAILB record.**		These variables must have been cleared before calling**		print_info() and may be checked afterwards.*/#define pr_name(x)	(listing ? pr_dotname(x) : x)u_char *print_rrec(name, cp, msg, eom, listing)input char *name;			/* full name we are querying about */register u_char *cp;			/* current position in answer buf */input u_char *msg, *eom;		/* begin and end of answer buf */input bool listing;			/* set if this is a zone listing */{	char rname[MAXDNAME+1];		/* record name in LHS */	char dname[MAXDNAME+1];		/* domain name in RHS */	int type, class, ttl, dlen;	/* fixed values in every record */	u_char *eor;			/* predicted position of next record */	bool classmatch;		/* set if we want to see this class */	register int n;	struct in_addr inaddr;	struct protoent *protocol;	struct servent *service;/* * Pickup the standard values present in each resource record. */	n = expand_name(name, T_NONE, cp, msg, eom, rname);	if (n < 0)		return(NULL);	cp += n;	n = 3*sizeof(u_short) + sizeof(u_int);	if (check_size(rname, T_NONE, cp, msg, eom, n) < 0)		return(NULL);	type = _getshort(cp);	cp += sizeof(u_short);	class = _getshort(cp);	cp += sizeof(u_short);	ttl = _getlong(cp);	cp += sizeof(u_int);	dlen = _getshort(cp);	cp += sizeof(u_short);	eor = cp + dlen;/* * Decide whether or not to print this resource record. */	if (listing)	{		classmatch = want_class(class, queryclass);		doprint = classmatch && want_type(type, querytype);	}	else	{		classmatch = want_class(class, C_ANY);		doprint = classmatch && want_type(type, T_ANY);	}#ifdef obsolete	if (doprint && exclusive && !samedomain(rname, name, TRUE))		doprint = FALSE;#endif	if (doprint && exclusive && !indomain(rname, name, TRUE))		doprint = FALSE;	if (doprint && exclusive && fakename(rname))		doprint = FALSE;#ifdef justfun	if (namelen && (strlength(rname) < namelen))		doprint = FALSE;#endif/* * Print name and common values, if appropriate. */	if (verbose)		doprintf("%-20s\t%s\t%s\t%s",			pr_name(rname), itoa(ttl), pr_class(class), pr_type(type));	else if (ttlprint)		doprintf("%-20s\t%s\t%s",			pr_name(rname), itoa(ttl), pr_type(type));	else		doprintf("%-20s\t%s",			pr_name(rname), pr_type(type));/* * Update resource record statistics for zone listing. */	if (listing && classmatch)	{		if (type >= T_FIRST && type <= T_LAST)			record_stats[type]++;	}/* * Save the domain name of an SOA or NS or A record for zone listing. */	if (listing && classmatch)	{

⌨️ 快捷键说明

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