brian@ucsd.Edu (Brian Kantor) (09/05/89)
We at UCSD run with at least two nameserver MX entries for every host on our Ethernet. The higher preference entry (usually 10) is for the host itself, and the lowest-preference (at 90) is for our campus mail gateway. We do this so that workstations can transfer mail directly, but if the destination is down, the mail will reach the gateway machine and spool there until the destination comes back up. It also allows systems without access from the outside world to receive incoming mail addressed directly to them, by letting it take a hop through the gateway when necessary. When delivering mail, sendmail checks to see if the MX host is the current host, and stops trying if it is. The problem is that the comparison is made between the MX host, which should be a fully-qualified domain name returned from the nameserver, and the local hostname as defined by the "$w" macro. Depending upon how you have your sendmail.cf set up, "$w" might well be a simple name, not in fully qualified domain style (i.e., "spudboy"). This is because $w is set to your hostname, as returned by the 'gethostname' call. On a typical Sun, for example, the hostname is simple. On most BSD-Tahoe systems, hostname is set to the FQDN (i.e., "spudboy.ucsd.edu"). If the MX hostname is not recognized as the local host, sendmail will attempt to connect to itself and puke badly. In former days, this yielded the justly-infamous "I refuse to talk to myself" message, which for the sake of incompatability and added confusion is now "Local configuration error, hostname not recognized as local". To make this work portably, the name passed into 'getmxrr' as the local hostname should be run once through the name server to obtain its canonical name before doing the comparison. The patch below does this. There are also some other minor changes to improve debugging output and for Sunix compatability. Brian Kantor UCSD Office of Academic Computing Academic Network Operations Group UCSD C-010, La Jolla, CA 92093 USA brian@ucsd.edu ucsd!brian BRIAN@UCSD ------ *** ../virgin/domain.c Sun Jan 1 17:18:06 1989 --- ./domain.c Mon Sep 4 12:27:27 1989 *************** *** 34,39 **** --- 34,47 ---- #include <resolv.h> #include <netdb.h> + #ifndef NO_DATA + #define NO_DATA NO_ADDRESS + #endif + + #ifndef EX_CONFIG + #define EX_CONFIG EX_OSFILE + #endif + typedef union { HEADER qb1; char qb2[PACKETSZ]; *************** *** 53,59 **** --- 61,77 ---- querybuf answer; int ancount, qdcount, buflen, seenlocal; u_short pref, localpref, type, prefer[MAXMXHOSTS]; + char localhostfqdn[MAXNAME]; + if (tTd(8, 1)) + printf("getmxrr: res_search(host=`%s',MX)\n", host); + + localpref = 0; + strcpy(localhostfqdn, localhost); + getcanonname(localhostfqdn, MAXNAME); + if (tTd(8, 2)) + printf("getmxrr:\tlocalhost=`%s'\n", localhostfqdn); + errno = 0; n = res_search(host, C_IN, T_MX, (char *)&answer, sizeof(answer)); if (n < 0) *************** *** 117,123 **** if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) break; cp += n; ! if (!strcasecmp(bp, localhost)) { if (seenlocal == 0 || pref < localpref) localpref = pref; seenlocal = 1; --- 135,143 ---- if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) break; cp += n; ! if (tTd(8, 2)) ! printf("getmxrr: MX '%s' = %d\n", bp, pref); ! if (!strcasecmp(bp, localhostfqdn)) { if (seenlocal == 0 || pref < localpref) localpref = pref; seenlocal = 1; *************** *** 190,197 **** --- 210,221 ---- * to match as names in a local domain. */ # ifdef NO_WILDCARD_MX + if (tTd(8, 1)) + printf("getmxrr: res_search(host=`%s',ANY)\n", host); n = res_search(host, C_IN, T_ANY, (char *)&answer, sizeof(answer)); # else + if (tTd(8, 1)) + printf("getmxrr: res_search(host=`%s',CNAME)\n", host); n = res_search(host, C_IN, T_CNAME, (char *)&answer, sizeof(answer)); # endif if (n < 0) {