[comp.soft-sys.andrew] fix to overhead/mail/lib/valhost.c

janssen@ARISIA.XEROX.COM (08/08/89)

When I moved over to a sun-4, I noticed that address validation of outgoing
mail messages ceased working, even for things like "xerox.com"!  I found that
the file overhead/mail/lib/valhost.c has a conditionally compiled define
that is broken on one case.  The function "dn_skipname" should be invoked
with two arguments, not just one.  You will not see this error unless you are
running "bind distribution 4.7.3" or later of the nameserver domain resolver
code.

My patch to valhost.c to fix is larger than it should be, because the union
used to define the type "querybuf" looked suspicious in a SPARC environment:

--- valhost.c	Mon Aug  7 19:29:19 1989
***************
*** 42,51 ****
  extern int errno;
  
  #if RESOLVER_ENV
! typedef union {
! 	HEADER qb1;
! 	char qb2[PACKETSZ*3];
! } querybuf;
  
  /* Return values from GetRec */
  #define NoDomain 1	/* Definite negative */
--- 42,48 ----
  extern int errno;
  
  #if RESOLVER_ENV
! typedef char querybuf[PACKETSZ*3];
  
  /* Return values from GetRec */
  #define NoDomain 1	/* Definite negative */
***************
*** 86,92 ****
  char *OutN; int sizeOutN; char *OutFwd; int sizeOutFwd;
  {
  	HEADER *hp;
! 	char *eom, *cp;
  	querybuf answer;
  	int n, ancount, qdcount;
  	u_short type, class;
--- 83,89 ----
  char *OutN; int sizeOutN; char *OutFwd; int sizeOutFwd;
  {
  	HEADER *hp;
! 	char *eom, *cp, *msg;
  	querybuf answer;
  	int n, ancount, qdcount;
  	u_short type, class;
***************
*** 93,105 ****
  	char nbuf[BUFSIZ];
  	int first, AnyAnswers, thisPref, minPref, n1, ancountOrig;
  
! 	n = res_search(InName, C_IN, wantedType, (char *)&answer, sizeof(answer));
  	if (n < 0) return TryAgain;
! 	eom = (char *)&answer + n;
  	/*
  	 * find first satisfactory answer
  	 */
! 	hp = (HEADER *) &answer;
  	ancount = ntohs(hp->ancount);
  	qdcount = ntohs(hp->qdcount);
  	if (hp->rcode != NOERROR || ancount == 0) {
--- 90,103 ----
  	char nbuf[BUFSIZ];
  	int first, AnyAnswers, thisPref, minPref, n1, ancountOrig;
  
! 	n = res_search(InName, C_IN, wantedType, (char *)answer, sizeof(answer));
  	if (n < 0) return TryAgain;
! 	eom = (char *)answer + n;
  	/*
  	 * find first satisfactory answer
  	 */
! 	hp = (HEADER *) answer;
! 	msg = (char *) answer;
  	ancount = ntohs(hp->ancount);
  	qdcount = ntohs(hp->qdcount);
  	if (hp->rcode != NOERROR || ancount == 0) {
***************
*** 124,150 ****
  			return TryAgain;
  		}
  	}
! 	cp = (char *)&answer + sizeof(HEADER);
  	if (qdcount) {
! #ifndef dn_SKIPNAME
! #ifdef CQUERYM
! /* Version 4.7.3 of the Bind distribution changed the function name dn_skip to dn_skipname.
!   Another thing that changed at that point was whether the old CQUERYM flag was defined in /usr/include/arpa/nameser.h; it became STATUS with 4.7.3.
!   We hope that one of [CQUERYM/dn_skip] and [STATUS/dn_skipname] is the pairing on your system.  But if it isn't, you need only define dn_SKIPNAME to be whichever is appropriate. */
! #define dn_SKIPNAME dn_skip
! #else CQUERYM
! #define dn_SKIPNAME dn_skipname
! #endif CQUERYM
! #endif dn_SKIPNAME
! 		cp += dn_SKIPNAME(cp) + QFIXEDSZ;
  		while (--qdcount > 0)
! 			cp += dn_SKIPNAME(cp) + QFIXEDSZ;
  	}
  	first = 1; AnyAnswers = 0; minPref = 100000;
  	ancountOrig = ancount;
  	while (--ancount >= 0 && cp < eom) {
! 		if ((n = dn_expand((char *)&answer, eom, cp, nbuf,
! 		    sizeof(nbuf))) < 0) break;
  		cp += n;
  		type = get_ushort(cp);
   		cp += sizeof(u_short);
--- 122,137 ----
  			return TryAgain;
  		}
  	}
! 	cp = msg + sizeof(HEADER);
  	if (qdcount) {
! 		cp += dn_skipname(cp,eom) + QFIXEDSZ;
  		while (--qdcount > 0)
! 			cp += dn_skipname(cp,eom) + QFIXEDSZ;
  	}
  	first = 1; AnyAnswers = 0; minPref = 100000;
  	ancountOrig = ancount;
  	while (--ancount >= 0 && cp < eom) {
! 		if ((n = dn_expand(msg, eom, cp, nbuf, sizeof(nbuf))) < 0) break;
  		cp += n;
  		type = get_ushort(cp);
   		cp += sizeof(u_short);
***************
*** 165,171 ****
  #endif myRES_OPTS
  					)) {
  /* The first CNAME found, which should be the only one, is good enough. */
! 			if ((n = dn_expand((char *)&answer, eom, cp, nbuf,
  			    sizeof(nbuf))) < 0) break;
  			(void)strncpy(OutN, nbuf, sizeOutN);
  			OutN[sizeOutN - 1] = '\0';
--- 152,158 ----
  #endif myRES_OPTS
  					)) {
  /* The first CNAME found, which should be the only one, is good enough. */
! 			if ((n = dn_expand(msg, eom, cp, nbuf,
  			    sizeof(nbuf))) < 0) break;
  			(void)strncpy(OutN, nbuf, sizeOutN);
  			OutN[sizeOutN - 1] = '\0';
***************
*** 179,185 ****
  			thisPref = get_ushort(cp);
  			if (thisPref < minPref) {
  			    cp += sizeof(u_short);	/* advance pointer to the MX host */
! 			    n1 = dn_expand((char *)&answer, eom, cp, nbuf, sizeof(nbuf));
  			    cp -= sizeof(u_short);	/* put the pointer back */
  			    if (n1 < 0) break;
  			    n1 = sizeOutFwd;
--- 166,172 ----
  			thisPref = get_ushort(cp);
  			if (thisPref < minPref) {
  			    cp += sizeof(u_short);	/* advance pointer to the MX host */
! 			    n1 = dn_expand(msg, eom, cp, nbuf, sizeof(nbuf));
  			    cp -= sizeof(u_short);	/* put the pointer back */
  			    if (n1 < 0) break;
  			    n1 = sizeOutFwd;