[comp.mail.sendmail] sendmail 5.61 MX wierdness

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) {