text: /*
   * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
   * Copyright (c) 1995,1999 by Internet Software Consortium.
   *
   * Permission to use, copy, modify, and distribute this software for any
   * purpose with or without fee is hereby granted, provided that the above
   * copyright notice and this permission notice appear in all copies.
   *
   * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
   * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
   * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
   * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
   * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
   * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
   * SOFTWARE.
   */
  
  #if !defined(_LIBC) && !defined(lint)
  static const char rcsid[] = "$BINDId: ns_samedomain.c,v 8.9 1999/10/15 21:06:51 vixie Exp $";
  #endif
  
  #include <sys/types.h>
  #include <arpa/nameser.h>
  #include <errno.h>
  #include <string.h>
  
  /*%
   *	Check whether a name belongs to a domain.
   *
   * Inputs:
   *\li	a - the domain whose ancestory is being verified
   *\li	b - the potential ancestor we're checking against
   *
   * Return:
   *\li	boolean - is a at or below b?
   *
   * Notes:
   *\li	Trailing dots are first removed from name and domain.
   *	Always compare complete subdomains, not only whether the
   *	domain name is the trailing string of the given name.
   *
   *\li	"host.foobar.top" lies in "foobar.top" and in "top" and in ""
   *	but NOT in "bar.top"
   */
  
  int
  ns_samedomain(const char *a, const char *b) {
  	size_t la, lb;
  	int diff, i, escaped;
  	const char *cp;
  
  	la = strlen(a);
  	lb = strlen(b);
  
  	/* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */
  	if (la != 0U && a[la - 1] == '.') {
  		escaped = 0;
  		/* Note this loop doesn't get executed if la==1. */
  		for (i = la - 2; i >= 0; i--)
  			if (a[i] == '\\') {
  				if (escaped)
  					escaped = 0;
  				else
  					escaped = 1;
  			} else
  				break;
  		if (!escaped)
  			la--;
  	}
  
  	/* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */
  	if (lb != 0U && b[lb - 1] == '.') {
  		escaped = 0;
  		/* note this loop doesn't get executed if lb==1 */
  		for (i = lb - 2; i >= 0; i--)
  			if (b[i] == '\\') {
  				if (escaped)
  					escaped = 0;
  				else
  					escaped = 1;
  			} else
  				break;
  		if (!escaped)
  			lb--;
  	}
  
  	/* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */
  	if (lb == 0U)
  		return (1);
  
  	/* 'b' longer than 'a' means 'a' can't be in 'b'. */
  	if (lb > la)
  		return (0);
  
  	/* 'a' and 'b' being equal at this point indicates sameness. */
  	if (lb == la)
  		return (strncasecmp(a, b, lb) == 0);
  
  	/* Ok, we know la > lb. */
  
  	diff = la - lb;
  
  	/*
  	 * If 'a' is only 1 character longer than 'b', then it can't be
  	 * a subdomain of 'b' (because of the need for the '.' label
  	 * separator).
  	 */
  	if (diff < 2)
  		return (0);
  
  	/*
  	 * If the character before the last 'lb' characters of 'b'
  	 * isn't '.', then it can't be a match (this lets us avoid
  	 * having "foobar.com" match "bar.com").
  	 */
  	if (a[diff - 1] != '.')
  		return (0);
  
  	/*
  	 * We're not sure about that '.', however.  It could be escaped
           * and thus not a really a label separator.
  	 */
  	escaped = 0;
  	for (i = diff - 2; i >= 0; i--)
  		if (a[i] == '\\') {
  			if (escaped)
  				escaped = 0;
  			else
  				escaped = 1;
  		} else
  			break;
  	if (escaped)
  		return (0);
  
  	/* Now compare aligned trailing substring. */
  	cp = a + diff;
  	return (strncasecmp(cp, b, lb) == 0);
  }
  libresolv_hidden_def (ns_samedomain)
  
  /*%
   *	is "a" a subdomain of "b"?
   */
  int
  ns_subdomain(const char *a, const char *b) {
  	return (ns_samename(a, b) != 1 && ns_samedomain(a, b));
  }
  
  /*%
   *	make a canonical copy of domain name "src"
   *
   * notes:
   * \code
   *	foo -> foo.
   *	foo. -> foo.
   *	foo.. -> foo.
   *	foo\. -> foo\..
   *	foo\\. -> foo\\.
   * \endcode
   */
  
  int
  ns_makecanon(const char *src, char *dst, size_t dstsize) {
  	size_t n = strlen(src);
  
  	if (n + sizeof "." > dstsize) {			/*%< Note: sizeof == 2 */
  		__set_errno (EMSGSIZE);
  		return (-1);
  	}
  	strcpy(dst, src);
  	while (n >= 1U && dst[n - 1] == '.')		/*%< Ends in "." */
  		if (n >= 2U && dst[n - 2] == '\\' &&	/*%< Ends in "\." */
  		    (n < 3U || dst[n - 3] != '\\'))	/*%< But not "\\." */
  			break;
  		else
  			dst[--n] = '\0';
  	dst[n++] = '.';
  	dst[n] = '\0';
  	return (0);
  }
  libresolv_hidden_def (ns_makecanon)
  
  /*%
   *	determine whether domain name "a" is the same as domain name "b"
   *
   * return:
   *\li	-1 on error
   *\li	0 if names differ
   *\li	1 if names are the same
   */
  
  int
  ns_samename(const char *a, const char *b) {
  	char ta[NS_MAXDNAME], tb[NS_MAXDNAME];
  
  	if (ns_makecanon(a, ta, sizeof ta) < 0 ||
  	    ns_makecanon(b, tb, sizeof tb) < 0)
  		return (-1);
  	if (strcasecmp(ta, tb) == 0)
  		return (1);
  	else
  		return (0);
  }
  libresolv_hidden_def (ns_samename)
  
  /*! \file */
  