RCS file: RCS/res_init.c,v
retrieving revision 1.1
diff -c -r1.1 res_init.c
*** /tmp/,RCSt1008200	Fri May 17 19:35:38 1991
--- res_init.c	Fri May 17 19:07:48 1991
***************
*** 60,65 ****
--- 60,66 ----
  	extern char *strcpy(), *strncpy();
  	extern char *getenv();
  	int nserv = 0;    /* number of nameserver records read from file */
+ 	int ntoplvl = 0;  /* number of toplevel records read from file  */
  	int haveenv = 0;
  	int havesearch = 0;
  
***************
*** 126,131 ****
--- 127,164 ----
  		    *cp = '\0';
  		    *pp++ = 0;
  		    havesearch = 1;
+ 		    continue;
+ 		}
+ 		/* read top level domains */
+ 		if (!strncmp(buf, "toplevel", sizeof("toplevel") - 1) &&
+ 		   ntoplvl < MAXTOPLEVEL) {
+ 		    static char tlbuf[1024];
+ 		    static int tbfill = 0;
+ 		    register char *dp;
+ 		    
+ 		    cp = buf + sizeof("toplevel") - 1;
+ 		    while (*cp == ' ' || *cp == '\t')
+ 			    cp++;
+ 		    if ((*cp == '\0') || (*cp == '\n'))
+ 			    continue;
+ 		    /* null terminate argument if there's cruft afterwards */
+ 		    for (dp = cp;
+ 			 (*dp!='\0' && *dp!=' ' && *dp!='\t' && *dp!='\n') ;)
+ 			    dp++;
+ 		    *dp = '\0';
+ 
+ 		    if ((tbfill + strlen(cp) + 1) < sizeof (tlbuf)) {
+ 			    strcpy((_res.toplvl[ntoplvl] = (tlbuf + tbfill)),
+ 				   cp);
+ 			    tbfill += strlen(cp) + 1;
+ 			    ntoplvl++;
+ 		    }
+ #ifdef DEBUG
+ 		    else if (_res.options & RES_DEBUG) {
+ 			    printf("Out of tlbuf space while reading %s\n",
+ 				   _PATH_RESCONF);
+ 		    }
+ #endif DEBUG
  		    continue;
  		}
  		/* read nameservers to query */
RCS file: RCS/res_query.c,v
retrieving revision 1.1
diff -c -r1.1 res_query.c
*** /tmp/,RCSt1008205	Fri May 17 19:35:45 1991
--- res_query.c	Fri May 17 19:34:53 1991
***************
*** 39,44 ****
--- 39,63 ----
  #define MAXPACKET	1024
  #endif
  
+ /*
+  * TOP_LEVEL_CHECK uses the toplevel declarations in /etc/resolv.conf
+  * to see if the last component matches one of the toplevel domains.
+  * If so, res_search skips doing the domain searching for that name.
+  *
+  * SUFFIX_CHECK is a quick hack which skips doing a query when trying
+  * to append a domain to a hostname which has the domain appended to
+  * it already.
+  *
+  * TOP_LEVEL_CHECK is a better check, since it completely solves the
+  * problem of needless queries (the case of UUNET.UU.NET.MIT.EDU), as
+  * opposed to only stopping needless queries in the local domain (the
+  * case of KERBEROS.MIT.EDU.MIT.EDU).  The one advantage of
+  * SUFFIX_CHECK is that you don't need to add toplevel declarations to
+  * /etc/resolv.conf.
+  */
+ #define SUFFIX_CHECK
+ #define TOP_LEVEL_CHECK
+ 
  extern int errno;
  int h_errno;
  
