salzman@randvax.UUCP (Isaac Salzman) (02/08/89)
The following patches will make sendmail 5.61+IDA handle host name resolution with BIND in a reasonable manner (at least in my opinion :-). The problem is with maphostname(). IDA likes to use gethostbyname() to do the job, which is insufficient for hosts that only have MX records. You'll end up getting a pathalias path for those hosts (assuming you're using IDA with it's sendmail.cf and a pathalias database) instead of using the MX record, which defeats to purpose of MX records all together. Lennart noted the following problem with using the supplied getcanonname() instead of gethostbyname(): /* from domain.c */ /* ** Getcanonname() below is broken in the sense that it won't return ** unqualified local host names with their full domain extension, ** unless the argument is an alias. ** ** Since gethostbyname() calls the name server with bind 4.8, ** I don't see why this function would be needed at all. I've ** therefore restored the old code in maphostname() of daemon.c ** that uses gethostbyname(). If there's something I've missed, ** feel free to change maphostname() to again call getcanonname(), ** but also make sure that the latter will qualify the host with ** its full domain AND return a status code indicating if the host ** was found. ** ** Lennart Lovstrand, Rank Xerox EuroPARC, 24-Aug-88 */ As he's suggested, I've modified maphostname() and getcanonname(). I did not get rid of the call to gethostbyname(). Instead, I look at h_errno after calling gethostbyname() to determine whether or not to bother calling getcanonname(). This solves the problem of returning FQDN's for local host names. If gethostbyname() fails and h_errno contains NO_DATA/NO_ADDRESS (the same), it will try getcanonname(), which will work for MX only sites (since it does a T_ANY query). For this to work you need the following in conf.h: #define NO_WILDCARD_MX 1 /* to use T_ANY instead of T_CNAME in getcanonname() */ #define GETHOSTBYNAME_ISNT_ENOUGH 1 /* to call getcanonname() in addition to gethostbyname() in maphostname() */ These patches were made to the port of IDA 1.2.8 to sendmail 5.61 that's available for ftp on gatekeeper.dec.com (sendmail.5.61.ida.tar.Z). If there's a better (or more proper) way to handle this, I'd really like to hear about it. Likewise if there are any problems. It would be nice to see these patches find their way into future releases of IDA (I once sent them to Lennart, but I think they ended up in /dev/null :-). Enjoy! [ Apply patches in src directory. Files effected: domain.c, daemon.c. Watch out for the .signature at the end of the message. ] *** domain.c.ORIG Thu Jan 26 07:50:59 1989 --- domain.c Tue Feb 7 13:42:34 1989 *************** *** 215,221 **** if (tTd(8, 1)) printf("getcanonname: res_search failed (errno=%d, h_errno=%d)\n", errno, h_errno); ! return; } /* find first satisfactory answer */ --- 215,221 ---- if (tTd(8, 1)) printf("getcanonname: res_search failed (errno=%d, h_errno=%d)\n", errno, h_errno); ! return FALSE; } /* find first satisfactory answer */ *************** *** 226,238 **** if (ancount == 0) { if (tTd(8, 1)) printf("rcode = %d, ancount=%d\n", hp->rcode, ancount); ! return; } cp = (u_char *)&answer + sizeof(HEADER); eom = (u_char *)&answer + n; for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ) if ((n = dn_skipname(cp, eom)) < 0) ! return; /* * just in case someone puts a CNAME record after another record, --- 226,238 ---- if (ancount == 0) { if (tTd(8, 1)) printf("rcode = %d, ancount=%d\n", hp->rcode, ancount); ! return FALSE; } cp = (u_char *)&answer + sizeof(HEADER); eom = (u_char *)&answer + n; for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ) if ((n = dn_skipname(cp, eom)) < 0) ! return FALSE; /* * just in case someone puts a CNAME record after another record, *************** *** 264,275 **** (void)strncpy(host, nbuf, hbsize); /* XXX */ host[hbsize - 1] = '\0'; if (++loopcnt > 8) /* never be more than 1 */ ! return; goto loop; } ! } } - #endif GETHOSTBYNAME_ISNT_ENOUGH #else /* not NAMED_BIND */ --- 264,276 ---- (void)strncpy(host, nbuf, hbsize); /* XXX */ host[hbsize - 1] = '\0'; if (++loopcnt > 8) /* never be more than 1 */ ! return FALSE; goto loop; } ! } ! return TRUE; ! } #else /* not NAMED_BIND */ *************** *** 283,294 **** hp = gethostbyname(host); if (hp == NULL) ! return; if (strlen(hp->h_name) >= hbsize) ! return; (void) strcpy(host, hp->h_name); } #endif /* not NAMED_BIND */ --- 284,298 ---- 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 */ + + #endif /* GETHOSTBYNAME_ISNT_ENOUGH */ *** daemon.c.ORIG Tue Feb 7 11:09:29 1989 --- daemon.c Tue Feb 7 14:06:14 1989 *************** *** 521,526 **** --- 521,528 ---- register struct hostent *hp; extern struct hostent *gethostbyname(); static char tmphbuf[MAXNAME]; + extern int h_errno; + int status; /* * If first character is a bracket, then it is an address *************** *** 540,556 **** else { hp = gethostbyname(hbuf); ! if (hp == NULL) { ! /* try lowercase version */ ! (void) strcpy(tmphbuf, hbuf); ! (void) makelower(tmphbuf); } } ! if (tTd(9, 1)) ! printf("maphostname(%s, %d) => %.*s\n", ! hbuf, hbsize, hbsize-1, hp ? hp->h_name : "NOT_FOUND"); if (hp == NULL) ! return FALSE; if (strlen(hp->h_name) >= hbsize) hp->h_name[hbsize - 1] = '\0'; --- 542,580 ---- else { hp = gethostbyname(hbuf); ! if (tTd(9, 1)) ! printf("maphostname [gethostbyname(%s)] => %.*s (%d)\n", ! hbuf, hbsize-1, ! hp ? hp->h_name : "NOT_FOUND", h_errno); ! ! #if defined(GETHOSTBYNAME_ISNT_ENOUGH) && defined(NAMED_BIND) ! if (hp == NULL) ! { ! switch(h_errno) ! { ! case HOST_NOT_FOUND: ! case NO_RECOVERY: ! return FALSE; ! case TRY_AGAIN: ! /* could either return FALSE or fall through and try ! getcanonname() for this case. I choose to return.... ! */ ! return FALSE; ! default: /* NO_DATA, NO_ADDRESS, try a T_CNAME or T_ANY query */ ! status = getcanonname(hbuf, hbsize); ! if (tTd(9, 1)) ! printf("maphostname [getcanonname(%s,%d)] => %.*s\n", ! hbuf, hbsize, hbsize-1, ! (status == FALSE) ? "NOT_FOUND" : hbuf); ! ! return (status == FALSE) ? FALSE : TRUE; ! } } + #endif /* defined(GETHOSTBYNAME_ISNT_ENOUGH) && defined(NAMED_BIND) */ } ! if (hp == NULL) ! return FALSE; if (strlen(hp->h_name) >= hbsize) hp->h_name[hbsize - 1] = '\0'; -- * Isaac J. Salzman ---- * The RAND Corporation - Information Sciences Dept. /o o/ / * 1700 Main St., PO Box 2138, Santa Monica, CA 90406-2138 | v | | * AT&T: +1 213-393-0411 x6421 or x7923 (ISL lab) _| |_/ * ARPA: salzman@RAND.ORG or salzman@rand-unix.ARPA / | | * UUCP: ...!{cbosgd,decvax,sdcrdcf}!randvax!salzman | | |
vixie@decwrl.dec.com (Paul A Vixie) (02/12/89)
I've been hacking IDA sendmail to make it find MX records in maphostname() since Len released his first version. I now realize that for unconnected sites (no SMTP or DNS) this is wrong and in fact, Len's method is better. Rathewr than #ifdef'ing it, can someone add a config-file option? And preferrably convince Len to buy back the change so I don't have to maintain hacked source? More and more I am convinced that sendmail is a solution in search of a problem. This is all too complex. -- Paul Vixie Work: vixie@decwrl.dec.com decwrl!vixie +1 415 853 6600 Play: paul@vixie.sf.ca.us vixie!paul +1 415 864 7013