190792Sgshapiro/*
2261370Sgshapiro * Copyright (c) 2000-2004, 2010 Proofpoint, Inc. and its suppliers.
390792Sgshapiro *	All rights reserved.
490792Sgshapiro *
590792Sgshapiro * By using this file, you agree to the terms and conditions set
690792Sgshapiro * forth in the LICENSE file which can be found at the top level of
790792Sgshapiro * the sendmail distribution.
890792Sgshapiro *
990792Sgshapiro */
1090792Sgshapiro
1190792Sgshapiro/*
1290792Sgshapiro * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska H�gskolan
1390792Sgshapiro * (Royal Institute of Technology, Stockholm, Sweden).
1490792Sgshapiro * All rights reserved.
1590792Sgshapiro *
1690792Sgshapiro * Redistribution and use in source and binary forms, with or without
1790792Sgshapiro * modification, are permitted provided that the following conditions
1890792Sgshapiro * are met:
1990792Sgshapiro *
2090792Sgshapiro * 1. Redistributions of source code must retain the above copyright
2190792Sgshapiro *    notice, this list of conditions and the following disclaimer.
2290792Sgshapiro *
2390792Sgshapiro * 2. Redistributions in binary form must reproduce the above copyright
2490792Sgshapiro *    notice, this list of conditions and the following disclaimer in the
2590792Sgshapiro *    documentation and/or other materials provided with the distribution.
2690792Sgshapiro *
2790792Sgshapiro * 3. Neither the name of the Institute nor the names of its contributors
2890792Sgshapiro *    may be used to endorse or promote products derived from this software
2990792Sgshapiro *    without specific prior written permission.
3090792Sgshapiro *
3190792Sgshapiro * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
3290792Sgshapiro * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3390792Sgshapiro * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3490792Sgshapiro * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
3590792Sgshapiro * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3690792Sgshapiro * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3790792Sgshapiro * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3890792Sgshapiro * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3990792Sgshapiro * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4090792Sgshapiro * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4190792Sgshapiro * SUCH DAMAGE.
4290792Sgshapiro */
4390792Sgshapiro
4490792Sgshapiro#include <sendmail.h>
4590792Sgshapiro#if DNSMAP
4690792Sgshapiro# if NAMED_BIND
47223067Sgshapiro#  if NETINET
48223067Sgshapiro#   include <netinet/in_systm.h>
49223067Sgshapiro#   include <netinet/ip.h>
50223067Sgshapiro#  endif /* NETINET */
5190792Sgshapiro#  include "sm_resolve.h"
5290792Sgshapiro
53266711SgshapiroSM_RCSID("$Id: sm_resolve.c,v 8.40 2013-11-22 20:51:56 ca Exp $")
5490792Sgshapiro
5590792Sgshapirostatic struct stot
5690792Sgshapiro{
5790792Sgshapiro	const char	*st_name;
5890792Sgshapiro	int		st_type;
5990792Sgshapiro} stot[] =
6090792Sgshapiro{
6190792Sgshapiro#  if NETINET
6290792Sgshapiro	{	"A",		T_A		},
6390792Sgshapiro#  endif /* NETINET */
6490792Sgshapiro#  if NETINET6
6590792Sgshapiro	{	"AAAA",		T_AAAA		},
6690792Sgshapiro#  endif /* NETINET6 */
6790792Sgshapiro	{	"NS",		T_NS		},
6890792Sgshapiro	{	"CNAME",	T_CNAME		},
6990792Sgshapiro	{	"PTR",		T_PTR		},
7090792Sgshapiro	{	"MX",		T_MX		},
7190792Sgshapiro	{	"TXT",		T_TXT		},
7290792Sgshapiro	{	"AFSDB",	T_AFSDB		},
7390792Sgshapiro	{	"SRV",		T_SRV		},
7490792Sgshapiro	{	NULL,		0		}
7590792Sgshapiro};
7690792Sgshapiro
77141858Sgshapirostatic DNS_REPLY_T *parse_dns_reply __P((unsigned char *, int));
78141858Sgshapiro
7990792Sgshapiro/*
8090792Sgshapiro**  DNS_STRING_TO_TYPE -- convert resource record name into type
8190792Sgshapiro**
8290792Sgshapiro**	Parameters:
8390792Sgshapiro**		name -- name of resource record type
8490792Sgshapiro**
8590792Sgshapiro**	Returns:
8690792Sgshapiro**		type if succeeded.
8790792Sgshapiro**		-1 otherwise.
8890792Sgshapiro*/
8990792Sgshapiro
9090792Sgshapiroint
9190792Sgshapirodns_string_to_type(name)
9290792Sgshapiro	const char *name;
9390792Sgshapiro{
9490792Sgshapiro	struct stot *p = stot;
9590792Sgshapiro
9690792Sgshapiro	for (p = stot; p->st_name != NULL; p++)
9790792Sgshapiro		if (sm_strcasecmp(name, p->st_name) == 0)
9890792Sgshapiro			return p->st_type;
9990792Sgshapiro	return -1;
10090792Sgshapiro}
10190792Sgshapiro
10290792Sgshapiro/*
10390792Sgshapiro**  DNS_TYPE_TO_STRING -- convert resource record type into name
10490792Sgshapiro**
10590792Sgshapiro**	Parameters:
10690792Sgshapiro**		type -- resource record type
10790792Sgshapiro**
10890792Sgshapiro**	Returns:
10990792Sgshapiro**		name if succeeded.
11090792Sgshapiro**		NULL otherwise.
11190792Sgshapiro*/
11290792Sgshapiro
11390792Sgshapiroconst char *
11490792Sgshapirodns_type_to_string(type)
11590792Sgshapiro	int type;
11690792Sgshapiro{
11790792Sgshapiro	struct stot *p = stot;
11890792Sgshapiro
11990792Sgshapiro	for (p = stot; p->st_name != NULL; p++)
12090792Sgshapiro		if (type == p->st_type)
12190792Sgshapiro			return p->st_name;
12290792Sgshapiro	return NULL;
12390792Sgshapiro}
12490792Sgshapiro
12590792Sgshapiro/*
12690792Sgshapiro**  DNS_FREE_DATA -- free all components of a DNS_REPLY_T
12790792Sgshapiro**
12890792Sgshapiro**	Parameters:
12990792Sgshapiro**		r -- pointer to DNS_REPLY_T
13090792Sgshapiro**
13190792Sgshapiro**	Returns:
13290792Sgshapiro**		none.
13390792Sgshapiro*/
13490792Sgshapiro
13590792Sgshapirovoid
13690792Sgshapirodns_free_data(r)
13790792Sgshapiro	DNS_REPLY_T *r;
13890792Sgshapiro{
13990792Sgshapiro	RESOURCE_RECORD_T *rr;
14090792Sgshapiro
14190792Sgshapiro	if (r->dns_r_q.dns_q_domain != NULL)
14290792Sgshapiro		sm_free(r->dns_r_q.dns_q_domain);
14390792Sgshapiro	for (rr = r->dns_r_head; rr != NULL; )
14490792Sgshapiro	{
14590792Sgshapiro		RESOURCE_RECORD_T *tmp = rr;
14690792Sgshapiro
14790792Sgshapiro		if (rr->rr_domain != NULL)
14890792Sgshapiro			sm_free(rr->rr_domain);
14990792Sgshapiro		if (rr->rr_u.rr_data != NULL)
15090792Sgshapiro			sm_free(rr->rr_u.rr_data);
15190792Sgshapiro		rr = rr->rr_next;
15290792Sgshapiro		sm_free(tmp);
15390792Sgshapiro	}
15490792Sgshapiro	sm_free(r);
15590792Sgshapiro}
15690792Sgshapiro
15790792Sgshapiro/*
15890792Sgshapiro**  PARSE_DNS_REPLY -- parse DNS reply data.
15990792Sgshapiro**
16090792Sgshapiro**	Parameters:
16190792Sgshapiro**		data -- pointer to dns data
16290792Sgshapiro**		len -- len of data
16390792Sgshapiro**
16490792Sgshapiro**	Returns:
16590792Sgshapiro**		pointer to DNS_REPLY_T if succeeded.
16690792Sgshapiro**		NULL otherwise.
16790792Sgshapiro*/
16890792Sgshapiro
16990792Sgshapirostatic DNS_REPLY_T *
17090792Sgshapiroparse_dns_reply(data, len)
17190792Sgshapiro	unsigned char *data;
17290792Sgshapiro	int len;
17390792Sgshapiro{
17490792Sgshapiro	unsigned char *p;
175182352Sgshapiro	unsigned short ans_cnt, ui;
17690792Sgshapiro	int status;
17790792Sgshapiro	size_t l;
17890792Sgshapiro	char host[MAXHOSTNAMELEN];
17990792Sgshapiro	DNS_REPLY_T *r;
18090792Sgshapiro	RESOURCE_RECORD_T **rr;
18190792Sgshapiro
182112810Sgshapiro	r = (DNS_REPLY_T *) sm_malloc(sizeof(*r));
18390792Sgshapiro	if (r == NULL)
18490792Sgshapiro		return NULL;
185112810Sgshapiro	memset(r, 0, sizeof(*r));
18690792Sgshapiro
18790792Sgshapiro	p = data;
18890792Sgshapiro
18990792Sgshapiro	/* doesn't work on Crays? */
19098841Sgshapiro	memcpy(&r->dns_r_h, p, sizeof(r->dns_r_h));
19198841Sgshapiro	p += sizeof(r->dns_r_h);
192168515Sgshapiro	status = dn_expand(data, data + len, p, host, sizeof(host));
19390792Sgshapiro	if (status < 0)
19490792Sgshapiro	{
19590792Sgshapiro		dns_free_data(r);
19690792Sgshapiro		return NULL;
19790792Sgshapiro	}
19890792Sgshapiro	r->dns_r_q.dns_q_domain = sm_strdup(host);
19990792Sgshapiro	if (r->dns_r_q.dns_q_domain == NULL)
20090792Sgshapiro	{
20190792Sgshapiro		dns_free_data(r);
20290792Sgshapiro		return NULL;
20390792Sgshapiro	}
204173340Sgshapiro
205182352Sgshapiro	ans_cnt = ntohs((unsigned short) r->dns_r_h.ancount);
206173340Sgshapiro
20790792Sgshapiro	p += status;
20890792Sgshapiro	GETSHORT(r->dns_r_q.dns_q_type, p);
20990792Sgshapiro	GETSHORT(r->dns_r_q.dns_q_class, p);
21090792Sgshapiro	rr = &r->dns_r_head;
211173340Sgshapiro	ui = 0;
212173340Sgshapiro	while (p < data + len && ui < ans_cnt)
21390792Sgshapiro	{
21498841Sgshapiro		int type, class, ttl, size, txtlen;
21590792Sgshapiro
216168515Sgshapiro		status = dn_expand(data, data + len, p, host, sizeof(host));
21790792Sgshapiro		if (status < 0)
21890792Sgshapiro		{
21990792Sgshapiro			dns_free_data(r);
22090792Sgshapiro			return NULL;
22190792Sgshapiro		}
222173340Sgshapiro		++ui;
22390792Sgshapiro		p += status;
22490792Sgshapiro		GETSHORT(type, p);
22590792Sgshapiro		GETSHORT(class, p);
22690792Sgshapiro		GETLONG(ttl, p);
22790792Sgshapiro		GETSHORT(size, p);
22898841Sgshapiro		if (p + size > data + len)
22998841Sgshapiro		{
23098841Sgshapiro			/*
23198841Sgshapiro			**  announced size of data exceeds length of
23298841Sgshapiro			**  data paket: someone is cheating.
23398841Sgshapiro			*/
23498841Sgshapiro
23598841Sgshapiro			if (LogLevel > 5)
23698841Sgshapiro				sm_syslog(LOG_WARNING, NOQID,
23798841Sgshapiro					  "ERROR: DNS RDLENGTH=%d > data len=%d",
23898841Sgshapiro					  size, len - (p - data));
23998841Sgshapiro			dns_free_data(r);
24098841Sgshapiro			return NULL;
24198841Sgshapiro		}
242112810Sgshapiro		*rr = (RESOURCE_RECORD_T *) sm_malloc(sizeof(**rr));
24390792Sgshapiro		if (*rr == NULL)
24490792Sgshapiro		{
24590792Sgshapiro			dns_free_data(r);
24690792Sgshapiro			return NULL;
24790792Sgshapiro		}
248112810Sgshapiro		memset(*rr, 0, sizeof(**rr));
24990792Sgshapiro		(*rr)->rr_domain = sm_strdup(host);
25090792Sgshapiro		if ((*rr)->rr_domain == NULL)
25190792Sgshapiro		{
25290792Sgshapiro			dns_free_data(r);
25390792Sgshapiro			return NULL;
25490792Sgshapiro		}
25590792Sgshapiro		(*rr)->rr_type = type;
25690792Sgshapiro		(*rr)->rr_class = class;
25790792Sgshapiro		(*rr)->rr_ttl = ttl;
25890792Sgshapiro		(*rr)->rr_size = size;
25990792Sgshapiro		switch (type)
26090792Sgshapiro		{
26190792Sgshapiro		  case T_NS:
26290792Sgshapiro		  case T_CNAME:
26390792Sgshapiro		  case T_PTR:
26490792Sgshapiro			status = dn_expand(data, data + len, p, host,
265168515Sgshapiro					   sizeof(host));
26690792Sgshapiro			if (status < 0)
26790792Sgshapiro			{
26890792Sgshapiro				dns_free_data(r);
26990792Sgshapiro				return NULL;
27090792Sgshapiro			}
27190792Sgshapiro			(*rr)->rr_u.rr_txt = sm_strdup(host);
27290792Sgshapiro			if ((*rr)->rr_u.rr_txt == NULL)
27390792Sgshapiro			{
27490792Sgshapiro				dns_free_data(r);
27590792Sgshapiro				return NULL;
27690792Sgshapiro			}
27790792Sgshapiro			break;
27890792Sgshapiro
27990792Sgshapiro		  case T_MX:
28090792Sgshapiro		  case T_AFSDB:
28190792Sgshapiro			status = dn_expand(data, data + len, p + 2, host,
282168515Sgshapiro					   sizeof(host));
28390792Sgshapiro			if (status < 0)
28490792Sgshapiro			{
28590792Sgshapiro				dns_free_data(r);
28690792Sgshapiro				return NULL;
28790792Sgshapiro			}
28890792Sgshapiro			l = strlen(host) + 1;
28990792Sgshapiro			(*rr)->rr_u.rr_mx = (MX_RECORD_T *)
290112810Sgshapiro				sm_malloc(sizeof(*((*rr)->rr_u.rr_mx)) + l);
29190792Sgshapiro			if ((*rr)->rr_u.rr_mx == NULL)
29290792Sgshapiro			{
29390792Sgshapiro				dns_free_data(r);
29490792Sgshapiro				return NULL;
29590792Sgshapiro			}
29690792Sgshapiro			(*rr)->rr_u.rr_mx->mx_r_preference = (p[0] << 8) | p[1];
29790792Sgshapiro			(void) sm_strlcpy((*rr)->rr_u.rr_mx->mx_r_domain,
29890792Sgshapiro					  host, l);
29990792Sgshapiro			break;
30090792Sgshapiro
30190792Sgshapiro		  case T_SRV:
30290792Sgshapiro			status = dn_expand(data, data + len, p + 6, host,
303168515Sgshapiro					   sizeof(host));
30490792Sgshapiro			if (status < 0)
30590792Sgshapiro			{
30690792Sgshapiro				dns_free_data(r);
30790792Sgshapiro				return NULL;
30890792Sgshapiro			}
30990792Sgshapiro			l = strlen(host) + 1;
31090792Sgshapiro			(*rr)->rr_u.rr_srv = (SRV_RECORDT_T*)
311112810Sgshapiro				sm_malloc(sizeof(*((*rr)->rr_u.rr_srv)) + l);
31290792Sgshapiro			if ((*rr)->rr_u.rr_srv == NULL)
31390792Sgshapiro			{
31490792Sgshapiro				dns_free_data(r);
31590792Sgshapiro				return NULL;
31690792Sgshapiro			}
31790792Sgshapiro			(*rr)->rr_u.rr_srv->srv_r_priority = (p[0] << 8) | p[1];
31890792Sgshapiro			(*rr)->rr_u.rr_srv->srv_r_weight = (p[2] << 8) | p[3];
31990792Sgshapiro			(*rr)->rr_u.rr_srv->srv_r_port = (p[4] << 8) | p[5];
32090792Sgshapiro			(void) sm_strlcpy((*rr)->rr_u.rr_srv->srv_r_target,
32190792Sgshapiro					  host, l);
32290792Sgshapiro			break;
32390792Sgshapiro
32490792Sgshapiro		  case T_TXT:
32598841Sgshapiro
32698841Sgshapiro			/*
32798841Sgshapiro			**  The TXT record contains the length as
32898841Sgshapiro			**  leading byte, hence the value is restricted
32998841Sgshapiro			**  to 255, which is less than the maximum value
33098841Sgshapiro			**  of RDLENGTH (size). Nevertheless, txtlen
33198841Sgshapiro			**  must be less than size because the latter
33298841Sgshapiro			**  specifies the length of the entire TXT
33398841Sgshapiro			**  record.
33498841Sgshapiro			*/
33598841Sgshapiro
33698841Sgshapiro			txtlen = *p;
33798841Sgshapiro			if (txtlen >= size)
33898841Sgshapiro			{
33998841Sgshapiro				if (LogLevel > 5)
34098841Sgshapiro					sm_syslog(LOG_WARNING, NOQID,
34198841Sgshapiro						  "ERROR: DNS TXT record size=%d <= text len=%d",
34298841Sgshapiro						  size, txtlen);
34398841Sgshapiro				dns_free_data(r);
34498841Sgshapiro				return NULL;
34598841Sgshapiro			}
346112810Sgshapiro			(*rr)->rr_u.rr_txt = (char *) sm_malloc(txtlen + 1);
34790792Sgshapiro			if ((*rr)->rr_u.rr_txt == NULL)
34890792Sgshapiro			{
34990792Sgshapiro				dns_free_data(r);
35090792Sgshapiro				return NULL;
35190792Sgshapiro			}
35298841Sgshapiro			(void) sm_strlcpy((*rr)->rr_u.rr_txt, (char*) p + 1,
35398841Sgshapiro					  txtlen + 1);
35490792Sgshapiro			break;
35590792Sgshapiro
35690792Sgshapiro		  default:
357112810Sgshapiro			(*rr)->rr_u.rr_data = (unsigned char*) sm_malloc(size);
358112810Sgshapiro			if ((*rr)->rr_u.rr_data == NULL)
35990792Sgshapiro			{
36090792Sgshapiro				dns_free_data(r);
36190792Sgshapiro				return NULL;
36290792Sgshapiro			}
36390792Sgshapiro			(void) memcpy((*rr)->rr_u.rr_data, p, size);
36498841Sgshapiro			break;
36590792Sgshapiro		}
36690792Sgshapiro		p += size;
36790792Sgshapiro		rr = &(*rr)->rr_next;
36890792Sgshapiro	}
36990792Sgshapiro	*rr = NULL;
37090792Sgshapiro	return r;
37190792Sgshapiro}
37290792Sgshapiro
37390792Sgshapiro/*
37490792Sgshapiro**  DNS_LOOKUP_INT -- perform dns map lookup (internal helper routine)
37590792Sgshapiro**
37690792Sgshapiro**	Parameters:
37790792Sgshapiro**		domain -- name to lookup
37890792Sgshapiro**		rr_class -- resource record class
37990792Sgshapiro**		rr_type -- resource record type
38090792Sgshapiro**		retrans -- retransmission timeout
38190792Sgshapiro**		retry -- number of retries
38290792Sgshapiro**
38390792Sgshapiro**	Returns:
38490792Sgshapiro**		result of lookup if succeeded.
38590792Sgshapiro**		NULL otherwise.
38690792Sgshapiro*/
38790792Sgshapiro
38890792SgshapiroDNS_REPLY_T *
38990792Sgshapirodns_lookup_int(domain, rr_class, rr_type, retrans, retry)
39090792Sgshapiro	const char *domain;
39190792Sgshapiro	int rr_class;
39290792Sgshapiro	int rr_type;
39390792Sgshapiro	time_t retrans;
39490792Sgshapiro	int retry;
39590792Sgshapiro{
39690792Sgshapiro	int len;
39790792Sgshapiro	unsigned long old_options = 0;
39890792Sgshapiro	time_t save_retrans = 0;
39990792Sgshapiro	int save_retry = 0;
40090792Sgshapiro	DNS_REPLY_T *r = NULL;
401223067Sgshapiro	querybuf reply_buf;
402223067Sgshapiro	unsigned char *reply;
40390792Sgshapiro
404223067Sgshapiro#define SMRBSIZE sizeof(reply_buf)
405223067Sgshapiro#ifndef IP_MAXPACKET
406223067Sgshapiro# define IP_MAXPACKET	65535
407223067Sgshapiro#endif
408223067Sgshapiro
40990792Sgshapiro	if (tTd(8, 16))
41090792Sgshapiro	{
41190792Sgshapiro		old_options = _res.options;
41290792Sgshapiro		_res.options |= RES_DEBUG;
41390792Sgshapiro		sm_dprintf("dns_lookup(%s, %d, %s)\n", domain,
41490792Sgshapiro			   rr_class, dns_type_to_string(rr_type));
41590792Sgshapiro	}
41690792Sgshapiro	if (retrans > 0)
41790792Sgshapiro	{
41890792Sgshapiro		save_retrans = _res.retrans;
41990792Sgshapiro		_res.retrans = retrans;
42090792Sgshapiro	}
42190792Sgshapiro	if (retry > 0)
42290792Sgshapiro	{
42390792Sgshapiro		save_retry = _res.retry;
42490792Sgshapiro		_res.retry = retry;
42590792Sgshapiro	}
42690792Sgshapiro	errno = 0;
42790792Sgshapiro	SM_SET_H_ERRNO(0);
428223067Sgshapiro	reply = (unsigned char *)&reply_buf;
429223067Sgshapiro	len = res_search(domain, rr_class, rr_type, reply, SMRBSIZE);
430223067Sgshapiro	if (len >= SMRBSIZE)
431223067Sgshapiro	{
432223067Sgshapiro		if (len >= IP_MAXPACKET)
433223067Sgshapiro		{
434223067Sgshapiro			if (tTd(8, 4))
435223067Sgshapiro				sm_dprintf("dns_lookup: domain=%s, length=%d, default_size=%d, max=%d, status=response too long\n",
436223067Sgshapiro					   domain, len, (int) SMRBSIZE,
437223067Sgshapiro					   IP_MAXPACKET);
438223067Sgshapiro		}
439223067Sgshapiro		else
440223067Sgshapiro		{
441223067Sgshapiro			if (tTd(8, 6))
442223067Sgshapiro				sm_dprintf("dns_lookup: domain=%s, length=%d, default_size=%d, max=%d, status=response longer than default size, resizing\n",
443223067Sgshapiro					   domain, len, (int) SMRBSIZE,
444223067Sgshapiro					   IP_MAXPACKET);
445223067Sgshapiro			reply = (unsigned char *)sm_malloc(IP_MAXPACKET);
446223067Sgshapiro			if (reply == NULL)
447223067Sgshapiro				SM_SET_H_ERRNO(TRY_AGAIN);
448223067Sgshapiro			else
449223067Sgshapiro				len = res_search(domain, rr_class, rr_type,
450223067Sgshapiro						 reply, IP_MAXPACKET);
451223067Sgshapiro		}
452223067Sgshapiro	}
45390792Sgshapiro	if (tTd(8, 16))
45490792Sgshapiro	{
45590792Sgshapiro		_res.options = old_options;
45690792Sgshapiro		sm_dprintf("dns_lookup(%s, %d, %s) --> %d\n",
45790792Sgshapiro			   domain, rr_class, dns_type_to_string(rr_type), len);
45890792Sgshapiro	}
459223067Sgshapiro	if (len >= 0 && len < IP_MAXPACKET && reply != NULL)
46090792Sgshapiro		r = parse_dns_reply(reply, len);
461223067Sgshapiro	if (reply != (unsigned char *)&reply_buf && reply != NULL)
462223067Sgshapiro	{
463223067Sgshapiro		sm_free(reply);
464223067Sgshapiro		reply = NULL;
465223067Sgshapiro	}
46690792Sgshapiro	if (retrans > 0)
46790792Sgshapiro		_res.retrans = save_retrans;
46890792Sgshapiro	if (retry > 0)
46990792Sgshapiro		_res.retry = save_retry;
47090792Sgshapiro	return r;
47190792Sgshapiro}
47290792Sgshapiro
47390792Sgshapiro#  if 0
47490792SgshapiroDNS_REPLY_T *
47590792Sgshapirodns_lookup(domain, type_name, retrans, retry)
47690792Sgshapiro	const char *domain;
47790792Sgshapiro	const char *type_name;
47890792Sgshapiro	time_t retrans;
47990792Sgshapiro	int retry;
48090792Sgshapiro{
48190792Sgshapiro	int type;
48290792Sgshapiro
48390792Sgshapiro	type = dns_string_to_type(type_name);
48490792Sgshapiro	if (type == -1)
48590792Sgshapiro	{
48690792Sgshapiro		if (tTd(8, 16))
48790792Sgshapiro			sm_dprintf("dns_lookup: unknown resource type: `%s'\n",
48890792Sgshapiro				type_name);
48990792Sgshapiro		return NULL;
49090792Sgshapiro	}
49190792Sgshapiro	return dns_lookup_int(domain, C_IN, type, retrans, retry);
49290792Sgshapiro}
49390792Sgshapiro#  endif /* 0 */
49490792Sgshapiro# endif /* NAMED_BIND */
49590792Sgshapiro#endif /* DNSMAP */
496