📄 domain.c
字号:
int c = *host++; if (isascii(c) && isupper(c)) c = tolower(c); hfunc = ((hfunc << 1) ^ c) % 2003; } hfunc &= 0xff; if (tTd(17, 9)) printf(" = %d\n", hfunc); return hfunc;}/*** GETCANONNAME -- get the canonical name for named host**** This algorithm tries to be smart about wildcard MX records.** This is hard to do because DNS doesn't tell is if we matched** against a wildcard or a specific MX.** ** We always prefer A & CNAME records, since these are presumed** to be specific.**** If we match an MX in one pass and lose it in the next, we use** the old one. For example, consider an MX matching *.FOO.BAR.COM.** A hostname bletch.foo.bar.com will match against this MX, but** will stop matching when we try bletch.bar.com -- so we know** that bletch.foo.bar.com must have been right. This fails if** there was also an MX record matching *.BAR.COM, but there are** some things that just can't be fixed.**** Parameters:** host -- a buffer containing the name of the host.** This is a value-result parameter.** hbsize -- the size of the host buffer.** trymx -- if set, try MX records as well as A and CNAME.**** Returns:** TRUE -- if the host matched.** FALSE -- otherwise.*/boolgetcanonname(host, hbsize, trymx) char *host; int hbsize; bool trymx;{ extern int h_errno; register u_char *eom, *ap; register char *cp; register int n; HEADER *hp; querybuf answer; int ancount, qdcount; int ret; char **domain; int type; char **dp; char *mxmatch; bool amatch; bool gotmx; int qtype; int loopcnt; char *xp; char nbuf[MAX(PACKETSZ, MAXDNAME*2+2)]; char *searchlist[MAXDNSRCH+2]; extern char *gethostalias(); if (tTd(8, 2)) printf("getcanonname(%s)\n", host); if ((_res.options & RES_INIT) == 0 && res_init() == -1) return (FALSE); /* ** Initialize domain search list. If there is at least one ** dot in the name, search the unmodified name first so we ** find "vse.CS" in Czechoslovakia instead of in the local ** domain (e.g., vse.CS.Berkeley.EDU). ** ** Older versions of the resolver could create this ** list by tearing apart the host name. */ loopcnt = 0;cnameloop: for (cp = host, n = 0; *cp; cp++) if (*cp == '.') n++; if (n == 0 && (xp = gethostalias(host)) != NULL) { if (loopcnt++ > MAXCNAMEDEPTH) { syserr("loop in ${HOSTALIASES} file"); } else { strncpy(host, xp, hbsize); host[hbsize - 1] = '\0'; goto cnameloop; } } dp = searchlist; if (n > 0) *dp++ = ""; if (n >= 0 && *--cp != '.' && bitset(RES_DNSRCH, _res.options)) { for (domain = _res.dnsrch; *domain != NULL; ) *dp++ = *domain++; } else if (n == 0 && bitset(RES_DEFNAMES, _res.options)) { *dp++ = _res.defdname; } else if (*cp == '.') { *cp = '\0'; } *dp = NULL; /* ** Now run through the search list for the name in question. */ mxmatch = NULL; qtype = T_ANY; for (dp = searchlist; *dp != NULL; ) { if (qtype == T_ANY) gotmx = FALSE; if (tTd(8, 5)) printf("getcanonname: trying %s.%s (%s)\n", host, *dp, qtype == T_ANY ? "ANY" : qtype == T_A ? "A" : qtype == T_MX ? "MX" : "???"); ret = res_querydomain(host, *dp, C_IN, qtype, &answer, sizeof(answer)); if (ret <= 0) { if (tTd(8, 7)) printf("\tNO: errno=%d, h_errno=%d\n", errno, h_errno); if (errno == ECONNREFUSED || h_errno == TRY_AGAIN) { /* the name server seems to be down */ h_errno = TRY_AGAIN; return FALSE; } if (h_errno != HOST_NOT_FOUND) { /* might have another type of interest */ if (qtype == T_ANY) { qtype = T_A; continue; } else if (qtype == T_A && !gotmx && trymx) { qtype = T_MX; continue; } } if (mxmatch != NULL) { /* we matched before -- use that one */ break; } /* otherwise, try the next name */ dp++; qtype = T_ANY; continue; } else if (tTd(8, 7)) printf("\tYES\n"); /* ** This might be a bogus match. Search for A or ** CNAME records. If we don't have a matching ** wild card MX record, we will accept MX as well. */ hp = (HEADER *) &answer; ap = (u_char *) &answer + HEADERSZ; eom = (u_char *) &answer + ret; /* skip question part of response -- we know what we asked */ for (qdcount = ntohs(hp->qdcount); qdcount--; ap += ret + QFIXEDSZ) { if ((ret = dn_skipname(ap, eom)) < 0) { if (tTd(8, 20)) printf("qdcount failure (%d)\n", ntohs(hp->qdcount)); return FALSE; /* ???XXX??? */ } } amatch = FALSE; for (ancount = ntohs(hp->ancount); --ancount >= 0 && ap < eom; ap += n) { n = dn_expand((u_char *) &answer, eom, ap, (u_char *) nbuf, sizeof nbuf); if (n < 0) break; ap += n; GETSHORT(type, ap); ap += SHORTSIZE + LONGSIZE; GETSHORT(n, ap); switch (type) { case T_MX: gotmx = TRUE; if (**dp != '\0') { /* got a match -- save that info */ if (trymx && mxmatch == NULL) mxmatch = *dp; continue; } /* exact MX matches are as good as an A match */ /* fall through */ case T_A: /* good show */ amatch = TRUE; /* continue in case a CNAME also exists */ continue; case T_CNAME: if (loopcnt++ > MAXCNAMEDEPTH) { /*XXX should notify postmaster XXX*/ message("DNS failure: CNAME loop for %s", host); if (CurEnv->e_message == NULL) { char ebuf[MAXLINE]; sprintf(ebuf, "Deferred: DNS failure: CNAME loop for %s", host); CurEnv->e_message = newstr(ebuf); } h_errno = NO_RECOVERY; return FALSE; } /* value points at name */ if ((ret = dn_expand((u_char *)&answer, eom, ap, (u_char *)nbuf, sizeof(nbuf))) < 0) break; (void)strncpy(host, nbuf, hbsize); /* XXX */ host[hbsize - 1] = '\0'; /* ** RFC 1034 section 3.6 specifies that CNAME ** should point at the canonical name -- but ** urges software to try again anyway. */ goto cnameloop; default: /* not a record of interest */ continue; } } if (amatch) { /* got an A record and no CNAME */ mxmatch = *dp; break; } /* ** If this was a T_ANY query, we may have the info but ** need an explicit query. Try T_A, then T_MX. */ if (qtype == T_ANY) qtype = T_A; else if (qtype == T_A && !gotmx && trymx) qtype = T_MX; else { /* really nothing in this domain; try the next */ qtype = T_ANY; dp++; } } if (mxmatch == NULL) return FALSE; /* create matching name and return */ (void) sprintf(nbuf, "%.*s%s%.*s", MAXDNAME, host, *mxmatch == '\0' ? "" : ".", MAXDNAME, mxmatch); strncpy(host, nbuf, hbsize); host[hbsize - 1] = '\0'; return TRUE;}char *gethostalias(host) char *host;{ char *fname; FILE *fp; register char *p; char buf[MAXLINE]; static char hbuf[MAXDNAME]; fname = getenv("HOSTALIASES"); if (fname == NULL || (fp = fopen(fname, "r")) == NULL) return NULL; while (fgets(buf, sizeof buf, fp) != NULL) { for (p = buf; p != '\0' && !(isascii(*p) && isspace(*p)); p++) continue; if (*p == 0) { /* syntax error */ continue; } *p++ = '\0'; if (strcasecmp(buf, host) == 0) break; } if (feof(fp)) { /* no match */ fclose(fp); return NULL; } /* got a match; extract the equivalent name */ while (*p != '\0' && isascii(*p) && isspace(*p)) p++; host = p; while (*p != '\0' && !(isascii(*p) && isspace(*p))) p++; *p = '\0'; strncpy(hbuf, host, sizeof hbuf - 1); hbuf[sizeof hbuf - 1] = '\0'; return hbuf;}#else /* not NAMED_BIND */#include <netdb.h>boolgetcanonname(host, hbsize, trymx) char *host; int hbsize; bool trymx;{ struct hostent *hp; hp = gethostbyname(host); if (hp == NULL) return (FALSE); if (strlen(hp->h_name) >= hbsize) return (FALSE); (void) strcpy(host, hp->h_name); return (TRUE);}#endif /* not NAMED_BIND */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -