DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T u

⟦2a8e11a55⟧ TextFile

    Length: 13435 (0x347b)
    Types: TextFile
    Names: »uk.domain.c«

Derivation

└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
    └─⟦bfebc70e2⟧ »EurOpenD3/mail/sendmail-5.65b+IDA-1.4.3.tar.Z« 
        └─⟦f9e35cd84⟧ 
            └─⟦this⟧ »sendmail/uk.extras/uk.domain.c« 

TextFile

/*
 * Copyright (c) 1986 Eric P. Allman
 * Copyright (c) 1988 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted provided
 * that: (1) source distributions retain this entire copyright notice and
 * comment, and (2) distributions including binaries display the following
 * acknowledgement:  ``This product includes software developed by the
 * University of California, Berkeley and its contributors'' in the
 * documentation or other materials provided with the distribution and in
 * all advertising materials mentioning features or use of this software.
 * Neither the name of the University nor the names of its contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "sendmail.h"

#ifndef lint
# ifdef NAMED_BIND
static char sccsid[] = "@(#)domain.c	5.22 (Berkeley) 6/1/90 (with name server)";
# else /* !NAMED_BIND */
static char sccsid[] = "@(#)domain.c	5.22 (Berkeley) 6/1/90 (without name server)";
# endif /* NAMED_BIND */
#endif /* not lint */

#ifdef NAMED_BIND

# include <sys/param.h>
# include <errno.h>
# include <arpa/nameser.h>
# include <resolv.h>
# include <netdb.h>

typedef union {
	HEADER qb1;
	char qb2[PACKETSZ];
} querybuf;

extern int h_errno;
static char hostbuf[MAXMXHOSTS*PACKETSZ];

getmxrr(host, mxhosts, localhost, rcode)
	char *host, **mxhosts, *localhost;
	int *rcode;
{
	register u_char *eom, *cp;
	register int i, j, n, nmx;
	register char *bp;
	HEADER *hp;
	querybuf answer;
	int ancount, qdcount, buflen, seenlocal;
	u_short pref, localpref, type, prefer[MAXMXHOSTS];

	errno = 0;
	n = res_search(host, C_IN, T_MX, (char *)&answer, sizeof(answer));
	if (n < 0)
	{
		if (tTd(8, 1))
			printf("getmxrr: res_search failed (errno=%d, h_errno=%d)\n",
			    errno, h_errno);
		switch (h_errno)
		{
# ifndef NO_DATA
#  define NO_DATA	NO_ADDRESS
# endif /* NO_DATA */
		  case NO_DATA:
		  case NO_RECOVERY:
			/* no MX data on this host */
			goto punt;

		  case HOST_NOT_FOUND:
			/* the host just doesn't exist */
			*rcode = EX_NOHOST;
			break;

		  case TRY_AGAIN:
			/* couldn't connect to the name server */
			if (!UseNameServer && errno == ECONNREFUSED)
				goto punt;

			/* it might come up later; better queue it up */
			*rcode = EX_TEMPFAIL;
			break;
		}

		/* irreconcilable differences */
		return (-1);
	}

	/* find first satisfactory answer */
	hp = (HEADER *)&answer;
	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)
			goto punt;
	nmx = 0;
	seenlocal = 0;
	buflen = sizeof(hostbuf);
	bp = hostbuf;
	ancount = ntohs(hp->ancount);
	while (--ancount >= 0 && cp < eom && nmx < MAXMXHOSTS) {
		if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0)
			break;
		cp += n;
		GETSHORT(type, cp);
 		cp += sizeof(u_short) + sizeof(u_long);
		GETSHORT(n, cp);
		if (type != T_MX)  {
			if (tTd(8, 1) || _res.options & RES_DEBUG)
				printf("unexpected answer type %d, size %d\n",
				    type, n);
			cp += n;
			continue;
		}
		GETSHORT(pref, cp);
		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;
			continue;
		}
		prefer[nmx] = pref;
		mxhosts[nmx++] = bp;
		n = strlen(bp) + 1;
		bp += n;
		buflen -= n;
	}
	if (nmx == 0) {
punt:		mxhosts[0] = strcpy(hostbuf, host);
		return(1);
	}

	/* sort the records */
	for (i = 0; i < nmx; i++) {
		for (j = i + 1; j < nmx; j++) {
			if (prefer[i] > prefer[j] ||
			    (prefer[i] == prefer[j] && (rand()/3 & 1) == 0)) {
				register int temp;
				register char *temp1;

				temp = prefer[i];
				prefer[i] = prefer[j];
				prefer[j] = temp;
				temp1 = mxhosts[i];
				mxhosts[i] = mxhosts[j];
				mxhosts[j] = temp1;
			}
		}
		if (seenlocal && prefer[i] >= localpref) {
			/*
			 * truncate higher pref part of list; if we're
			 * the best choice left, we should have realized
			 * awhile ago that this was a local delivery.
			 */
			if (i == 0)
				goto punt;
			nmx = i;
			break;
		}
	}
	return(nmx);
}