***************
*** 133,138 ****
--- 152,161 ----
  {
  	register char *cp, **domain;
  	int n, ret, got_nodata = 0;
+ #ifdef TOP_LEVEL_CHECK
+ 	char *last_component = 0;
+ #endif
+ 	int	is_toplevel = 0;
  	char *hostalias();
  
  	if ((_res.options & RES_INIT) == 0 && res_init() == -1)
***************
*** 141,159 ****
  	errno = 0;
  	h_errno = HOST_NOT_FOUND;		/* default, if we never query */
  	for (cp = name, n = 0; *cp; cp++)
! 		if (*cp == '.')
  			n++;
  	if (n == 0 && (cp = hostalias(name)))
  		return (res_query(cp, class, type, answer, anslen));
  
  	/*
  	 * We do at least one level of search if
  	 *	- there is no dot and RES_DEFNAME is set, or
  	 *	- there is at least one dot, there is no trailing dot,
! 	 *	  and RES_DNSRCH is set.
  	 */
  	if ((n == 0 && _res.options & RES_DEFNAMES) ||
! 	   (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH))
  	     for (domain = _res.dnsrch; *domain; domain++) {
  		ret = res_querydomain(name, *domain, class, type,
  		    answer, anslen);
--- 164,206 ----
  	errno = 0;
  	h_errno = HOST_NOT_FOUND;		/* default, if we never query */
  	for (cp = name, n = 0; *cp; cp++)
! 		if (*cp == '.') {
! #ifdef TOP_LEVEL_CHECK
! 			last_component = cp;
! #endif
  			n++;
+ 		}
  	if (n == 0 && (cp = hostalias(name)))
  		return (res_query(cp, class, type, answer, anslen));
  
+ #ifdef TOP_LEVEL_CHECK
  	/*
+ 	 * Let's check to see if the last component matches one of the
+ 	 * top level domains.
+ 	 * [tytso:19910517.1934EDT]
+ 	 */
+ 	if (last_component)
+ 		last_component++; /* past the last dot */
+ 	if (last_component && *last_component) {
+ 		for (domain=_res.toplvl ;*domain;domain++) {
+ 			if (! strcasecmp(*domain,last_component)) {
+ 				is_toplevel++;
+ 				break;
+ 			}
+ 		}
+ 	}
+ #endif
+ 
+ 	/*
  	 * We do at least one level of search if
  	 *	- there is no dot and RES_DEFNAME is set, or
  	 *	- there is at least one dot, there is no trailing dot,
! 	 *	  the last component wasn't a toplevel domain,
! 	 * 	  and RES_DNSRCH is set.
  	 */
  	if ((n == 0 && _res.options & RES_DEFNAMES) ||
! 	    (n != 0 && *--cp != '.' && !is_toplevel &&
! 	     _res.options & RES_DNSRCH))
  	     for (domain = _res.dnsrch; *domain; domain++) {
  		ret = res_querydomain(name, *domain, class, type,
  		    answer, anslen);
***************
*** 226,234 ****
  			nbuf[n] = '\0';
  		} else
  			longname = name;
! 	} else
  		(void)sprintf(nbuf, "%.*s.%.*s",
  		    MAXDNAME, name, MAXDNAME, domain);
  
  	return (res_query(longname, class, type, answer, anslen));
  }
--- 273,298 ----
  			nbuf[n] = '\0';
  		} else
  			longname = name;
! 	} else {
! #ifdef SUFFIX_CHECK
! 		/*
! 		 * Check to see if the domain that we're about to
! 		 * append is already present as the suffix of name.
! 		 * If so, assume that adding the suffix will be a
! 		 * waste of time.... so punt.
! 		 * [tytso:19901024.1625EDT]
! 		 */
! 		int	offset = strlen(name) - strlen(domain);
! 		
! 		if ((offset >= 0 ) && !strcasecmp(name+offset, domain) &&
! 		    ((offset == 0) || (*(name+offset-1)=='.')))
! 			return(-1); /* Tell res_search to try again */
! #endif
! 		
  		(void)sprintf(nbuf, "%.*s.%.*s",
  		    MAXDNAME, name, MAXDNAME, domain);
+ 	}
+ 	
  
  	return (res_query(longname, class, type, answer, anslen));
  }
RCS file: RCS/resolv.h,v
retrieving revision 1.1
diff -c -r1.1 resolv.h
*** /tmp/,RCSt1008226	Fri May 17 19:37:13 1991
--- resolv.h	Fri May 17 19:36:59 1991
***************
*** 35,40 ****
--- 35,41 ----
  #define	MAXNS		3		/* max # name servers we'll track */
  #define	MAXDFLSRCH	3		/* # default domain levels to try */
  #define	MAXDNSRCH	6		/* max # domains in search path */
+ #define MAXTOPLEVEL	16		/* max # of toplevel specifications */
  #define	LOCALDOMAINPARTS 2		/* min levels in name that is "local" */
  
  #define	RES_TIMEOUT	5		/* min. seconds between retries */
***************
*** 49,54 ****
--- 50,56 ----
  	u_short	id;			/* current packet id */
  	char	defdname[MAXDNAME];	/* default domain */
  	char	*dnsrch[MAXDNSRCH+1];	/* components of domain to search */
+ 	char	*toplvl[MAXTOPLEVEL+1];	/* top-level domains */
  };
  
  /*
