diff options
| author | Sam Varshavchik | 2013-08-19 16:39:41 -0400 | 
|---|---|---|
| committer | Sam Varshavchik | 2013-08-25 14:43:51 -0400 | 
| commit | 9c45d9ad13fdf439d44d7443ae75da15ea0223ed (patch) | |
| tree | 7a81a04cb51efb078ee350859a64be2ebc6b8813 /rfc1035/rfc1035search.c | |
| parent | a9520698b770168d1f33d6301463bb70a19655ec (diff) | |
| download | courier-libs-9c45d9ad13fdf439d44d7443ae75da15ea0223ed.tar.bz2 | |
Initial checkin
Imported from subversion report, converted to git. Updated all paths in
scripts and makefiles, reflecting the new directory hierarchy.
Diffstat (limited to 'rfc1035/rfc1035search.c')
| -rw-r--r-- | rfc1035/rfc1035search.c | 214 | 
1 files changed, 214 insertions, 0 deletions
| diff --git a/rfc1035/rfc1035search.c b/rfc1035/rfc1035search.c new file mode 100644 index 0000000..8e69ad4 --- /dev/null +++ b/rfc1035/rfc1035search.c @@ -0,0 +1,214 @@ +/* +** Copyright 1998 - 2011 Double Precision, Inc. +** See COPYING for distribution information. +*/ + +#include	"rfc1035.h" +#include	<string.h> +#include	<stdlib.h> + + +static int found(const struct rfc1035_reply *r, +	const struct rfc1035_rr *rrp, const char *h, +	unsigned qclass, unsigned qtype) +{ +char	namebuf[RFC1035_MAXNAMESIZE+1]; + +	if ((rrp->rrtype != qtype && +		rrp->rrtype != RFC1035_TYPE_CNAME) || +			rrp->rrclass != qclass)	return (0); + +	if (rfc1035_replyhostname(r, rrp->rrname, namebuf) == 0) +		return (0); + +	if (rfc1035_hostnamecmp(namebuf, h) == 0)	return (1); +	return (0); +} + +int rfc1035_replysearch_an(const struct rfc1035_res *res, +			   const struct rfc1035_reply *r, const char *h, +			   unsigned qtype, unsigned qclass, int pos) +{ +	if (res->rfc1035_defaultdomain && strchr(h, '.') == NULL) +	{ +		char *buf; +		int rc; + +		/* Append default domain */ + +		if ((buf=malloc(strlen(h)+ +				strlen(res->rfc1035_defaultdomain)+2)) == 0) +			return (-1); + +		strcat(strcat(strcpy(buf, h), "."), +		       res->rfc1035_defaultdomain); + +		rc=rfc1035_replysearch_an(res, r, buf, qtype, qclass, pos); +		free(buf); +		return (rc); +	} + +	for ( ; pos >= 0 && pos < r->ancount; pos++) +		if (found(r, r->anptr+pos, h, qclass, qtype))	return (pos); +	return (-1); +} + +int rfc1035_replysearch_ns(const struct rfc1035_res *res, +			   const struct rfc1035_reply *r, const char *h, +			   unsigned qtype, unsigned qclass, int pos) +{ +	if (res->rfc1035_defaultdomain && strchr(h, '.') == NULL) +	{ +		char *buf; +		int rc; + +		/* Append default domain */ + +		if ((buf=malloc(strlen(h)+ +				strlen(res->rfc1035_defaultdomain)+2)) == 0) +			return (-1); + +		strcat(strcat(strcpy(buf, h), "."), +		       res->rfc1035_defaultdomain); + +		rc=rfc1035_replysearch_ns(res, r, buf, qtype, qclass, pos); +		free(buf); +		return (rc); +	} + +	for ( ; pos >= 0 && pos < r->nscount; pos++) +		if (found(r, r->nsptr+pos, h, qclass, qtype))	return (pos); +	return (-1); +} + +int rfc1035_replysearch_ar(const struct rfc1035_res *res, +			   const struct rfc1035_reply *r, const char *h, +			   unsigned qtype, unsigned qclass, int pos) +{ +	if (res->rfc1035_defaultdomain && strchr(h, '.') == NULL) +	{ +		char *buf; +		int rc; + +		/* Append default domain */ + +		if ((buf=malloc(strlen(h)+ +				strlen(res->rfc1035_defaultdomain)+2)) == 0) +			return (-1); + +		strcat(strcat(strcpy(buf, h), "."), +		       res->rfc1035_defaultdomain); + +		rc=rfc1035_replysearch_ar(res, r, buf, qtype, qclass, pos); +		free(buf); +		return (rc); +	} + +	for ( ; pos >= 0 && pos < r->arcount; pos++) +		if (found(r, r->arptr+pos, h, qclass, qtype))	return (pos); +	return (-1); +} + +int rfc1035_replysearch_all(const struct rfc1035_res *res, +			   const struct rfc1035_reply *r, const char *h, +			    unsigned qtype, unsigned qclass, int pos) +{ +	unsigned s; + +	if (res->rfc1035_defaultdomain && strchr(h, '.') == NULL) +	{ +		char *buf; +		int rc; + +		/* Append default domain */ + +		if ((buf=malloc(strlen(h)+ +				strlen(res->rfc1035_defaultdomain)+2)) == 0) +			return (-1); + +		strcat(strcat(strcpy(buf, h), "."), +		       res->rfc1035_defaultdomain); + +		rc=rfc1035_replysearch_all(res, r, buf, qtype, qclass, pos); +		free(buf); +		return (rc); +	} + +	s=r->ancount+r->nscount+r->arcount; + +	for ( ; pos >= 0 && pos < s; pos++) +		if (found(r, r->allrrs[pos], h, qclass, qtype))	return (pos); +	return (-1); +} + +int rfc1035_resolve_cname(struct rfc1035_res *res, char *namebuf, +			  unsigned qtype, +			  unsigned qclass, +			  struct rfc1035_reply **ptr, +			  int x_flags) +{ +int	n; +int	recursion_count=10; + +	if ( (*ptr=rfc1035_resolve(res, RFC1035_OPCODE_QUERY, +			namebuf, qtype, qclass)) == 0) +		return (-1); + +	if (x_flags && RFC1035_X_RANDOMIZE && +	    (*ptr)->rcode == RFC1035_RCODE_NOERROR) +		rfc1035_rr_rand(*ptr); + +	if ( (*ptr)->rcode != RFC1035_RCODE_NOERROR || +		(n=rfc1035_replysearch_an( res, +					   *ptr, namebuf, qtype, qclass, 0))<0) +		return (-1); + +	if ( (*ptr)->anptr[n].rrtype == qtype)	return (n); + +	/* Must've gotten back a CNAME when we were looking for something else +	*/ + +	for (;;) +	{ + +		if (rfc1035_replyhostname( *ptr, (*ptr)->anptr[n].rr.domainname, +			namebuf) == 0) +		{ +			rfc1035_replyfree( *ptr ); +			*ptr=0; +			return (-1); +		} + +	/* Let's see if we already have the answer for the canonical name */ + +		if ( (n=rfc1035_replysearch_all( res, *ptr, namebuf, qtype, +				qclass, 0)) >= 0) +		{ +			if ( (*ptr)->anptr[n].rrtype == qtype)	return (n); +			if ( --recursion_count > 0) +				continue; + +			rfc1035_replyfree( *ptr );	/* Recursive CNAME */ +			*ptr=0; +			return (RFC1035_ERR_CNAME_RECURSIVE); +		} + +		rfc1035_replyfree( *ptr ); +		if ( (*ptr=rfc1035_resolve(res, RFC1035_OPCODE_QUERY, +				namebuf, qtype, qclass)) == 0) +			return (-1); + +		if ( (*ptr)->rcode == RFC1035_RCODE_NOERROR && +			(n=rfc1035_replysearch_an( res, *ptr, namebuf, +				qtype, qclass, 0)) >= 0) +		{ +			if ( (*ptr)->anptr[n].rrtype == qtype)	return (n); +			if ( --recursion_count > 0) +				continue; +			rfc1035_replyfree( *ptr );	/* Recursive CNAME */ +			*ptr=0; +			return (RFC1035_ERR_CNAME_RECURSIVE); +		} +		return (-1); +	} +} | 
