+ 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 + HFIXEDSZ;
+ 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));
+ *statp = EX_SOFTWARE;
+ return FALSE; /* ???XXX??? */
+ }
+ }
+
+ amatch = FALSE;
+ for (ancount = ntohs(hp->ancount); --ancount >= 0 && ap < eom; ap += n)
+ {
+ n = dn_expand((u_char *) &answer, eom, ap,
+ (RES_UNC_T) nbuf, sizeof nbuf);
+ if (n < 0)
+ break;
+ ap += n;
+ GETSHORT(type, ap);
+ ap += INT16SZ + INT32SZ;
+ GETSHORT(n, ap);
+ switch (type)
+ {
+ case T_MX:
+ gotmx = TRUE;
+ if (**dp != '\0' || !HasWildcardMX)
+ {
+ /* 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 (DontExpandCnames)
+ {
+ /* got CNAME -- guaranteed canonical */
+ amatch = TRUE;
+ break;
+ }
+
+ 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;
+ *statp = EX_CONFIG;
+ return FALSE;
+ }
+
+ /* value points at name */
+ if ((ret = dn_expand((u_char *)&answer,
+ eom, ap, (RES_UNC_T) 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++;
+ }