📄 host.c
字号:
/* * 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 + -