/* Getcanonname - try to find canonical names using the BIND name
   server. This is basically done by looking up entries and using
   the names found, or the CNAME values. If nothing is found then
   FALSE is returned. Note, that if the return value is FALSE,
   the host value is not necessarily valid - the code that calls
   getcanonname only uses host for TRUE results.

   The exact behaviour depends on the values of NO_WOLDCARD_MX,
   TOP_DOMAIN_CLASS, DONT_DNSRCH, LOOK_FOR_LONGSYNONYMS and 
   IGNORE_SELF_MX - see conf.h for more details.

   This version, John.Forrest@umist.ac.uk December 90 */

#ifndef NO_WILDCARD_MX
   /* if NO_WILDCARD_MX is undefined, we can only resolve full names. */
#  define is_full_name(host) (TRUE)

#else

#ifdef TOP_DOMAIN_CLASS
clear_topdomain = TRUE;
#endif /* TOP_DOMAIN_CLASS */

static is_full_name (host)
	char *host;
{
	char *top_dom;

	top_dom = rindex (host, '.');
	if (top_dom == NULL) 
		return FALSE;
	top_dom += 1;
	if (*top_dom == '\0') /* name ends with "." */
		return TRUE;
#if defined(TOP_DOMAIN_CLASS)
	{
	STAB *s;
	if (clear_topdomain) /* we know no top domains - have to */
		return TRUE;  /* assume full for safety */
	/* is it in class TOP_DOMAIN_CLASS ? */
	s = stab (top_dom, ST_CLASS, ST_FIND);
	return (s != NULL && bitnset(TOP_DOMAIN_CLASS, s->s_class));
	}
#else
	return FALSE;
#endif /* TOP_DOMAIN_CLASS */
}

#endif /* !NO_WILDCARD_MX */

#if defined(TOP_DOMAIN_CLASS) && defined(NO_WILDCARD_MX) && defined(LOG)
#  define CHECK_TOP 1
#else
#  define CHECK_TOP 0
#endif

#if CHECK_TOP

static check_top(host)
	char *host;
{
	char *top_dom;
	STAB *s;


	if ((top_dom = rindex (host, '.')) == NULL) {
		syslog(LOG_WARNING, "Incomplete named found by BIND - %s",
			host);
		return;
	}
	if (clear_topdomain)
		return;
	top_dom += 1; /* skip over '.' */
	/* is it in class TOP_DOMAIN_CLASS ? */
	s = stab (top_dom, ST_CLASS, ST_FIND);
	if (s == NULL || ! bitnset(TOP_DOMAIN_CLASS, s->s_class))
		syslog (LOG_WARNING, "Unknown top domains %s in %s (returned from BIND)",
			top_dom, host);
}

#endif /* CHECK_TOP */
	
#if defined(DONT_DNSRCH)
#  define SEARCH (RES_DEFNAMES)
#else
#  define SEARCH (RES_DEFNAMES|RES_DNSRCH)
#endif

# if defined(IGNORE_SELF_MX)
/*      In the case of a host with a MX record pointing at localhost,
**      another routing method must be used.  Examine any MX RRs returned.
**      If the best one points to localhost, return FALSE.
**
**      Paul Pomes, University of Illinois, 10-Oct-88
*/

#define InitPreference 1000
# endif

getcanonname(host, hbsize)
	char *host;
	int hbsize;
{
	register u_char *eom, *cp;
	register int n;
	HEADER *hp;
	querybuf answer;
	u_short type;
	int first, ancount, qdcount, loopcnt;
	char nbuf[PACKETSZ];
	char *wanted_name;
#ifdef LOOK_FOR_LONGSYNONYMS
	char name_stub [MAXNAME];
	char *temp;
#endif
	int must_be_full;
	long keep_res_options;
	int search_failed;
#ifdef IGNORE_SELF_MX
	u_short MailPreference;
	char MailAgent[MAXNAME];
	char MyName[MAXNAME];
	char **MyAliases;
	extern char **myhostname();
#endif
#ifdef LOOK_FOR_LONGSYNONYMS
#  define no_stub() (*name_stub == '\0')
#else
#  define no_stub() (TRUE)
#endif

	loopcnt = 0;
	must_be_full = is_full_name (host);
	keep_res_options = _res.options;
loop:
	wanted_name = host;
#ifdef IGNORE_SELF_MX
	MailPreference = InitPreference;
	MailAgent[0] = '\0';
#endif
#ifdef LOOK_FOR_LONGSYNONYMS
	strcpy (name_stub, "");
	while (strlen(wanted_name) > 0) {
#endif
	search_failed = 0;
	/*
	 * Use query type of ANY if possible (NO_WILDCARD_MX), which will
	 * find types CNAME, A, and MX, and will cause all existing records
	 * to be cached by our local server.  If there is (might be) a
	 * wildcard MX record in the local domain or its parents that are
	 * searched, we can't use ANY; it would cause fully-qualified names
	 * to match as names in a local domain.
	 */
	if (must_be_full)
		_res.options &= ( ~SEARCH & 0xffff );
	else
		_res.options |= SEARCH;
	if (tTd(8, 1))
	    printf ("getcanonname: looking for %s (%d %d %x)\n", wanted_name, 
		no_stub(), must_be_full, _res.options); /* DEBUG */
	n = 0;
	if (! no_stub ()) { 
		/* if this is true, we are just interested in CNAMES,
		   but in BIND4.6 at least, a lookup for CNAME
		   seems to produce "delayed" lookup, even with
		   RES_RECURSE set. Thus, look on local server for
		   CNAME, and if that fails do ANY normally */
		if (tTd(8, 2))
	    		printf ("getcanonname: looking for CNAME\n");
		_res.options &= ~ RES_RECURSE;
		n = res_search(wanted_name, C_IN, 
			T_CNAME, (char *)&answer, sizeof(answer));
		_res.options |= RES_RECURSE;
	}
	if (n <= 0) {
		if (tTd(8, 2))
	    		printf ("getcanonname: looking for ANY\n");
		n = res_search(wanted_name, C_IN, 
			T_ANY, (char *)&answer, sizeof(answer));
	}
	_res.options = keep_res_options;
	if (n < 0) {
		if (tTd(8, 1))
			printf("getcanonname:  res_search failed (errno=%d, h_errno=%d)\n",
			    errno, h_errno);
		if (h_errno == TRY_AGAIN) /* difficult to know what to do */
#ifdef IGNORE_TRYAGAIN
			return TRUE;
#else
			return FALSE;
#endif
		search_failed ++;
	}

	if (!search_failed) {
		/* find first satisfactory answer */
		hp = (HEADER *)&answer;
		ancount = ntohs(hp->ancount);

		/* we don't care about errors here, only if we got an answer */
		if (ancount == 0) {
			if (tTd(8, 1))
				printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
			search_failed ++;
		}
	}
	if (!search_failed) {
		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)
				search_failed ++;
	}
	if (search_failed)
# ifdef LOOK_FOR_LONGSYNONYMS
	{
		temp = index (wanted_name, '.');
		if (temp == NULL)
			return FALSE;
		temp += 1;
		if (*temp == '\0')
			return FALSE;
		strncat (name_stub, wanted_name, temp - wanted_name);
		wanted_name = temp;
		continue;
	}
# else
		return FALSE;
# endif
	/*
	 * just in case someone puts a CNAME record after another record,
	 * check all records for CNAME; otherwise, just take the first
	 * name found.
	 */
	for (first = 1; --ancount >= 0 && cp < eom; cp += n) {
		if ((n = dn_expand((char *)&answer, eom, cp, nbuf,
		    sizeof(nbuf))) < 0)
			break;
		if (first) {                    /* XXX */
			/* if ! no_stub() we are only interested in CNAME ! */
			if (no_stub ()) {
				(void)strncpy(host, nbuf, hbsize);
				host[hbsize - 1] = '\0';
#if CHECK_TOP
				check_top (host);
#endif
			}
			first = 0;
		}
		cp += n;
		GETSHORT(type, cp);
		cp += sizeof(u_short) + sizeof(u_long);
		GETSHORT(n, cp);
		if (type == T_CNAME)  {
			/*
			 * assume that only one cname will be found.  More
			 * than one is undefined.  Copy so that if dn_expand
			 * fails, `host' is still okay.
			 */
			if ((n = dn_expand((char *)&answer, eom, cp, nbuf,
			    sizeof(nbuf))) < 0)
				break;
#ifdef LOOK_FOR_LONGSYNONYMS
			host [0] = '\0';
			strncat (host, name_stub, hbsize);
			strncat (host, nbuf, hbsize - strlen (host));
#else
			(void)strncpy(host, nbuf, hbsize); /* XXX */
			host[hbsize - 1] = '\0';
#endif
#if CHECK_TOP
			check_top (host);
#endif
			must_be_full = 1;       /* new name is bound to be full */
			if (++loopcnt > 8)      /* never be more than 1 */
				return FALSE;
			goto loop;
		}
#ifdef IGNORE_SELF_MX
		else if (type == T_MX)  {
			/*
			 * Be sure that the best MX record doesn't point
			 * to the local machine.  If it does, some other
			 * delivery method is assumed.
			 */

			u_short preference;

			GETSHORT(preference, cp);
			if ((n = dn_expand((char *)&answer, eom, cp, nbuf,
			    sizeof(nbuf))) < 0)
				break;
			if (tTd(8, 1))
				printf("getcanonname: MX host %s, preference %d\n",
					nbuf, preference);
			if (preference < MailPreference) {
				MailPreference = preference;
				(void) strcpy(MailAgent, nbuf);
			}
		}
#endif /* IGNORE_SELF_MX */
	}
#ifdef LOOK_FOR_LONGSYNONYMS
	break;
	}
#endif
	if (tTd(8, 1))
#ifdef LOOK_FOR_LONGSYNONYMS
		printf ("getcanonname: found stub='%s' host='%s'\n",
			name_stub, host);
#else
		printf ("getcanonname: found '%s'\n", host);
#endif
	if (! no_stub())
		return FALSE;
#ifdef IGNORE_SELF_MX
	/* test MailAgent against $j */
	if (MailAgent[0] != '\0' && MyHostName != NULL &&
	    strcasecmp(MailAgent, MyHostName) == 0)
		return FALSE;

	/* test MailAgent against our DNS name and aliases */
	if (MailAgent[0] != '\0' &&
	    (MyAliases = myhostname(MyName, MAXNAME)) != NULL) {
		if (strcasecmp(MailAgent, MyName) == 0)
			return FALSE;
		for (; *MyAliases != NULL; MyAliases++)
			if (strcasecmp(MailAgent, *MyAliases) == 0)
				return FALSE;
	}
#endif /* IGNORE_SELF_MX */
	return TRUE;
}

#else /* !NAMED_BIND */

# include <netdb.h>

getcanonname(host, hbsize)
	char *host;
	int hbsize;
{
	struct hostent *hp;

	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 /* !NAMED_BIND */