xref: /freebsd/contrib/sendmail/src/sm_resolve.c (revision d39bd2c1388b520fcba9abed1932acacead60fba)
140266059SGregory Neil Shapiro /*
25b0945b5SGregory Neil Shapiro  * Copyright (c) 2000-2004, 2010, 2015, 2020 Proofpoint, Inc. and its suppliers.
340266059SGregory Neil Shapiro  *	All rights reserved.
440266059SGregory Neil Shapiro  *
540266059SGregory Neil Shapiro  * By using this file, you agree to the terms and conditions set
640266059SGregory Neil Shapiro  * forth in the LICENSE file which can be found at the top level of
740266059SGregory Neil Shapiro  * the sendmail distribution.
840266059SGregory Neil Shapiro  *
940266059SGregory Neil Shapiro  */
1040266059SGregory Neil Shapiro 
1140266059SGregory Neil Shapiro /*
1240266059SGregory Neil Shapiro  * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska H�gskolan
1340266059SGregory Neil Shapiro  * (Royal Institute of Technology, Stockholm, Sweden).
1440266059SGregory Neil Shapiro  * All rights reserved.
1540266059SGregory Neil Shapiro  *
1640266059SGregory Neil Shapiro  * Redistribution and use in source and binary forms, with or without
1740266059SGregory Neil Shapiro  * modification, are permitted provided that the following conditions
1840266059SGregory Neil Shapiro  * are met:
1940266059SGregory Neil Shapiro  *
2040266059SGregory Neil Shapiro  * 1. Redistributions of source code must retain the above copyright
2140266059SGregory Neil Shapiro  *    notice, this list of conditions and the following disclaimer.
2240266059SGregory Neil Shapiro  *
2340266059SGregory Neil Shapiro  * 2. Redistributions in binary form must reproduce the above copyright
2440266059SGregory Neil Shapiro  *    notice, this list of conditions and the following disclaimer in the
2540266059SGregory Neil Shapiro  *    documentation and/or other materials provided with the distribution.
2640266059SGregory Neil Shapiro  *
2740266059SGregory Neil Shapiro  * 3. Neither the name of the Institute nor the names of its contributors
2840266059SGregory Neil Shapiro  *    may be used to endorse or promote products derived from this software
2940266059SGregory Neil Shapiro  *    without specific prior written permission.
3040266059SGregory Neil Shapiro  *
3140266059SGregory Neil Shapiro  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
3240266059SGregory Neil Shapiro  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3340266059SGregory Neil Shapiro  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3440266059SGregory Neil Shapiro  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
3540266059SGregory Neil Shapiro  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3640266059SGregory Neil Shapiro  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3740266059SGregory Neil Shapiro  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3840266059SGregory Neil Shapiro  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3940266059SGregory Neil Shapiro  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4040266059SGregory Neil Shapiro  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4140266059SGregory Neil Shapiro  * SUCH DAMAGE.
4240266059SGregory Neil Shapiro  */
4340266059SGregory Neil Shapiro 
4440266059SGregory Neil Shapiro #include <sendmail.h>
452fb4f839SGregory Neil Shapiro #include <sm/sendmail.h>
46*d39bd2c1SGregory Neil Shapiro 
4740266059SGregory Neil Shapiro #if NAMED_BIND
486f9c8e5bSGregory Neil Shapiro # if NETINET
496f9c8e5bSGregory Neil Shapiro #  include <netinet/in_systm.h>
506f9c8e5bSGregory Neil Shapiro #  include <netinet/ip.h>
515b0945b5SGregory Neil Shapiro # endif
52*d39bd2c1SGregory Neil Shapiro # if DNSSEC_TEST || _FFR_NAMESERVER
535b0945b5SGregory Neil Shapiro #  define _DEFINE_SMR_GLOBALS 1
54*d39bd2c1SGregory Neil Shapiro # endif
5540266059SGregory Neil Shapiro # include "sm_resolve.h"
56*d39bd2c1SGregory Neil Shapiro # if DNSMAP || DANE
5740266059SGregory Neil Shapiro 
585b0945b5SGregory Neil Shapiro #include <arpa/inet.h>
595b0945b5SGregory Neil Shapiro 
604313cc83SGregory Neil Shapiro SM_RCSID("$Id: sm_resolve.c,v 8.40 2013-11-22 20:51:56 ca Exp $")
6140266059SGregory Neil Shapiro 
6240266059SGregory Neil Shapiro static struct stot
6340266059SGregory Neil Shapiro {
6440266059SGregory Neil Shapiro 	const char	*st_name;
6540266059SGregory Neil Shapiro 	int		st_type;
6640266059SGregory Neil Shapiro } stot[] =
6740266059SGregory Neil Shapiro {
6840266059SGregory Neil Shapiro #  if NETINET
6940266059SGregory Neil Shapiro 	{	"A",		T_A		},
705b0945b5SGregory Neil Shapiro #  endif
7140266059SGregory Neil Shapiro #  if NETINET6
7240266059SGregory Neil Shapiro 	{	"AAAA",		T_AAAA		},
735b0945b5SGregory Neil Shapiro #  endif
7440266059SGregory Neil Shapiro 	{	"NS",		T_NS		},
7540266059SGregory Neil Shapiro 	{	"CNAME",	T_CNAME		},
7640266059SGregory Neil Shapiro 	{	"PTR",		T_PTR		},
7740266059SGregory Neil Shapiro 	{	"MX",		T_MX		},
7840266059SGregory Neil Shapiro 	{	"TXT",		T_TXT		},
7940266059SGregory Neil Shapiro 	{	"AFSDB",	T_AFSDB		},
8040266059SGregory Neil Shapiro 	{	"SRV",		T_SRV		},
815b0945b5SGregory Neil Shapiro #  ifdef T_DS
825b0945b5SGregory Neil Shapiro 	{	"DS",		T_DS		},
835b0945b5SGregory Neil Shapiro #  endif
845b0945b5SGregory Neil Shapiro 	{	"RRSIG",	T_RRSIG		},
855b0945b5SGregory Neil Shapiro #  ifdef T_NSEC
865b0945b5SGregory Neil Shapiro 	{	"NSEC",		T_NSEC		},
875b0945b5SGregory Neil Shapiro #  endif
885b0945b5SGregory Neil Shapiro #  ifdef T_DNSKEY
895b0945b5SGregory Neil Shapiro 	{	"DNSKEY",	T_DNSKEY	},
905b0945b5SGregory Neil Shapiro #  endif
915b0945b5SGregory Neil Shapiro 	{	"TLSA",		T_TLSA		},
9240266059SGregory Neil Shapiro 	{	NULL,		0		}
9340266059SGregory Neil Shapiro };
9440266059SGregory Neil Shapiro 
955b0945b5SGregory Neil Shapiro static DNS_REPLY_T *parse_dns_reply __P((unsigned char *, int, unsigned int));
965b0945b5SGregory Neil Shapiro #  if DNSSEC_TEST && defined(T_TLSA)
975b0945b5SGregory Neil Shapiro static char *hex2bin __P((const char *, int));
985b0945b5SGregory Neil Shapiro #  endif
99b6bacd31SGregory Neil Shapiro 
10040266059SGregory Neil Shapiro /*
10140266059SGregory Neil Shapiro **  DNS_STRING_TO_TYPE -- convert resource record name into type
10240266059SGregory Neil Shapiro **
10340266059SGregory Neil Shapiro **	Parameters:
10440266059SGregory Neil Shapiro **		name -- name of resource record type
10540266059SGregory Neil Shapiro **
10640266059SGregory Neil Shapiro **	Returns:
10740266059SGregory Neil Shapiro **		type if succeeded.
10840266059SGregory Neil Shapiro **		-1 otherwise.
10940266059SGregory Neil Shapiro */
11040266059SGregory Neil Shapiro 
11140266059SGregory Neil Shapiro int
dns_string_to_type(name)11240266059SGregory Neil Shapiro dns_string_to_type(name)
11340266059SGregory Neil Shapiro 	const char *name;
11440266059SGregory Neil Shapiro {
11540266059SGregory Neil Shapiro 	struct stot *p = stot;
11640266059SGregory Neil Shapiro 
11740266059SGregory Neil Shapiro 	for (p = stot; p->st_name != NULL; p++)
1182fb4f839SGregory Neil Shapiro 		if (SM_STRCASEEQ(name, p->st_name))
11940266059SGregory Neil Shapiro 			return p->st_type;
12040266059SGregory Neil Shapiro 	return -1;
12140266059SGregory Neil Shapiro }
12240266059SGregory Neil Shapiro 
12340266059SGregory Neil Shapiro /*
12440266059SGregory Neil Shapiro **  DNS_TYPE_TO_STRING -- convert resource record type into name
12540266059SGregory Neil Shapiro **
12640266059SGregory Neil Shapiro **	Parameters:
12740266059SGregory Neil Shapiro **		type -- resource record type
12840266059SGregory Neil Shapiro **
12940266059SGregory Neil Shapiro **	Returns:
13040266059SGregory Neil Shapiro **		name if succeeded.
13140266059SGregory Neil Shapiro **		NULL otherwise.
13240266059SGregory Neil Shapiro */
13340266059SGregory Neil Shapiro 
13440266059SGregory Neil Shapiro const char *
dns_type_to_string(type)13540266059SGregory Neil Shapiro dns_type_to_string(type)
13640266059SGregory Neil Shapiro 	int type;
13740266059SGregory Neil Shapiro {
13840266059SGregory Neil Shapiro 	struct stot *p = stot;
13940266059SGregory Neil Shapiro 
14040266059SGregory Neil Shapiro 	for (p = stot; p->st_name != NULL; p++)
14140266059SGregory Neil Shapiro 		if (type == p->st_type)
14240266059SGregory Neil Shapiro 			return p->st_name;
14340266059SGregory Neil Shapiro 	return NULL;
14440266059SGregory Neil Shapiro }
14540266059SGregory Neil Shapiro 
14640266059SGregory Neil Shapiro /*
14740266059SGregory Neil Shapiro **  DNS_FREE_DATA -- free all components of a DNS_REPLY_T
14840266059SGregory Neil Shapiro **
14940266059SGregory Neil Shapiro **	Parameters:
1505b0945b5SGregory Neil Shapiro **		dr -- pointer to DNS_REPLY_T
15140266059SGregory Neil Shapiro **
15240266059SGregory Neil Shapiro **	Returns:
15340266059SGregory Neil Shapiro **		none.
15440266059SGregory Neil Shapiro */
15540266059SGregory Neil Shapiro 
15640266059SGregory Neil Shapiro void
dns_free_data(dr)1575b0945b5SGregory Neil Shapiro dns_free_data(dr)
1585b0945b5SGregory Neil Shapiro 	DNS_REPLY_T *dr;
15940266059SGregory Neil Shapiro {
16040266059SGregory Neil Shapiro 	RESOURCE_RECORD_T *rr;
16140266059SGregory Neil Shapiro 
1625b0945b5SGregory Neil Shapiro 	if (dr == NULL)
1635b0945b5SGregory Neil Shapiro 		return;
1645b0945b5SGregory Neil Shapiro 	if (dr->dns_r_q.dns_q_domain != NULL)
1655b0945b5SGregory Neil Shapiro 		sm_free(dr->dns_r_q.dns_q_domain);
1665b0945b5SGregory Neil Shapiro 	for (rr = dr->dns_r_head; rr != NULL; )
16740266059SGregory Neil Shapiro 	{
16840266059SGregory Neil Shapiro 		RESOURCE_RECORD_T *tmp = rr;
16940266059SGregory Neil Shapiro 
17040266059SGregory Neil Shapiro 		if (rr->rr_domain != NULL)
17140266059SGregory Neil Shapiro 			sm_free(rr->rr_domain);
17240266059SGregory Neil Shapiro 		if (rr->rr_u.rr_data != NULL)
17340266059SGregory Neil Shapiro 			sm_free(rr->rr_u.rr_data);
17440266059SGregory Neil Shapiro 		rr = rr->rr_next;
17540266059SGregory Neil Shapiro 		sm_free(tmp);
17640266059SGregory Neil Shapiro 	}
1775b0945b5SGregory Neil Shapiro 	sm_free(dr);
1785b0945b5SGregory Neil Shapiro }
1795b0945b5SGregory Neil Shapiro 
1805b0945b5SGregory Neil Shapiro /*
1815b0945b5SGregory Neil Shapiro **  BIN2HEX -- convert binary TLSA RR to hex string
1825b0945b5SGregory Neil Shapiro **
1835b0945b5SGregory Neil Shapiro **	Parameters:
1845b0945b5SGregory Neil Shapiro **		tlsa -- pointer to result (allocated here)
1855b0945b5SGregory Neil Shapiro **		p --  binary data (TLSA RR)
1865b0945b5SGregory Neil Shapiro **		size -- length of p
1875b0945b5SGregory Neil Shapiro **		min_size -- minimum expected size
1885b0945b5SGregory Neil Shapiro **
1895b0945b5SGregory Neil Shapiro **	Returns:
1905b0945b5SGregory Neil Shapiro **		>0: length of string (*tlsa)
1915b0945b5SGregory Neil Shapiro **		-1: error
1925b0945b5SGregory Neil Shapiro */
1935b0945b5SGregory Neil Shapiro 
1945b0945b5SGregory Neil Shapiro static int bin2hex __P((char **, unsigned char *, int, int));
1955b0945b5SGregory Neil Shapiro 
1965b0945b5SGregory Neil Shapiro static int
bin2hex(tlsa,p,size,min_size)1975b0945b5SGregory Neil Shapiro bin2hex(tlsa, p, size, min_size)
1985b0945b5SGregory Neil Shapiro 	char **tlsa;
1995b0945b5SGregory Neil Shapiro 	unsigned char *p;
2005b0945b5SGregory Neil Shapiro 	int size;
2015b0945b5SGregory Neil Shapiro 	int min_size;
2025b0945b5SGregory Neil Shapiro {
2035b0945b5SGregory Neil Shapiro 	int i, pos, txtlen;
2045b0945b5SGregory Neil Shapiro 
2055b0945b5SGregory Neil Shapiro 	txtlen = size * 3;
2065b0945b5SGregory Neil Shapiro 	if (txtlen <= size || size < min_size)
2075b0945b5SGregory Neil Shapiro 	{
2085b0945b5SGregory Neil Shapiro 		if (LogLevel > 5)
2095b0945b5SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
2105b0945b5SGregory Neil Shapiro 				  "ERROR: bin2hex: size %d wrong", size);
2115b0945b5SGregory Neil Shapiro 		return -1;
2125b0945b5SGregory Neil Shapiro 	}
2135b0945b5SGregory Neil Shapiro 	*tlsa = (char *) sm_malloc(txtlen);
2145b0945b5SGregory Neil Shapiro 	if (*tlsa == NULL)
2155b0945b5SGregory Neil Shapiro 	{
2165b0945b5SGregory Neil Shapiro 		if (tTd(8, 17))
2175b0945b5SGregory Neil Shapiro 			sm_dprintf("len=%d, rr_data=NULL\n", txtlen);
2185b0945b5SGregory Neil Shapiro 		return -1;
2195b0945b5SGregory Neil Shapiro 	}
2205b0945b5SGregory Neil Shapiro 	snprintf(*tlsa, txtlen,
2215b0945b5SGregory Neil Shapiro 		"%02X %02X %02X", p[0], p[1], p[2]);
2225b0945b5SGregory Neil Shapiro 	pos = strlen(*tlsa);
2235b0945b5SGregory Neil Shapiro 
2245b0945b5SGregory Neil Shapiro 	/* why isn't there a print function like strlcat? */
2255b0945b5SGregory Neil Shapiro 	for (i = 3; i < size && pos < txtlen; i++, pos += 3)
2265b0945b5SGregory Neil Shapiro 		snprintf(*tlsa + pos, txtlen - pos, "%c%02X",
2275b0945b5SGregory Neil Shapiro 			(i == 3) ? ' ' : ':', p[i]);
2285b0945b5SGregory Neil Shapiro 
2295b0945b5SGregory Neil Shapiro 	return i;
23040266059SGregory Neil Shapiro }
23140266059SGregory Neil Shapiro 
23240266059SGregory Neil Shapiro /*
23340266059SGregory Neil Shapiro **  PARSE_DNS_REPLY -- parse DNS reply data.
23440266059SGregory Neil Shapiro **
23540266059SGregory Neil Shapiro **	Parameters:
23640266059SGregory Neil Shapiro **		data -- pointer to dns data
23740266059SGregory Neil Shapiro **		len -- len of data
2385b0945b5SGregory Neil Shapiro **		flags -- flags (RR_*)
23940266059SGregory Neil Shapiro **
24040266059SGregory Neil Shapiro **	Returns:
24140266059SGregory Neil Shapiro **		pointer to DNS_REPLY_T if succeeded.
24240266059SGregory Neil Shapiro **		NULL otherwise.
2435b0945b5SGregory Neil Shapiro **
2445b0945b5SGregory Neil Shapiro **	Note:
2455b0945b5SGregory Neil Shapiro **		use dns_free_data() to free() the result when no longer needed.
24640266059SGregory Neil Shapiro */
24740266059SGregory Neil Shapiro 
24840266059SGregory Neil Shapiro static DNS_REPLY_T *
parse_dns_reply(data,len,flags)2495b0945b5SGregory Neil Shapiro parse_dns_reply(data, len, flags)
25040266059SGregory Neil Shapiro 	unsigned char *data;
25140266059SGregory Neil Shapiro 	int len;
2525b0945b5SGregory Neil Shapiro 	unsigned int flags;
25340266059SGregory Neil Shapiro {
25440266059SGregory Neil Shapiro 	unsigned char *p;
255e3793f76SGregory Neil Shapiro 	unsigned short ans_cnt, ui;
25640266059SGregory Neil Shapiro 	int status;
25740266059SGregory Neil Shapiro 	size_t l;
25840266059SGregory Neil Shapiro 	char host[MAXHOSTNAMELEN];
2595b0945b5SGregory Neil Shapiro 	DNS_REPLY_T *dr;
26040266059SGregory Neil Shapiro 	RESOURCE_RECORD_T **rr;
26140266059SGregory Neil Shapiro 
2625b0945b5SGregory Neil Shapiro 	if (tTd(8, 90))
2635b0945b5SGregory Neil Shapiro 	{
2645b0945b5SGregory Neil Shapiro 		FILE *fp;
2655b0945b5SGregory Neil Shapiro 
2665b0945b5SGregory Neil Shapiro 		fp = fopen("dns.buffer", "w");
2675b0945b5SGregory Neil Shapiro 		if (fp != NULL)
2685b0945b5SGregory Neil Shapiro 		{
2695b0945b5SGregory Neil Shapiro 			fwrite(data, 1, len, fp);
2705b0945b5SGregory Neil Shapiro 			fclose(fp);
2715b0945b5SGregory Neil Shapiro 			fp = NULL;
2725b0945b5SGregory Neil Shapiro 		}
2735b0945b5SGregory Neil Shapiro 		else
2745b0945b5SGregory Neil Shapiro 			sm_dprintf("parse_dns_reply: fp=%p, e=%d\n",
2755b0945b5SGregory Neil Shapiro 				(void *)fp, errno);
2765b0945b5SGregory Neil Shapiro 	}
2775b0945b5SGregory Neil Shapiro 
2785b0945b5SGregory Neil Shapiro 	dr = (DNS_REPLY_T *) sm_malloc(sizeof(*dr));
2795b0945b5SGregory Neil Shapiro 	if (dr == NULL)
28040266059SGregory Neil Shapiro 		return NULL;
2815b0945b5SGregory Neil Shapiro 	memset(dr, 0, sizeof(*dr));
28240266059SGregory Neil Shapiro 
28340266059SGregory Neil Shapiro 	p = data;
28440266059SGregory Neil Shapiro 
28540266059SGregory Neil Shapiro 	/* doesn't work on Crays? */
2865b0945b5SGregory Neil Shapiro 	memcpy(&dr->dns_r_h, p, sizeof(dr->dns_r_h));
2875b0945b5SGregory Neil Shapiro 	p += sizeof(dr->dns_r_h);
288d0cef73dSGregory Neil Shapiro 	status = dn_expand(data, data + len, p, host, sizeof(host));
28940266059SGregory Neil Shapiro 	if (status < 0)
2905b0945b5SGregory Neil Shapiro 		goto error;
2915b0945b5SGregory Neil Shapiro 	dr->dns_r_q.dns_q_domain = sm_strdup(host);
2925b0945b5SGregory Neil Shapiro 	if (dr->dns_r_q.dns_q_domain == NULL)
2935b0945b5SGregory Neil Shapiro 		goto error;
294ffb83623SGregory Neil Shapiro 
2955b0945b5SGregory Neil Shapiro 	ans_cnt = ntohs((unsigned short) dr->dns_r_h.ancount);
2965b0945b5SGregory Neil Shapiro 	if (tTd(8, 17))
2975b0945b5SGregory Neil Shapiro 		sm_dprintf("parse_dns_reply: ac=%d, ad=%d\n", ans_cnt,
2985b0945b5SGregory Neil Shapiro 			dr->dns_r_h.ad);
299ffb83623SGregory Neil Shapiro 
30040266059SGregory Neil Shapiro 	p += status;
3015b0945b5SGregory Neil Shapiro 	GETSHORT(dr->dns_r_q.dns_q_type, p);
3025b0945b5SGregory Neil Shapiro 	GETSHORT(dr->dns_r_q.dns_q_class, p);
3035b0945b5SGregory Neil Shapiro 	rr = &dr->dns_r_head;
304ffb83623SGregory Neil Shapiro 	ui = 0;
305ffb83623SGregory Neil Shapiro 	while (p < data + len && ui < ans_cnt)
30640266059SGregory Neil Shapiro 	{
307739ac4d4SGregory Neil Shapiro 		int type, class, ttl, size, txtlen;
30840266059SGregory Neil Shapiro 
309d0cef73dSGregory Neil Shapiro 		status = dn_expand(data, data + len, p, host, sizeof(host));
31040266059SGregory Neil Shapiro 		if (status < 0)
3115b0945b5SGregory Neil Shapiro 			goto error;
312ffb83623SGregory Neil Shapiro 		++ui;
31340266059SGregory Neil Shapiro 		p += status;
31440266059SGregory Neil Shapiro 		GETSHORT(type, p);
31540266059SGregory Neil Shapiro 		GETSHORT(class, p);
31640266059SGregory Neil Shapiro 		GETLONG(ttl, p);
31740266059SGregory Neil Shapiro 		GETSHORT(size, p);
318739ac4d4SGregory Neil Shapiro 		if (p + size > data + len)
319739ac4d4SGregory Neil Shapiro 		{
320739ac4d4SGregory Neil Shapiro 			/*
321739ac4d4SGregory Neil Shapiro 			**  announced size of data exceeds length of
322739ac4d4SGregory Neil Shapiro 			**  data paket: someone is cheating.
323739ac4d4SGregory Neil Shapiro 			*/
324739ac4d4SGregory Neil Shapiro 
325739ac4d4SGregory Neil Shapiro 			if (LogLevel > 5)
326739ac4d4SGregory Neil Shapiro 				sm_syslog(LOG_WARNING, NOQID,
327739ac4d4SGregory Neil Shapiro 					  "ERROR: DNS RDLENGTH=%d > data len=%d",
328da7d7b9cSGregory Neil Shapiro 					  size, len - (int)(p - data));
3295b0945b5SGregory Neil Shapiro 			goto error;
330739ac4d4SGregory Neil Shapiro 		}
3315ef517c0SGregory Neil Shapiro 		*rr = (RESOURCE_RECORD_T *) sm_malloc(sizeof(**rr));
33240266059SGregory Neil Shapiro 		if (*rr == NULL)
3335b0945b5SGregory Neil Shapiro 			goto error;
3345ef517c0SGregory Neil Shapiro 		memset(*rr, 0, sizeof(**rr));
33540266059SGregory Neil Shapiro 		(*rr)->rr_domain = sm_strdup(host);
33640266059SGregory Neil Shapiro 		if ((*rr)->rr_domain == NULL)
3375b0945b5SGregory Neil Shapiro 			goto error;
33840266059SGregory Neil Shapiro 		(*rr)->rr_type = type;
33940266059SGregory Neil Shapiro 		(*rr)->rr_class = class;
34040266059SGregory Neil Shapiro 		(*rr)->rr_ttl = ttl;
34140266059SGregory Neil Shapiro 		(*rr)->rr_size = size;
34240266059SGregory Neil Shapiro 		switch (type)
34340266059SGregory Neil Shapiro 		{
34440266059SGregory Neil Shapiro 		  case T_NS:
34540266059SGregory Neil Shapiro 		  case T_CNAME:
34640266059SGregory Neil Shapiro 		  case T_PTR:
34740266059SGregory Neil Shapiro 			status = dn_expand(data, data + len, p, host,
348d0cef73dSGregory Neil Shapiro 					   sizeof(host));
34940266059SGregory Neil Shapiro 			if (status < 0)
3505b0945b5SGregory Neil Shapiro 				goto error;
3515b0945b5SGregory Neil Shapiro 			if (tTd(8, 50))
3525b0945b5SGregory Neil Shapiro 				sm_dprintf("parse_dns_reply: type=%s, host=%s\n",
3535b0945b5SGregory Neil Shapiro 					dns_type_to_string(type), host);
35440266059SGregory Neil Shapiro 			(*rr)->rr_u.rr_txt = sm_strdup(host);
35540266059SGregory Neil Shapiro 			if ((*rr)->rr_u.rr_txt == NULL)
3565b0945b5SGregory Neil Shapiro 				goto error;
35740266059SGregory Neil Shapiro 			break;
35840266059SGregory Neil Shapiro 
35940266059SGregory Neil Shapiro 		  case T_MX:
36040266059SGregory Neil Shapiro 		  case T_AFSDB:
36140266059SGregory Neil Shapiro 			status = dn_expand(data, data + len, p + 2, host,
362d0cef73dSGregory Neil Shapiro 					   sizeof(host));
36340266059SGregory Neil Shapiro 			if (status < 0)
3645b0945b5SGregory Neil Shapiro 				goto error;
36540266059SGregory Neil Shapiro 			l = strlen(host) + 1;
36640266059SGregory Neil Shapiro 			(*rr)->rr_u.rr_mx = (MX_RECORD_T *)
3675ef517c0SGregory Neil Shapiro 				sm_malloc(sizeof(*((*rr)->rr_u.rr_mx)) + l);
36840266059SGregory Neil Shapiro 			if ((*rr)->rr_u.rr_mx == NULL)
3695b0945b5SGregory Neil Shapiro 				goto error;
37040266059SGregory Neil Shapiro 			(*rr)->rr_u.rr_mx->mx_r_preference = (p[0] << 8) | p[1];
37140266059SGregory Neil Shapiro 			(void) sm_strlcpy((*rr)->rr_u.rr_mx->mx_r_domain,
37240266059SGregory Neil Shapiro 					  host, l);
3735b0945b5SGregory Neil Shapiro 			if (tTd(8, 50))
3745b0945b5SGregory Neil Shapiro 				sm_dprintf("mx=%s, pref=%d\n", host,
3755b0945b5SGregory Neil Shapiro 					(*rr)->rr_u.rr_mx->mx_r_preference);
37640266059SGregory Neil Shapiro 			break;
37740266059SGregory Neil Shapiro 
37840266059SGregory Neil Shapiro 		  case T_SRV:
37940266059SGregory Neil Shapiro 			status = dn_expand(data, data + len, p + 6, host,
380d0cef73dSGregory Neil Shapiro 					   sizeof(host));
38140266059SGregory Neil Shapiro 			if (status < 0)
3825b0945b5SGregory Neil Shapiro 				goto error;
38340266059SGregory Neil Shapiro 			l = strlen(host) + 1;
38440266059SGregory Neil Shapiro 			(*rr)->rr_u.rr_srv = (SRV_RECORDT_T*)
3855ef517c0SGregory Neil Shapiro 				sm_malloc(sizeof(*((*rr)->rr_u.rr_srv)) + l);
38640266059SGregory Neil Shapiro 			if ((*rr)->rr_u.rr_srv == NULL)
3875b0945b5SGregory Neil Shapiro 				goto error;
38840266059SGregory Neil Shapiro 			(*rr)->rr_u.rr_srv->srv_r_priority = (p[0] << 8) | p[1];
38940266059SGregory Neil Shapiro 			(*rr)->rr_u.rr_srv->srv_r_weight = (p[2] << 8) | p[3];
39040266059SGregory Neil Shapiro 			(*rr)->rr_u.rr_srv->srv_r_port = (p[4] << 8) | p[5];
39140266059SGregory Neil Shapiro 			(void) sm_strlcpy((*rr)->rr_u.rr_srv->srv_r_target,
39240266059SGregory Neil Shapiro 					  host, l);
39340266059SGregory Neil Shapiro 			break;
39440266059SGregory Neil Shapiro 
39540266059SGregory Neil Shapiro 		  case T_TXT:
396739ac4d4SGregory Neil Shapiro 
397739ac4d4SGregory Neil Shapiro 			/*
398739ac4d4SGregory Neil Shapiro 			**  The TXT record contains the length as
399739ac4d4SGregory Neil Shapiro 			**  leading byte, hence the value is restricted
400739ac4d4SGregory Neil Shapiro 			**  to 255, which is less than the maximum value
401739ac4d4SGregory Neil Shapiro 			**  of RDLENGTH (size). Nevertheless, txtlen
402739ac4d4SGregory Neil Shapiro 			**  must be less than size because the latter
403739ac4d4SGregory Neil Shapiro 			**  specifies the length of the entire TXT
404739ac4d4SGregory Neil Shapiro 			**  record.
405739ac4d4SGregory Neil Shapiro 			*/
406739ac4d4SGregory Neil Shapiro 
407739ac4d4SGregory Neil Shapiro 			txtlen = *p;
408739ac4d4SGregory Neil Shapiro 			if (txtlen >= size)
409739ac4d4SGregory Neil Shapiro 			{
410739ac4d4SGregory Neil Shapiro 				if (LogLevel > 5)
411739ac4d4SGregory Neil Shapiro 					sm_syslog(LOG_WARNING, NOQID,
412739ac4d4SGregory Neil Shapiro 						  "ERROR: DNS TXT record size=%d <= text len=%d",
413739ac4d4SGregory Neil Shapiro 						  size, txtlen);
4145b0945b5SGregory Neil Shapiro 				goto error;
415739ac4d4SGregory Neil Shapiro 			}
4165ef517c0SGregory Neil Shapiro 			(*rr)->rr_u.rr_txt = (char *) sm_malloc(txtlen + 1);
41740266059SGregory Neil Shapiro 			if ((*rr)->rr_u.rr_txt == NULL)
4185b0945b5SGregory Neil Shapiro 				goto error;
419739ac4d4SGregory Neil Shapiro 			(void) sm_strlcpy((*rr)->rr_u.rr_txt, (char*) p + 1,
420739ac4d4SGregory Neil Shapiro 					  txtlen + 1);
42140266059SGregory Neil Shapiro 			break;
42240266059SGregory Neil Shapiro 
4235b0945b5SGregory Neil Shapiro #  ifdef T_TLSA
4245b0945b5SGregory Neil Shapiro 		  case T_TLSA:
4255b0945b5SGregory Neil Shapiro 			if (tTd(8, 61))
4265b0945b5SGregory Neil Shapiro 				sm_dprintf("parse_dns_reply: TLSA, size=%d, flags=%X\n",
4275b0945b5SGregory Neil Shapiro 					size, flags);
4285b0945b5SGregory Neil Shapiro 			if ((flags & RR_AS_TEXT) != 0)
4295b0945b5SGregory Neil Shapiro 			{
4305b0945b5SGregory Neil Shapiro 				txtlen = bin2hex((char **)&((*rr)->rr_u.rr_data),
4315b0945b5SGregory Neil Shapiro 						p, size, 4);
4325b0945b5SGregory Neil Shapiro 				if (txtlen <= 0)
4335b0945b5SGregory Neil Shapiro 					goto error;
4345b0945b5SGregory Neil Shapiro 				break;
4355b0945b5SGregory Neil Shapiro 			}
4365b0945b5SGregory Neil Shapiro 			/* FALLTHROUGH */
4375b0945b5SGregory Neil Shapiro 			/* return "raw" data for caller to use as it pleases */
4385b0945b5SGregory Neil Shapiro #  endif /* T_TLSA */
4395b0945b5SGregory Neil Shapiro 
44040266059SGregory Neil Shapiro 		  default:
4415ef517c0SGregory Neil Shapiro 			(*rr)->rr_u.rr_data = (unsigned char*) sm_malloc(size);
4425ef517c0SGregory Neil Shapiro 			if ((*rr)->rr_u.rr_data == NULL)
4435b0945b5SGregory Neil Shapiro 				goto error;
44440266059SGregory Neil Shapiro 			(void) memcpy((*rr)->rr_u.rr_data, p, size);
4455b0945b5SGregory Neil Shapiro 			if (tTd(8, 61) && type == T_A)
4465b0945b5SGregory Neil Shapiro 			{
4475b0945b5SGregory Neil Shapiro 				SOCKADDR addr;
4485b0945b5SGregory Neil Shapiro 
4495b0945b5SGregory Neil Shapiro 				(void) memcpy((void *)&addr.sin.sin_addr.s_addr, p, size);
4505b0945b5SGregory Neil Shapiro 				sm_dprintf("parse_dns_reply: IPv4=%s\n",
4515b0945b5SGregory Neil Shapiro 					inet_ntoa(addr.sin.sin_addr));
4525b0945b5SGregory Neil Shapiro 			}
453739ac4d4SGregory Neil Shapiro 			break;
45440266059SGregory Neil Shapiro 		}
45540266059SGregory Neil Shapiro 		p += size;
45640266059SGregory Neil Shapiro 		rr = &(*rr)->rr_next;
45740266059SGregory Neil Shapiro 	}
45840266059SGregory Neil Shapiro 	*rr = NULL;
4595b0945b5SGregory Neil Shapiro 	return dr;
4605b0945b5SGregory Neil Shapiro 
4615b0945b5SGregory Neil Shapiro   error:
4625b0945b5SGregory Neil Shapiro 	dns_free_data(dr);
4635b0945b5SGregory Neil Shapiro 	return NULL;
4645b0945b5SGregory Neil Shapiro }
4655b0945b5SGregory Neil Shapiro 
4665b0945b5SGregory Neil Shapiro #  if DNSSEC_TEST
4675b0945b5SGregory Neil Shapiro 
4685b0945b5SGregory Neil Shapiro #   include <arpa/nameser.h>
4692fb4f839SGregory Neil Shapiro #   if _FFR_8BITENVADDR
4702fb4f839SGregory Neil Shapiro #    include <sm/sendmail.h>
4712fb4f839SGregory Neil Shapiro #   endif
4725b0945b5SGregory Neil Shapiro 
4735b0945b5SGregory Neil Shapiro static int gen_dns_reply __P((unsigned char *, int, unsigned char *,
4745b0945b5SGregory Neil Shapiro 		const char *, int, const char *, int, int, int, int,
4755b0945b5SGregory Neil Shapiro 		const char *, int, int, int));
4765b0945b5SGregory Neil Shapiro static int dnscrtrr __P((const char *, const char *, int, char *, int,
4775b0945b5SGregory Neil Shapiro 	unsigned int, int *, int *, unsigned char *, int, unsigned char *));
4785b0945b5SGregory Neil Shapiro 
4795b0945b5SGregory Neil Shapiro /*
4805b0945b5SGregory Neil Shapiro **  HERRNO2TXT -- return error text for h_errno
4815b0945b5SGregory Neil Shapiro **
4825b0945b5SGregory Neil Shapiro **	Parameters:
4835b0945b5SGregory Neil Shapiro **		e -- h_errno
4845b0945b5SGregory Neil Shapiro **
4855b0945b5SGregory Neil Shapiro **	Returns:
4865b0945b5SGregory Neil Shapiro **		DNS error text if available
4875b0945b5SGregory Neil Shapiro */
4885b0945b5SGregory Neil Shapiro 
4895b0945b5SGregory Neil Shapiro const char *
herrno2txt(e)4905b0945b5SGregory Neil Shapiro herrno2txt(e)
4915b0945b5SGregory Neil Shapiro 	int e;
4925b0945b5SGregory Neil Shapiro {
4935b0945b5SGregory Neil Shapiro 	switch (e)
4945b0945b5SGregory Neil Shapiro 	{
4955b0945b5SGregory Neil Shapiro 	  case NETDB_INTERNAL:
4965b0945b5SGregory Neil Shapiro 		return "see errno";
4975b0945b5SGregory Neil Shapiro 	  case NETDB_SUCCESS:
4985b0945b5SGregory Neil Shapiro 		return "OK";
4995b0945b5SGregory Neil Shapiro 	  case HOST_NOT_FOUND:
5005b0945b5SGregory Neil Shapiro 		return "HOST_NOT_FOUND";
5015b0945b5SGregory Neil Shapiro 	  case TRY_AGAIN:
5025b0945b5SGregory Neil Shapiro 		return "TRY_AGAIN";
5035b0945b5SGregory Neil Shapiro 	  case NO_RECOVERY:
5045b0945b5SGregory Neil Shapiro 		return "NO_RECOVERY";
5055b0945b5SGregory Neil Shapiro 	  case NO_DATA:
5065b0945b5SGregory Neil Shapiro 		return "NO_DATA";
5075b0945b5SGregory Neil Shapiro 	}
5085b0945b5SGregory Neil Shapiro 	return "bogus h_errno";
50940266059SGregory Neil Shapiro }
51040266059SGregory Neil Shapiro 
51140266059SGregory Neil Shapiro /*
5125b0945b5SGregory Neil Shapiro **  GEN_DNS_REPLY -- generate DNS reply data.
5135b0945b5SGregory Neil Shapiro **
5145b0945b5SGregory Neil Shapiro **	Parameters:
5155b0945b5SGregory Neil Shapiro **		buf -- buffer to which DNS data is written
5165b0945b5SGregory Neil Shapiro **		buflen -- length of buffer
5175b0945b5SGregory Neil Shapiro **		bufpos -- position in buffer where DNS RRs are appended
5185b0945b5SGregory Neil Shapiro **		query -- name of query
5195b0945b5SGregory Neil Shapiro **		qtype -- resource record type of query
5205b0945b5SGregory Neil Shapiro **		domain -- name of domain which has been "found"
5215b0945b5SGregory Neil Shapiro **		class -- resource record class
5225b0945b5SGregory Neil Shapiro **		type -- resource record type
5235b0945b5SGregory Neil Shapiro **		ttl -- TTL
5245b0945b5SGregory Neil Shapiro **		size -- size of data
5255b0945b5SGregory Neil Shapiro **		data -- data
5265b0945b5SGregory Neil Shapiro **		txtlen -- length of text
5275b0945b5SGregory Neil Shapiro **		pref -- MX preference
5285b0945b5SGregory Neil Shapiro **		ad -- ad flag
5295b0945b5SGregory Neil Shapiro **
5305b0945b5SGregory Neil Shapiro **	Returns:
5315b0945b5SGregory Neil Shapiro **		>0 length of buffer that has been used.
5325b0945b5SGregory Neil Shapiro **		<0 error
5335b0945b5SGregory Neil Shapiro */
5345b0945b5SGregory Neil Shapiro 
5355b0945b5SGregory Neil Shapiro static int
gen_dns_reply(buf,buflen,bufpos,query,qtype,domain,class,type,ttl,size,data,txtlen,pref,ad)5365b0945b5SGregory Neil Shapiro gen_dns_reply(buf, buflen, bufpos, query, qtype, domain, class, type, ttl, size, data, txtlen, pref, ad)
5375b0945b5SGregory Neil Shapiro 	unsigned char *buf;
5385b0945b5SGregory Neil Shapiro 	int buflen;
5395b0945b5SGregory Neil Shapiro 	unsigned char *bufpos;
5405b0945b5SGregory Neil Shapiro 	const char *query;
5415b0945b5SGregory Neil Shapiro 	int qtype;
5425b0945b5SGregory Neil Shapiro 	const char *domain;
5435b0945b5SGregory Neil Shapiro 	int class;
5445b0945b5SGregory Neil Shapiro 	int type;
5455b0945b5SGregory Neil Shapiro 	int ttl;
5465b0945b5SGregory Neil Shapiro 	int size;
5475b0945b5SGregory Neil Shapiro 	const char *data;
5485b0945b5SGregory Neil Shapiro 	int txtlen;
5495b0945b5SGregory Neil Shapiro 	int pref;
5505b0945b5SGregory Neil Shapiro 	int ad;
5515b0945b5SGregory Neil Shapiro {
5525b0945b5SGregory Neil Shapiro 	unsigned short ans_cnt;
5535b0945b5SGregory Neil Shapiro 	HEADER *hp;
5545b0945b5SGregory Neil Shapiro 	unsigned char *cp, *ep;
5555b0945b5SGregory Neil Shapiro 	int n;
5565b0945b5SGregory Neil Shapiro 	static unsigned char *dnptrs[20], **dpp, **lastdnptr;
5575b0945b5SGregory Neil Shapiro 
5582fb4f839SGregory Neil Shapiro #define DN_COMP_CHK	do	\
5592fb4f839SGregory Neil Shapiro 	{	\
5602fb4f839SGregory Neil Shapiro 		if (n < 0)	\
5612fb4f839SGregory Neil Shapiro 		{	\
5622fb4f839SGregory Neil Shapiro 			if (tTd(8, 91))	\
5632fb4f839SGregory Neil Shapiro 				sm_dprintf("gen_dns_reply: dn_comp=%d\n", n); \
5642fb4f839SGregory Neil Shapiro 			return n;	\
5652fb4f839SGregory Neil Shapiro 		}	\
5662fb4f839SGregory Neil Shapiro 	} while (0)
5672fb4f839SGregory Neil Shapiro 
5685b0945b5SGregory Neil Shapiro 	SM_REQUIRE(NULL != buf);
5695b0945b5SGregory Neil Shapiro 	SM_REQUIRE(buflen >= HFIXEDSZ);
5705b0945b5SGregory Neil Shapiro 	SM_REQUIRE(query != NULL);
5715b0945b5SGregory Neil Shapiro 	hp = (HEADER *) buf;
5725b0945b5SGregory Neil Shapiro 	ep = buf + buflen;
5735b0945b5SGregory Neil Shapiro 	cp = buf + HFIXEDSZ;
5745b0945b5SGregory Neil Shapiro 
5755b0945b5SGregory Neil Shapiro 	if (bufpos != NULL)
5765b0945b5SGregory Neil Shapiro 		cp = bufpos;
5775b0945b5SGregory Neil Shapiro 	else
5785b0945b5SGregory Neil Shapiro 	{
5795b0945b5SGregory Neil Shapiro 		sm_dprintf("gen_dns_reply: query=%s, domain=%s, type=%s, size=%d, ad=%d\n",
5805b0945b5SGregory Neil Shapiro 			query, domain, dns_type_to_string(type), size, ad);
5815b0945b5SGregory Neil Shapiro 		dpp = dnptrs;
5825b0945b5SGregory Neil Shapiro 		*dpp++ = buf;
5835b0945b5SGregory Neil Shapiro 		*dpp++ = NULL;
5845b0945b5SGregory Neil Shapiro 		lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
5855b0945b5SGregory Neil Shapiro 
5865b0945b5SGregory Neil Shapiro 		memset(buf, 0, HFIXEDSZ);
5875b0945b5SGregory Neil Shapiro 		hp->id = 0xdead;	/* HACK */
5885b0945b5SGregory Neil Shapiro 		hp->qr = 1;
5895b0945b5SGregory Neil Shapiro 		hp->opcode = QUERY;
5905b0945b5SGregory Neil Shapiro 		hp->rd = 0;	/* recursion desired? */
5915b0945b5SGregory Neil Shapiro 		hp->rcode = 0; /* !!! */
5925b0945b5SGregory Neil Shapiro 		/* hp->aa = ?;	* !!! */
5935b0945b5SGregory Neil Shapiro 		/* hp->tc = ?;	* !!! */
5945b0945b5SGregory Neil Shapiro 		/* hp->ra = ?;	* !!! */
5955b0945b5SGregory Neil Shapiro 		hp->qdcount = htons(1);
5965b0945b5SGregory Neil Shapiro 		hp->ancount = 0;
5975b0945b5SGregory Neil Shapiro 
5985b0945b5SGregory Neil Shapiro 		n = dn_comp(query, cp, ep - cp - QFIXEDSZ, dnptrs, lastdnptr);
5992fb4f839SGregory Neil Shapiro 		DN_COMP_CHK;
6005b0945b5SGregory Neil Shapiro 		cp += n;
6015b0945b5SGregory Neil Shapiro 		PUTSHORT(qtype, cp);
6025b0945b5SGregory Neil Shapiro 		PUTSHORT(class, cp);
6035b0945b5SGregory Neil Shapiro 	}
6045b0945b5SGregory Neil Shapiro 	hp->ad = ad;
6055b0945b5SGregory Neil Shapiro 
6065b0945b5SGregory Neil Shapiro 	if (ep - cp < QFIXEDSZ)
6072fb4f839SGregory Neil Shapiro 	{
6082fb4f839SGregory Neil Shapiro 		if (tTd(8, 91))
6092fb4f839SGregory Neil Shapiro 			sm_dprintf("gen_dns_reply: ep-cp=%ld\n",
6102fb4f839SGregory Neil Shapiro 				(long) (ep - cp));
6115b0945b5SGregory Neil Shapiro 		return (-1);
6122fb4f839SGregory Neil Shapiro 	}
6135b0945b5SGregory Neil Shapiro 	n = dn_comp(domain, cp, ep - cp - QFIXEDSZ, dnptrs, lastdnptr);
6142fb4f839SGregory Neil Shapiro 	DN_COMP_CHK;
6155b0945b5SGregory Neil Shapiro 	cp += n;
6165b0945b5SGregory Neil Shapiro 	PUTSHORT(type, cp);
6175b0945b5SGregory Neil Shapiro 	PUTSHORT(class, cp);
6185b0945b5SGregory Neil Shapiro 	PUTLONG(ttl, cp);
6195b0945b5SGregory Neil Shapiro 
6205b0945b5SGregory Neil Shapiro 	ans_cnt = ntohs((unsigned short) hp->ancount);
6215b0945b5SGregory Neil Shapiro 	++ans_cnt;
6225b0945b5SGregory Neil Shapiro 	hp->ancount = htons((unsigned short) ans_cnt);
6235b0945b5SGregory Neil Shapiro 
6245b0945b5SGregory Neil Shapiro 	switch (type)
6255b0945b5SGregory Neil Shapiro 	{
6265b0945b5SGregory Neil Shapiro 	  case T_MX:
6275b0945b5SGregory Neil Shapiro 		n = dn_comp(data, cp + 4, ep - cp - QFIXEDSZ, dnptrs, lastdnptr);
6282fb4f839SGregory Neil Shapiro 		DN_COMP_CHK;
6295b0945b5SGregory Neil Shapiro 		PUTSHORT(n + 2, cp);
6305b0945b5SGregory Neil Shapiro 		PUTSHORT(pref, cp);
6315b0945b5SGregory Neil Shapiro 		cp += n;
6325b0945b5SGregory Neil Shapiro 		break;
6335b0945b5SGregory Neil Shapiro 
6345b0945b5SGregory Neil Shapiro 	  case T_TXT:
6355b0945b5SGregory Neil Shapiro 		if (txtlen >= size)
6365b0945b5SGregory Neil Shapiro 			return -1;
6375b0945b5SGregory Neil Shapiro 		PUTSHORT(txtlen, cp);
6385b0945b5SGregory Neil Shapiro 		(void) sm_strlcpy((char *)cp, data, txtlen + 1);
6395b0945b5SGregory Neil Shapiro 		cp += txtlen;
6405b0945b5SGregory Neil Shapiro 		break;
6415b0945b5SGregory Neil Shapiro 
6425b0945b5SGregory Neil Shapiro 	  case T_CNAME:
6435b0945b5SGregory Neil Shapiro 		n = dn_comp(data, cp + 2, ep - cp - QFIXEDSZ, dnptrs, lastdnptr);
6442fb4f839SGregory Neil Shapiro 		DN_COMP_CHK;
6455b0945b5SGregory Neil Shapiro 		PUTSHORT(n, cp);
6465b0945b5SGregory Neil Shapiro 		cp += n;
6475b0945b5SGregory Neil Shapiro 		break;
6485b0945b5SGregory Neil Shapiro 
6495b0945b5SGregory Neil Shapiro #   if defined(T_TLSA)
6505b0945b5SGregory Neil Shapiro 	  case T_TLSA:
6515b0945b5SGregory Neil Shapiro 		{
6525b0945b5SGregory Neil Shapiro 		char *tlsa;
6535b0945b5SGregory Neil Shapiro 
6545b0945b5SGregory Neil Shapiro 		tlsa = hex2bin(data, size);
6555b0945b5SGregory Neil Shapiro 		if (tlsa == NULL)
6565b0945b5SGregory Neil Shapiro 			return (-1);
6575b0945b5SGregory Neil Shapiro 		n = size / 2;
6585b0945b5SGregory Neil Shapiro 		PUTSHORT(n, cp);
6595b0945b5SGregory Neil Shapiro 		(void) memcpy(cp, tlsa, n);
6605b0945b5SGregory Neil Shapiro 		cp += n;
6615b0945b5SGregory Neil Shapiro 		}
6625b0945b5SGregory Neil Shapiro 		break;
6635b0945b5SGregory Neil Shapiro #   endif /* T_TLSA */
6645b0945b5SGregory Neil Shapiro 
6655b0945b5SGregory Neil Shapiro 	  default:
6665b0945b5SGregory Neil Shapiro 		PUTSHORT(size, cp);
6675b0945b5SGregory Neil Shapiro 		(void) memcpy(cp, data, size);
6685b0945b5SGregory Neil Shapiro 		cp += size;
6695b0945b5SGregory Neil Shapiro 		break;
6705b0945b5SGregory Neil Shapiro 	}
6715b0945b5SGregory Neil Shapiro 
6725b0945b5SGregory Neil Shapiro 	return (cp - buf);
6735b0945b5SGregory Neil Shapiro }
6745b0945b5SGregory Neil Shapiro 
6755b0945b5SGregory Neil Shapiro /*
6765b0945b5SGregory Neil Shapiro **  SETHERRNOFROMSTRING -- set h_errno based on text
6775b0945b5SGregory Neil Shapiro **
6785b0945b5SGregory Neil Shapiro **	Parameters:
6795b0945b5SGregory Neil Shapiro **		str -- string which might contain h_errno text
6805b0945b5SGregory Neil Shapiro **		prc -- pointer to rcode (EX_*)
6815b0945b5SGregory Neil Shapiro **
6825b0945b5SGregory Neil Shapiro **	Returns:
6835b0945b5SGregory Neil Shapiro **		h_errno if found
6845b0945b5SGregory Neil Shapiro **		0 otherwise
6855b0945b5SGregory Neil Shapiro */
6865b0945b5SGregory Neil Shapiro 
6875b0945b5SGregory Neil Shapiro int
setherrnofromstring(str,prc)6885b0945b5SGregory Neil Shapiro setherrnofromstring(str, prc)
6895b0945b5SGregory Neil Shapiro 	const char *str;
6905b0945b5SGregory Neil Shapiro 	int *prc;
6915b0945b5SGregory Neil Shapiro {
6925b0945b5SGregory Neil Shapiro 	SM_SET_H_ERRNO(0);
6932fb4f839SGregory Neil Shapiro 	if (SM_IS_EMPTY(str))
6945b0945b5SGregory Neil Shapiro 		return 0;
6955b0945b5SGregory Neil Shapiro 	if (strstr(str, "herrno:") == NULL)
6965b0945b5SGregory Neil Shapiro 		return 0;
6975b0945b5SGregory Neil Shapiro 	if (prc != NULL)
6985b0945b5SGregory Neil Shapiro 		*prc = EX_NOHOST;
6995b0945b5SGregory Neil Shapiro 	if (strstr(str, "host_not_found"))
7005b0945b5SGregory Neil Shapiro 		SM_SET_H_ERRNO(HOST_NOT_FOUND);
7015b0945b5SGregory Neil Shapiro 	else if (strstr(str, "try_again"))
7025b0945b5SGregory Neil Shapiro 	{
7035b0945b5SGregory Neil Shapiro 		SM_SET_H_ERRNO(TRY_AGAIN);
7045b0945b5SGregory Neil Shapiro 		if (prc != NULL)
7055b0945b5SGregory Neil Shapiro 			*prc = EX_TEMPFAIL;
7065b0945b5SGregory Neil Shapiro 	}
7075b0945b5SGregory Neil Shapiro 	else if (strstr(str, "no_recovery"))
7085b0945b5SGregory Neil Shapiro 		SM_SET_H_ERRNO(NO_RECOVERY);
7095b0945b5SGregory Neil Shapiro 	else if (strstr(str, "no_data"))
7105b0945b5SGregory Neil Shapiro 		SM_SET_H_ERRNO(NO_DATA);
7115b0945b5SGregory Neil Shapiro 	else
7125b0945b5SGregory Neil Shapiro 		SM_SET_H_ERRNO(NETDB_INTERNAL);
7135b0945b5SGregory Neil Shapiro 	return h_errno;
7145b0945b5SGregory Neil Shapiro }
7155b0945b5SGregory Neil Shapiro 
7165b0945b5SGregory Neil Shapiro /*
7175b0945b5SGregory Neil Shapiro **  GETTTLFROMSTRING -- extract ttl from a string
7185b0945b5SGregory Neil Shapiro **
7195b0945b5SGregory Neil Shapiro **	Parameters:
7205b0945b5SGregory Neil Shapiro **		str -- string which might contain ttl
7215b0945b5SGregory Neil Shapiro **
7225b0945b5SGregory Neil Shapiro **	Returns:
7235b0945b5SGregory Neil Shapiro **		ttl if found
7245b0945b5SGregory Neil Shapiro **		0 otherwise
7255b0945b5SGregory Neil Shapiro */
7265b0945b5SGregory Neil Shapiro 
7275b0945b5SGregory Neil Shapiro int
getttlfromstring(str)7285b0945b5SGregory Neil Shapiro getttlfromstring(str)
7295b0945b5SGregory Neil Shapiro 	const char *str;
7305b0945b5SGregory Neil Shapiro {
7312fb4f839SGregory Neil Shapiro 	if (SM_IS_EMPTY(str))
7325b0945b5SGregory Neil Shapiro 		return 0;
7335b0945b5SGregory Neil Shapiro #define TTL_PRE "ttl="
7345b0945b5SGregory Neil Shapiro 	if (strstr(str, TTL_PRE) == NULL)
7355b0945b5SGregory Neil Shapiro 		return 0;
7365b0945b5SGregory Neil Shapiro 	return strtoul(str + strlen(TTL_PRE), NULL, 10);
7375b0945b5SGregory Neil Shapiro }
7385b0945b5SGregory Neil Shapiro 
7395b0945b5SGregory Neil Shapiro 
7405b0945b5SGregory Neil Shapiro #   if defined(T_TLSA)
7415b0945b5SGregory Neil Shapiro /*
7425b0945b5SGregory Neil Shapiro **  HEX2BIN -- convert hex string to binary TLSA RR
7435b0945b5SGregory Neil Shapiro **
7445b0945b5SGregory Neil Shapiro **	Parameters:
7455b0945b5SGregory Neil Shapiro **		p --  hex representation of TLSA RR
7465b0945b5SGregory Neil Shapiro **		size -- length of p
7475b0945b5SGregory Neil Shapiro **
7485b0945b5SGregory Neil Shapiro **	Returns:
7495b0945b5SGregory Neil Shapiro **		pointer to binary TLSA RR
7505b0945b5SGregory Neil Shapiro **		NULL: error
7515b0945b5SGregory Neil Shapiro */
7525b0945b5SGregory Neil Shapiro 
7535b0945b5SGregory Neil Shapiro static char *
hex2bin(p,size)7545b0945b5SGregory Neil Shapiro hex2bin(p, size)
7555b0945b5SGregory Neil Shapiro 	const char *p;
7565b0945b5SGregory Neil Shapiro 	int size;
7575b0945b5SGregory Neil Shapiro {
7585b0945b5SGregory Neil Shapiro 	int i, pos, txtlen;
7595b0945b5SGregory Neil Shapiro 	char *tlsa;
7605b0945b5SGregory Neil Shapiro 
7615b0945b5SGregory Neil Shapiro 	txtlen = size / 2;
7625b0945b5SGregory Neil Shapiro 	if (txtlen * 2 == size)
7635b0945b5SGregory Neil Shapiro 	{
7645b0945b5SGregory Neil Shapiro 		if (LogLevel > 5)
7655b0945b5SGregory Neil Shapiro 			sm_syslog(LOG_WARNING, NOQID,
7665b0945b5SGregory Neil Shapiro 				  "ERROR: hex2bin: size %d wrong", size);
7675b0945b5SGregory Neil Shapiro 		return NULL;
7685b0945b5SGregory Neil Shapiro 	}
7695b0945b5SGregory Neil Shapiro 	tlsa = sm_malloc(txtlen + 1);
7705b0945b5SGregory Neil Shapiro 	if (tlsa == NULL)
7715b0945b5SGregory Neil Shapiro 	{
7725b0945b5SGregory Neil Shapiro 		if (tTd(8, 17))
7735b0945b5SGregory Neil Shapiro 			sm_dprintf("len=%d, tlsa=NULL\n", txtlen);
7745b0945b5SGregory Neil Shapiro 		return NULL;
7755b0945b5SGregory Neil Shapiro 	}
7765b0945b5SGregory Neil Shapiro 
7775b0945b5SGregory Neil Shapiro #define CHAR2INT(c)	(((c) <= '9') ? ((c) - '0') : (toupper(c) - 'A' + 10))
7785b0945b5SGregory Neil Shapiro 	for (i = 0, pos = 0; i + 1 < size && pos < txtlen; i += 2, pos++)
7795b0945b5SGregory Neil Shapiro 		tlsa[pos] = CHAR2INT(p[i]) * 16 + CHAR2INT(p[i+1]);
7805b0945b5SGregory Neil Shapiro 
7815b0945b5SGregory Neil Shapiro 	return tlsa;
7825b0945b5SGregory Neil Shapiro }
7835b0945b5SGregory Neil Shapiro #   endif /* T_TLSA */
7845b0945b5SGregory Neil Shapiro 
7855b0945b5SGregory Neil Shapiro const char *
rr_type2tag(rr_type)7865b0945b5SGregory Neil Shapiro rr_type2tag(rr_type)
7875b0945b5SGregory Neil Shapiro 	int rr_type;
7885b0945b5SGregory Neil Shapiro {
7895b0945b5SGregory Neil Shapiro 	switch (rr_type)
7905b0945b5SGregory Neil Shapiro 	{
7915b0945b5SGregory Neil Shapiro 	  case T_A:
7925b0945b5SGregory Neil Shapiro 		return "ipv4";
7935b0945b5SGregory Neil Shapiro #   if NETINET6
7945b0945b5SGregory Neil Shapiro 	  case T_AAAA:
7955b0945b5SGregory Neil Shapiro 		return "ipv6";
7965b0945b5SGregory Neil Shapiro #   endif
7975b0945b5SGregory Neil Shapiro 	  case T_CNAME:
7985b0945b5SGregory Neil Shapiro 		return "cname";
7995b0945b5SGregory Neil Shapiro 	  case T_MX:
8005b0945b5SGregory Neil Shapiro 		return "mx";
8015b0945b5SGregory Neil Shapiro #   ifdef T_TLSA
8025b0945b5SGregory Neil Shapiro 	  case T_TLSA:
8035b0945b5SGregory Neil Shapiro 		return "tlsa";
8045b0945b5SGregory Neil Shapiro #   endif
8055b0945b5SGregory Neil Shapiro 	}
8065b0945b5SGregory Neil Shapiro 	return NULL;
8075b0945b5SGregory Neil Shapiro }
8085b0945b5SGregory Neil Shapiro 
8095b0945b5SGregory Neil Shapiro /*
8105b0945b5SGregory Neil Shapiro **  DNSCRTRR -- create DNS RR
8115b0945b5SGregory Neil Shapiro **
8125b0945b5SGregory Neil Shapiro **	Parameters:
8135b0945b5SGregory Neil Shapiro **		domain -- original query domain
8145b0945b5SGregory Neil Shapiro **		query -- name of query
8155b0945b5SGregory Neil Shapiro **		qtype -- resource record type of query
8165b0945b5SGregory Neil Shapiro **		value -- (list of) data to set
8175b0945b5SGregory Neil Shapiro **		rr_type -- resource record type
8185b0945b5SGregory Neil Shapiro **		flags -- flags how to handle various lookups
8195b0945b5SGregory Neil Shapiro **		herr -- (pointer to) h_errno (output if non-NULL)
8205b0945b5SGregory Neil Shapiro **		adp -- (pointer to) ad flag
8215b0945b5SGregory Neil Shapiro **		answer -- buffer for RRs
8225b0945b5SGregory Neil Shapiro **		anslen -- size of answer
8235b0945b5SGregory Neil Shapiro **		anspos -- current position in answer
8245b0945b5SGregory Neil Shapiro **
8255b0945b5SGregory Neil Shapiro **	Returns:
8265b0945b5SGregory Neil Shapiro **		>0: length of data in answer
8275b0945b5SGregory Neil Shapiro **		<0: error, check *herr
8285b0945b5SGregory Neil Shapiro */
8295b0945b5SGregory Neil Shapiro 
8305b0945b5SGregory Neil Shapiro static int
dnscrtrr(domain,query,qtype,value,rr_type,flags,herr,adp,answer,anslen,anspos)8315b0945b5SGregory Neil Shapiro dnscrtrr(domain, query, qtype, value, rr_type, flags, herr, adp, answer, anslen, anspos)
8325b0945b5SGregory Neil Shapiro 	const char *domain;
8335b0945b5SGregory Neil Shapiro 	const char *query;
8345b0945b5SGregory Neil Shapiro 	int qtype;
8355b0945b5SGregory Neil Shapiro 	char *value;
8365b0945b5SGregory Neil Shapiro 	int rr_type;
8375b0945b5SGregory Neil Shapiro 	unsigned int flags;
8385b0945b5SGregory Neil Shapiro 	int *herr;
8395b0945b5SGregory Neil Shapiro 	int *adp;
8405b0945b5SGregory Neil Shapiro 	unsigned char *answer;
8415b0945b5SGregory Neil Shapiro 	int anslen;
8425b0945b5SGregory Neil Shapiro 	unsigned char *anspos;
8435b0945b5SGregory Neil Shapiro {
8445b0945b5SGregory Neil Shapiro 	SOCKADDR addr;
8455b0945b5SGregory Neil Shapiro 	int ttl, ad, rlen;
8465b0945b5SGregory Neil Shapiro 	char *p, *token;
8475b0945b5SGregory Neil Shapiro 	char data[IN6ADDRSZ];
8485b0945b5SGregory Neil Shapiro 	char rhs[MAXLINE];
8495b0945b5SGregory Neil Shapiro 
8505b0945b5SGregory Neil Shapiro 	rlen = -1;
8512fb4f839SGregory Neil Shapiro 	if (SM_IS_EMPTY(value))
8525b0945b5SGregory Neil Shapiro 		return rlen;
8535b0945b5SGregory Neil Shapiro 	SM_REQUIRE(adp != NULL);
8545b0945b5SGregory Neil Shapiro 	(void) sm_strlcpy(rhs, value, sizeof(rhs));
8555b0945b5SGregory Neil Shapiro 	p = rhs;
8565b0945b5SGregory Neil Shapiro 	if (setherrnofromstring(p, NULL) != 0)
8575b0945b5SGregory Neil Shapiro 	{
8585b0945b5SGregory Neil Shapiro 		if (herr != NULL)
8595b0945b5SGregory Neil Shapiro 			*herr = h_errno;
8605b0945b5SGregory Neil Shapiro 		if (tTd(8, 16))
8615b0945b5SGregory Neil Shapiro 			sm_dprintf("dnscrtrr rhs=%s h_errno=%d (%s)\n",
8625b0945b5SGregory Neil Shapiro 				p, h_errno, herrno2txt(h_errno));
8635b0945b5SGregory Neil Shapiro 		return rlen;
8645b0945b5SGregory Neil Shapiro 	}
8655b0945b5SGregory Neil Shapiro 
8665b0945b5SGregory Neil Shapiro 	ttl = 0;
8675b0945b5SGregory Neil Shapiro 	ad = 0;
8685b0945b5SGregory Neil Shapiro 	for (token = p; token != NULL && *token != '\0'; token = p)
8695b0945b5SGregory Neil Shapiro 	{
8705b0945b5SGregory Neil Shapiro 		rlen = 0;
8715b0945b5SGregory Neil Shapiro 		while (p != NULL && *p != '\0' && !SM_ISSPACE(*p))
8725b0945b5SGregory Neil Shapiro 			++p;
8735b0945b5SGregory Neil Shapiro 		if (SM_ISSPACE(*p))
8745b0945b5SGregory Neil Shapiro 			*p++ = '\0';
8755b0945b5SGregory Neil Shapiro 		sm_dprintf("dnscrtrr: token=%s\n", token);
8765b0945b5SGregory Neil Shapiro 		if (strcmp(token, "ad") == 0)
8775b0945b5SGregory Neil Shapiro 		{
8785b0945b5SGregory Neil Shapiro 			bool adflag;
8795b0945b5SGregory Neil Shapiro 
8805b0945b5SGregory Neil Shapiro 			adflag = (_res.options & RES_USE_DNSSEC) != 0;
8815b0945b5SGregory Neil Shapiro 
8825b0945b5SGregory Neil Shapiro 			/* maybe print this only for the final RR? */
8835b0945b5SGregory Neil Shapiro 			if (tTd(8, 61))
8845b0945b5SGregory Neil Shapiro 				sm_dprintf("dnscrtrr: ad=1, adp=%d, adflag=%d\n",
8855b0945b5SGregory Neil Shapiro 					*adp, adflag);
8865b0945b5SGregory Neil Shapiro 			if (*adp != 0 && adflag)
8875b0945b5SGregory Neil Shapiro 			{
8885b0945b5SGregory Neil Shapiro 				*adp = 1;
8895b0945b5SGregory Neil Shapiro 				ad = 1;
8905b0945b5SGregory Neil Shapiro 			}
8915b0945b5SGregory Neil Shapiro 			continue;
8925b0945b5SGregory Neil Shapiro 		}
8935b0945b5SGregory Neil Shapiro 		if (ttl == 0 && (ttl = getttlfromstring(token)) > 0)
8945b0945b5SGregory Neil Shapiro 		{
8955b0945b5SGregory Neil Shapiro 			if (tTd(8, 61))
8965b0945b5SGregory Neil Shapiro 				sm_dprintf("dnscrtrr: ttl=%d\n", ttl);
8975b0945b5SGregory Neil Shapiro 			continue;
8985b0945b5SGregory Neil Shapiro 		}
8995b0945b5SGregory Neil Shapiro 
9005b0945b5SGregory Neil Shapiro 		if (rr_type == T_A)
9015b0945b5SGregory Neil Shapiro 		{
9025b0945b5SGregory Neil Shapiro 			addr.sin.sin_addr.s_addr = inet_addr(token);
9035b0945b5SGregory Neil Shapiro 			(void) memmove(data, (void *)&addr.sin.sin_addr.s_addr,
9045b0945b5SGregory Neil Shapiro 				INADDRSZ);
9055b0945b5SGregory Neil Shapiro 			rlen = gen_dns_reply(answer, anslen, anspos,
9065b0945b5SGregory Neil Shapiro 				query, qtype, domain, C_IN, rr_type, ttl,
9075b0945b5SGregory Neil Shapiro 				INADDRSZ, data, 0, 0, ad);
9085b0945b5SGregory Neil Shapiro 		}
9095b0945b5SGregory Neil Shapiro 
9105b0945b5SGregory Neil Shapiro #   if NETINET6
9115b0945b5SGregory Neil Shapiro 		if (rr_type == T_AAAA)
9125b0945b5SGregory Neil Shapiro 		{
9135b0945b5SGregory Neil Shapiro 			anynet_pton(AF_INET6, token, &addr.sin6.sin6_addr);
9145b0945b5SGregory Neil Shapiro 			memmove(data, (void *)&addr.sin6.sin6_addr, IN6ADDRSZ);
9155b0945b5SGregory Neil Shapiro 			rlen = gen_dns_reply(answer, anslen, anspos,
9165b0945b5SGregory Neil Shapiro 				query, qtype, domain, C_IN, rr_type, ttl,
9175b0945b5SGregory Neil Shapiro 				IN6ADDRSZ, data, 0, 0, ad);
9185b0945b5SGregory Neil Shapiro 		}
9195b0945b5SGregory Neil Shapiro #   endif /* NETINET6 */
9205b0945b5SGregory Neil Shapiro 
9215b0945b5SGregory Neil Shapiro 		if (rr_type == T_MX)
9225b0945b5SGregory Neil Shapiro 		{
9235b0945b5SGregory Neil Shapiro 			char *endptr;
9245b0945b5SGregory Neil Shapiro 			int pref;
9255b0945b5SGregory Neil Shapiro 
9265b0945b5SGregory Neil Shapiro 			pref = (int) strtoul(token, &endptr, 10);
9275b0945b5SGregory Neil Shapiro 			if (endptr == NULL || *endptr != ':')
9285b0945b5SGregory Neil Shapiro 				goto error;
9295b0945b5SGregory Neil Shapiro 			token = endptr + 1;
9305b0945b5SGregory Neil Shapiro 			rlen = gen_dns_reply(answer, anslen, anspos,
9315b0945b5SGregory Neil Shapiro 				query, qtype, domain, C_IN, rr_type, ttl,
9325b0945b5SGregory Neil Shapiro 				strlen(token) + 1, token, 0, pref, ad);
9335b0945b5SGregory Neil Shapiro 			if (tTd(8, 50))
9342fb4f839SGregory Neil Shapiro 				sm_dprintf("dnscrtrr: mx=%s, pref=%d, rlen=%d\n",
9352fb4f839SGregory Neil Shapiro 					token, pref, rlen);
9365b0945b5SGregory Neil Shapiro 		}
9375b0945b5SGregory Neil Shapiro 
9385b0945b5SGregory Neil Shapiro #   ifdef T_TLSA
9395b0945b5SGregory Neil Shapiro 		if (rr_type == T_TLSA)
9405b0945b5SGregory Neil Shapiro 			rlen = gen_dns_reply(answer, anslen, anspos,
9415b0945b5SGregory Neil Shapiro 				query, qtype, domain, C_IN, rr_type, ttl,
9425b0945b5SGregory Neil Shapiro 				strlen(token) + 1, token, 0, 0, ad);
9435b0945b5SGregory Neil Shapiro #   endif
9445b0945b5SGregory Neil Shapiro 
9455b0945b5SGregory Neil Shapiro 		if (rr_type == T_CNAME)
9465b0945b5SGregory Neil Shapiro 			rlen = gen_dns_reply(answer, anslen, anspos,
9475b0945b5SGregory Neil Shapiro 				query, qtype, domain, C_IN, rr_type, ttl,
9485b0945b5SGregory Neil Shapiro 				strlen(token), token, 0, 0, ad);
9495b0945b5SGregory Neil Shapiro 		if (rlen < 0)
9505b0945b5SGregory Neil Shapiro 			goto error;
9515b0945b5SGregory Neil Shapiro 		if (rlen > 0)
9525b0945b5SGregory Neil Shapiro 			anspos = answer + rlen;
9535b0945b5SGregory Neil Shapiro 	}
9545b0945b5SGregory Neil Shapiro 
9555b0945b5SGregory Neil Shapiro 	if (ad != 1)
9565b0945b5SGregory Neil Shapiro 		*adp = 0;
9575b0945b5SGregory Neil Shapiro 
9585b0945b5SGregory Neil Shapiro 	return rlen;
9595b0945b5SGregory Neil Shapiro 
9605b0945b5SGregory Neil Shapiro   error:
9615b0945b5SGregory Neil Shapiro 	if (herr != NULL && 0 == *herr)
9625b0945b5SGregory Neil Shapiro 		*herr = NO_RECOVERY;
9635b0945b5SGregory Neil Shapiro 	return -1;
9645b0945b5SGregory Neil Shapiro }
9655b0945b5SGregory Neil Shapiro 
9665b0945b5SGregory Neil Shapiro /*
9675b0945b5SGregory Neil Shapiro **  TSTDNS_SEARCH -- replacement for res_search() for testing
9685b0945b5SGregory Neil Shapiro **
9695b0945b5SGregory Neil Shapiro **	Parameters:
9705b0945b5SGregory Neil Shapiro **		domain -- query domain
9715b0945b5SGregory Neil Shapiro **		class -- class
9725b0945b5SGregory Neil Shapiro **		type -- resource record type
9735b0945b5SGregory Neil Shapiro **		answer -- buffer for RRs
9745b0945b5SGregory Neil Shapiro **		anslen -- size of answer
9755b0945b5SGregory Neil Shapiro **
9765b0945b5SGregory Neil Shapiro **	Returns:
9775b0945b5SGregory Neil Shapiro **		>0: length of data in answer
9785b0945b5SGregory Neil Shapiro **		<0: error, check h_errno
9795b0945b5SGregory Neil Shapiro */
9805b0945b5SGregory Neil Shapiro 
9815b0945b5SGregory Neil Shapiro int
tstdns_search(domain,class,type,answer,anslen)9825b0945b5SGregory Neil Shapiro tstdns_search(domain, class, type, answer, anslen)
9835b0945b5SGregory Neil Shapiro 	const char *domain;
9845b0945b5SGregory Neil Shapiro 	int class;
9855b0945b5SGregory Neil Shapiro 	int type;
9865b0945b5SGregory Neil Shapiro 	unsigned char *answer;
9875b0945b5SGregory Neil Shapiro 	int anslen;
9885b0945b5SGregory Neil Shapiro {
9895b0945b5SGregory Neil Shapiro 	int rlen, ad, maprcode, cnt, flags, herr;
9905b0945b5SGregory Neil Shapiro 	bool found_cname;
9915b0945b5SGregory Neil Shapiro 	const char *query;
9925b0945b5SGregory Neil Shapiro 	char *p;
9935b0945b5SGregory Neil Shapiro 	const char *tag;
9945b0945b5SGregory Neil Shapiro 	char *av[2];
9955b0945b5SGregory Neil Shapiro 	STAB *map;
9962fb4f839SGregory Neil Shapiro #   if _FFR_8BITENVADDR
9972fb4f839SGregory Neil Shapiro 	char qbuf[MAXNAME_I];
9982fb4f839SGregory Neil Shapiro 	char *qdomain;
9992fb4f839SGregory Neil Shapiro #   else
10002fb4f839SGregory Neil Shapiro #    define qdomain domain
10012fb4f839SGregory Neil Shapiro #   endif
10022fb4f839SGregory Neil Shapiro 	char key[MAXNAME_I + 16];
10035b0945b5SGregory Neil Shapiro 	char rhs[MAXLINE];
10045b0945b5SGregory Neil Shapiro 	unsigned char *anspos;
10055b0945b5SGregory Neil Shapiro 
10065b0945b5SGregory Neil Shapiro 	rlen = -1;
10075b0945b5SGregory Neil Shapiro 	herr = 0;
10085b0945b5SGregory Neil Shapiro 	if (class != C_IN)
10095b0945b5SGregory Neil Shapiro 		goto error;
10102fb4f839SGregory Neil Shapiro 	if (SM_IS_EMPTY(domain))
10115b0945b5SGregory Neil Shapiro 		goto error;
10125b0945b5SGregory Neil Shapiro 	tag = rr_type2tag(type);
10135b0945b5SGregory Neil Shapiro 	if (tag == NULL)
10145b0945b5SGregory Neil Shapiro 		goto error;
10155b0945b5SGregory Neil Shapiro 	maprcode = EX_OK;
10165b0945b5SGregory Neil Shapiro 	ad = -1;
10175b0945b5SGregory Neil Shapiro 	flags = 0;
10182fb4f839SGregory Neil Shapiro #   if _FFR_8BITENVADDR
10192fb4f839SGregory Neil Shapiro 	if (tTd(8, 62))
10202fb4f839SGregory Neil Shapiro 		sm_dprintf("domain=%s\n", domain);
10212fb4f839SGregory Neil Shapiro 	(void) dequote_internal_chars((char *)domain, qbuf, sizeof(qbuf));
10222fb4f839SGregory Neil Shapiro 	query = qbuf;
10232fb4f839SGregory Neil Shapiro 	qdomain = qbuf;
10242fb4f839SGregory Neil Shapiro 	if (tTd(8, 63))
10252fb4f839SGregory Neil Shapiro 		sm_dprintf("qdomain=%s\n", qdomain);
10262fb4f839SGregory Neil Shapiro #   else
10275b0945b5SGregory Neil Shapiro 	query = domain;
10282fb4f839SGregory Neil Shapiro #   endif /* _FFR_8BITENVADDR */
10295b0945b5SGregory Neil Shapiro 	anspos = NULL;
10305b0945b5SGregory Neil Shapiro 
10315b0945b5SGregory Neil Shapiro 	map = stab("access", ST_MAP, ST_FIND);
10325b0945b5SGregory Neil Shapiro 	if (NULL == map)
10335b0945b5SGregory Neil Shapiro 	{
10345b0945b5SGregory Neil Shapiro 		sm_dprintf("access map not found\n");
10355b0945b5SGregory Neil Shapiro 		goto error;
10365b0945b5SGregory Neil Shapiro 	}
10375b0945b5SGregory Neil Shapiro 	if (!bitset(MF_OPEN, map->s_map.map_mflags) &&
10385b0945b5SGregory Neil Shapiro 	    !openmap(&(map->s_map)))
10395b0945b5SGregory Neil Shapiro 	{
10405b0945b5SGregory Neil Shapiro 		sm_dprintf("access map open failed\n");
10415b0945b5SGregory Neil Shapiro 		goto error;
10425b0945b5SGregory Neil Shapiro 	}
10435b0945b5SGregory Neil Shapiro 
10445b0945b5SGregory Neil Shapiro /*
10455b0945b5SGregory Neil Shapiro **  Look up tag:domain, if not found and domain does not end with a dot
10465b0945b5SGregory Neil Shapiro **  (and the proper debug level is selected), also try with trailing dot.
10475b0945b5SGregory Neil Shapiro */
10485b0945b5SGregory Neil Shapiro 
10495b0945b5SGregory Neil Shapiro #define SM_LOOKUP2(tag)	\
10505b0945b5SGregory Neil Shapiro 	do {	\
10515b0945b5SGregory Neil Shapiro 		int len;	\
10525b0945b5SGregory Neil Shapiro 				\
10532fb4f839SGregory Neil Shapiro 		len = strlen(qdomain);	\
10545b0945b5SGregory Neil Shapiro 		av[0] = key;	\
10555b0945b5SGregory Neil Shapiro 		av[1] = NULL;	\
10562fb4f839SGregory Neil Shapiro 		snprintf(key, sizeof(key), "%s:%s", tag, qdomain); \
10575b0945b5SGregory Neil Shapiro 		p = (*map->s_map.map_class->map_lookup)(&map->s_map, key, av, \
10585b0945b5SGregory Neil Shapiro 			&maprcode);	\
10595b0945b5SGregory Neil Shapiro 		if (p != NULL)	\
10605b0945b5SGregory Neil Shapiro 			break;	\
10612fb4f839SGregory Neil Shapiro 		if (!tTd(8, 112) || (len > 0 && '.' == qdomain[len - 1])) \
10625b0945b5SGregory Neil Shapiro 			break;	\
10632fb4f839SGregory Neil Shapiro 		snprintf(key, sizeof(key), "%s:%s.", tag, qdomain); \
10645b0945b5SGregory Neil Shapiro 		p = (*map->s_map.map_class->map_lookup)(&map->s_map, key, av, \
10655b0945b5SGregory Neil Shapiro 			&maprcode);	\
10665b0945b5SGregory Neil Shapiro 	} while (0)
10675b0945b5SGregory Neil Shapiro 
10685b0945b5SGregory Neil Shapiro 	cnt = 0;
10695b0945b5SGregory Neil Shapiro 	found_cname = false;
10705b0945b5SGregory Neil Shapiro 	while (cnt < 6)
10715b0945b5SGregory Neil Shapiro 	{
10725b0945b5SGregory Neil Shapiro 		char *last;
10735b0945b5SGregory Neil Shapiro 
10745b0945b5SGregory Neil Shapiro 		/* Should this try with/without trailing dot? */
10755b0945b5SGregory Neil Shapiro 		SM_LOOKUP2(tag);
10765b0945b5SGregory Neil Shapiro 		if (p != NULL)
10775b0945b5SGregory Neil Shapiro 		{
10785b0945b5SGregory Neil Shapiro 			sm_dprintf("access map lookup key=%s, value=%s\n", key,
10795b0945b5SGregory Neil Shapiro 				p);
10805b0945b5SGregory Neil Shapiro 			break;
10815b0945b5SGregory Neil Shapiro 		}
10825b0945b5SGregory Neil Shapiro 		if (NULL == p && (flags & RR_NO_CNAME) == 0)
10835b0945b5SGregory Neil Shapiro 		{
10845b0945b5SGregory Neil Shapiro 			sm_dprintf("access map lookup failed key=%s, try cname\n",
10855b0945b5SGregory Neil Shapiro 				key);
10865b0945b5SGregory Neil Shapiro 			SM_LOOKUP2("cname");
10875b0945b5SGregory Neil Shapiro 			if (p != NULL)
10885b0945b5SGregory Neil Shapiro 			{
10895b0945b5SGregory Neil Shapiro 				sm_dprintf("cname lookup key=%s, value=%s, ad=%d\n",
10905b0945b5SGregory Neil Shapiro 					key, p, ad);
10912fb4f839SGregory Neil Shapiro 				rlen = dnscrtrr(qdomain, query, type, p, T_CNAME,
10925b0945b5SGregory Neil Shapiro 						flags, &herr, &ad, answer,
10935b0945b5SGregory Neil Shapiro 						anslen, anspos);
10945b0945b5SGregory Neil Shapiro 				if (rlen < 0)
10955b0945b5SGregory Neil Shapiro 					goto error;
10965b0945b5SGregory Neil Shapiro 				if (rlen > 0)
10975b0945b5SGregory Neil Shapiro 					anspos = answer + rlen;
10985b0945b5SGregory Neil Shapiro 				found_cname = true;
10995b0945b5SGregory Neil Shapiro 			}
11005b0945b5SGregory Neil Shapiro 		}
11015b0945b5SGregory Neil Shapiro 		if (NULL == p)
11025b0945b5SGregory Neil Shapiro 			break;
11035b0945b5SGregory Neil Shapiro 
11045b0945b5SGregory Neil Shapiro 		(void) sm_strlcpy(rhs, p, sizeof(rhs));
11055b0945b5SGregory Neil Shapiro 		p = rhs;
11065b0945b5SGregory Neil Shapiro 
11075b0945b5SGregory Neil Shapiro 		/* skip (leading) ad/ttl: look for last ' ' */
11085b0945b5SGregory Neil Shapiro 		if ((last = strrchr(p, ' ')) != NULL && last[1] != '\0')
11092fb4f839SGregory Neil Shapiro 			qdomain = last + 1;
11105b0945b5SGregory Neil Shapiro 		else
11112fb4f839SGregory Neil Shapiro 			qdomain = p;
11125b0945b5SGregory Neil Shapiro 		++cnt;
11135b0945b5SGregory Neil Shapiro 	}
11145b0945b5SGregory Neil Shapiro 	if (NULL == p)
11155b0945b5SGregory Neil Shapiro 	{
11165b0945b5SGregory Neil Shapiro 		int t;
11175b0945b5SGregory Neil Shapiro 		char *tags[] = { "ipv4", "mx", "tlsa",
11185b0945b5SGregory Neil Shapiro #   if NETINET6
11195b0945b5SGregory Neil Shapiro 			"ipv6",
11205b0945b5SGregory Neil Shapiro #   endif
11215b0945b5SGregory Neil Shapiro 			NULL
11225b0945b5SGregory Neil Shapiro 		};
11235b0945b5SGregory Neil Shapiro 
11245b0945b5SGregory Neil Shapiro 		for (t = 0; tags[t] != NULL; t++)
11255b0945b5SGregory Neil Shapiro 		{
11265b0945b5SGregory Neil Shapiro 			if (strcmp(tag, tags[t]) == 0)
11275b0945b5SGregory Neil Shapiro 				continue;
11285b0945b5SGregory Neil Shapiro 			SM_LOOKUP2(tags[t]);
11295b0945b5SGregory Neil Shapiro 			if (p != NULL)
11305b0945b5SGregory Neil Shapiro 			{
11315b0945b5SGregory Neil Shapiro 				sm_dprintf("access map lookup failed key=%s:%s, but found key=%s\n",
11322fb4f839SGregory Neil Shapiro 					tag, qdomain, key);
11335b0945b5SGregory Neil Shapiro 				herr = NO_DATA;
11345b0945b5SGregory Neil Shapiro 				goto error;
11355b0945b5SGregory Neil Shapiro 			}
11365b0945b5SGregory Neil Shapiro 		}
11375b0945b5SGregory Neil Shapiro 		sm_dprintf("access map lookup failed key=%s\n", key);
11385b0945b5SGregory Neil Shapiro 		herr = HOST_NOT_FOUND;
11395b0945b5SGregory Neil Shapiro 		goto error;
11405b0945b5SGregory Neil Shapiro 	}
11415b0945b5SGregory Neil Shapiro 	if (found_cname && (flags & RR_ONLY_CNAME) != 0)
11425b0945b5SGregory Neil Shapiro 		return rlen;
11432fb4f839SGregory Neil Shapiro 	rlen = dnscrtrr(qdomain, query, type, p, type, flags, &herr, &ad,
11445b0945b5SGregory Neil Shapiro 			answer, anslen, anspos);
11455b0945b5SGregory Neil Shapiro 	if (rlen < 0)
11465b0945b5SGregory Neil Shapiro 		goto error;
11475b0945b5SGregory Neil Shapiro 	return rlen;
11485b0945b5SGregory Neil Shapiro 
11495b0945b5SGregory Neil Shapiro   error:
11505b0945b5SGregory Neil Shapiro 	if (0 == herr)
11515b0945b5SGregory Neil Shapiro 		herr = NO_RECOVERY;
11525b0945b5SGregory Neil Shapiro 	SM_SET_H_ERRNO(herr);
11535b0945b5SGregory Neil Shapiro 	sm_dprintf("rlen=%d, herr=%d\n", rlen, herr);
11545b0945b5SGregory Neil Shapiro 	return -1;
11555b0945b5SGregory Neil Shapiro }
11565b0945b5SGregory Neil Shapiro 
11575b0945b5SGregory Neil Shapiro /*
11585b0945b5SGregory Neil Shapiro **  TSTDNS_QUERYDOMAIN -- replacement for res_querydomain() for testing
11595b0945b5SGregory Neil Shapiro **
11605b0945b5SGregory Neil Shapiro **	Parameters:
11615b0945b5SGregory Neil Shapiro **		name -- query name
11625b0945b5SGregory Neil Shapiro **		domain -- query domain
11635b0945b5SGregory Neil Shapiro **		class -- class
11645b0945b5SGregory Neil Shapiro **		type -- resource record type
11655b0945b5SGregory Neil Shapiro **		answer -- buffer for RRs
11665b0945b5SGregory Neil Shapiro **		anslen -- size of answer
11675b0945b5SGregory Neil Shapiro **
11685b0945b5SGregory Neil Shapiro **	Returns:
11695b0945b5SGregory Neil Shapiro **		>0: length of data in answer
11705b0945b5SGregory Neil Shapiro **		<0: error, check h_errno
11715b0945b5SGregory Neil Shapiro */
11725b0945b5SGregory Neil Shapiro 
11735b0945b5SGregory Neil Shapiro int
tstdns_querydomain(name,domain,class,type,answer,anslen)11745b0945b5SGregory Neil Shapiro tstdns_querydomain(name, domain, class, type, answer, anslen)
11755b0945b5SGregory Neil Shapiro 	const char *name;
11765b0945b5SGregory Neil Shapiro 	const char *domain;
11775b0945b5SGregory Neil Shapiro 	int class;
11785b0945b5SGregory Neil Shapiro 	int type;
11795b0945b5SGregory Neil Shapiro 	unsigned char *answer;
11805b0945b5SGregory Neil Shapiro 	int anslen;
11815b0945b5SGregory Neil Shapiro {
11822fb4f839SGregory Neil Shapiro 	char query[MAXNAME_I];
11835b0945b5SGregory Neil Shapiro 	int len;
11845b0945b5SGregory Neil Shapiro 
11855b0945b5SGregory Neil Shapiro 	if (NULL == name)
11865b0945b5SGregory Neil Shapiro 		goto error;
11872fb4f839SGregory Neil Shapiro 	if (SM_IS_EMPTY(domain))
11885b0945b5SGregory Neil Shapiro 		return tstdns_search(name, class, type, answer, anslen);
11895b0945b5SGregory Neil Shapiro 
11905b0945b5SGregory Neil Shapiro 	len = snprintf(query, sizeof(query), "%s.%s", name, domain);
11915b0945b5SGregory Neil Shapiro 	if (len >= (int)sizeof(query))
11925b0945b5SGregory Neil Shapiro 		goto error;
11935b0945b5SGregory Neil Shapiro 	return tstdns_search(query, class, type, answer, anslen);
11945b0945b5SGregory Neil Shapiro 
11955b0945b5SGregory Neil Shapiro   error:
11965b0945b5SGregory Neil Shapiro 	SM_SET_H_ERRNO(NO_RECOVERY);
11975b0945b5SGregory Neil Shapiro 	return -1;
11985b0945b5SGregory Neil Shapiro }
11995b0945b5SGregory Neil Shapiro 
12005b0945b5SGregory Neil Shapiro #  endif /* DNSSEC_TEST */
12015b0945b5SGregory Neil Shapiro 
12025b0945b5SGregory Neil Shapiro /*
12035b0945b5SGregory Neil Shapiro **  DNS_LOOKUP_INT -- perform DNS lookup
120440266059SGregory Neil Shapiro **
120540266059SGregory Neil Shapiro **	Parameters:
120640266059SGregory Neil Shapiro **		domain -- name to look up
120740266059SGregory Neil Shapiro **		rr_class -- resource record class
120840266059SGregory Neil Shapiro **		rr_type -- resource record type
120940266059SGregory Neil Shapiro **		retrans -- retransmission timeout
121040266059SGregory Neil Shapiro **		retry -- number of retries
12115b0945b5SGregory Neil Shapiro **		options -- DNS resolver options
12125b0945b5SGregory Neil Shapiro **		flags -- currently only passed to parse_dns_reply()
12135b0945b5SGregory Neil Shapiro **		err -- (pointer to) errno (output if non-NULL)
12145b0945b5SGregory Neil Shapiro **		herr -- (pointer to) h_errno (output if non-NULL)
121540266059SGregory Neil Shapiro **
121640266059SGregory Neil Shapiro **	Returns:
121740266059SGregory Neil Shapiro **		result of lookup if succeeded.
121840266059SGregory Neil Shapiro **		NULL otherwise.
121940266059SGregory Neil Shapiro */
122040266059SGregory Neil Shapiro 
122140266059SGregory Neil Shapiro DNS_REPLY_T *
dns_lookup_int(domain,rr_class,rr_type,retrans,retry,options,flags,err,herr)12225b0945b5SGregory Neil Shapiro dns_lookup_int(domain, rr_class, rr_type, retrans, retry, options, flags, err, herr)
122340266059SGregory Neil Shapiro 	const char *domain;
122440266059SGregory Neil Shapiro 	int rr_class;
122540266059SGregory Neil Shapiro 	int rr_type;
122640266059SGregory Neil Shapiro 	time_t retrans;
122740266059SGregory Neil Shapiro 	int retry;
12285b0945b5SGregory Neil Shapiro 	unsigned int options;
12295b0945b5SGregory Neil Shapiro 	unsigned int flags;
12305b0945b5SGregory Neil Shapiro 	int *err;
12315b0945b5SGregory Neil Shapiro 	int *herr;
123240266059SGregory Neil Shapiro {
123340266059SGregory Neil Shapiro 	int len;
123440266059SGregory Neil Shapiro 	unsigned long old_options = 0;
123540266059SGregory Neil Shapiro 	time_t save_retrans = 0;
123640266059SGregory Neil Shapiro 	int save_retry = 0;
12375b0945b5SGregory Neil Shapiro 	DNS_REPLY_T *dr = NULL;
12386f9c8e5bSGregory Neil Shapiro 	querybuf reply_buf;
12396f9c8e5bSGregory Neil Shapiro 	unsigned char *reply;
12405b0945b5SGregory Neil Shapiro 	int (*resfunc) __P((const char *, int, int, u_char *, int));
12416f9c8e5bSGregory Neil Shapiro 
12425b0945b5SGregory Neil Shapiro #  define SMRBSIZE ((int) sizeof(reply_buf))
12436f9c8e5bSGregory Neil Shapiro #  ifndef IP_MAXPACKET
12446f9c8e5bSGregory Neil Shapiro #   define IP_MAXPACKET	65535
12456f9c8e5bSGregory Neil Shapiro #  endif
124640266059SGregory Neil Shapiro 
12475b0945b5SGregory Neil Shapiro 	resfunc = res_search;
12485b0945b5SGregory Neil Shapiro #  if DNSSEC_TEST
12495b0945b5SGregory Neil Shapiro 	if (tTd(8, 110))
12505b0945b5SGregory Neil Shapiro 		resfunc = tstdns_search;
12515b0945b5SGregory Neil Shapiro #  endif
12525b0945b5SGregory Neil Shapiro 
12535b0945b5SGregory Neil Shapiro 	old_options = _res.options;
12545b0945b5SGregory Neil Shapiro 	_res.options |= options;
12555b0945b5SGregory Neil Shapiro 	if (err != NULL)
12565b0945b5SGregory Neil Shapiro 		*err = 0;
12575b0945b5SGregory Neil Shapiro 	if (herr != NULL)
12585b0945b5SGregory Neil Shapiro 		*herr = 0;
125940266059SGregory Neil Shapiro 	if (tTd(8, 16))
126040266059SGregory Neil Shapiro 	{
126140266059SGregory Neil Shapiro 		_res.options |= RES_DEBUG;
12625b0945b5SGregory Neil Shapiro 		sm_dprintf("dns_lookup_int(%s, %d, %s, %x)\n", domain,
12635b0945b5SGregory Neil Shapiro 			   rr_class, dns_type_to_string(rr_type), options);
126440266059SGregory Neil Shapiro 	}
12655b0945b5SGregory Neil Shapiro #  if DNSSEC_TEST
12665b0945b5SGregory Neil Shapiro 	if (tTd(8, 15))
12675b0945b5SGregory Neil Shapiro 		sm_dprintf("NS=%s, port=%d\n",
12685b0945b5SGregory Neil Shapiro 			inet_ntoa(_res.nsaddr_list[0].sin_addr),
12695b0945b5SGregory Neil Shapiro 			ntohs(_res.nsaddr_list[0].sin_port));
12705b0945b5SGregory Neil Shapiro #  endif
127140266059SGregory Neil Shapiro 	if (retrans > 0)
127240266059SGregory Neil Shapiro 	{
127340266059SGregory Neil Shapiro 		save_retrans = _res.retrans;
127440266059SGregory Neil Shapiro 		_res.retrans = retrans;
127540266059SGregory Neil Shapiro 	}
127640266059SGregory Neil Shapiro 	if (retry > 0)
127740266059SGregory Neil Shapiro 	{
127840266059SGregory Neil Shapiro 		save_retry = _res.retry;
127940266059SGregory Neil Shapiro 		_res.retry = retry;
128040266059SGregory Neil Shapiro 	}
128140266059SGregory Neil Shapiro 	errno = 0;
128240266059SGregory Neil Shapiro 	SM_SET_H_ERRNO(0);
12836f9c8e5bSGregory Neil Shapiro 	reply = (unsigned char *)&reply_buf;
12845b0945b5SGregory Neil Shapiro 	len = (*resfunc)(domain, rr_class, rr_type, reply, SMRBSIZE);
12856f9c8e5bSGregory Neil Shapiro 	if (len >= SMRBSIZE)
12866f9c8e5bSGregory Neil Shapiro 	{
12876f9c8e5bSGregory Neil Shapiro 		if (len >= IP_MAXPACKET)
12886f9c8e5bSGregory Neil Shapiro 		{
12896f9c8e5bSGregory Neil Shapiro 			if (tTd(8, 4))
12906f9c8e5bSGregory Neil Shapiro 				sm_dprintf("dns_lookup: domain=%s, length=%d, default_size=%d, max=%d, status=response too long\n",
12915b0945b5SGregory Neil Shapiro 					   domain, len, SMRBSIZE, IP_MAXPACKET);
12926f9c8e5bSGregory Neil Shapiro 		}
12936f9c8e5bSGregory Neil Shapiro 		else
12946f9c8e5bSGregory Neil Shapiro 		{
12956f9c8e5bSGregory Neil Shapiro 			if (tTd(8, 6))
12966f9c8e5bSGregory Neil Shapiro 				sm_dprintf("dns_lookup: domain=%s, length=%d, default_size=%d, max=%d, status=response longer than default size, resizing\n",
12975b0945b5SGregory Neil Shapiro 					   domain, len, SMRBSIZE, IP_MAXPACKET);
12986f9c8e5bSGregory Neil Shapiro 			reply = (unsigned char *)sm_malloc(IP_MAXPACKET);
12996f9c8e5bSGregory Neil Shapiro 			if (reply == NULL)
13006f9c8e5bSGregory Neil Shapiro 				SM_SET_H_ERRNO(TRY_AGAIN);
13016f9c8e5bSGregory Neil Shapiro 			else
13025b0945b5SGregory Neil Shapiro 			{
13035b0945b5SGregory Neil Shapiro 				SM_SET_H_ERRNO(0);
13045b0945b5SGregory Neil Shapiro 				len = (*resfunc)(domain, rr_class, rr_type,
13056f9c8e5bSGregory Neil Shapiro 						 reply, IP_MAXPACKET);
13066f9c8e5bSGregory Neil Shapiro 			}
13076f9c8e5bSGregory Neil Shapiro 		}
13085b0945b5SGregory Neil Shapiro 	}
13095b0945b5SGregory Neil Shapiro 	_res.options = old_options;
13105b0945b5SGregory Neil Shapiro 	if (len < 0)
13115b0945b5SGregory Neil Shapiro 	{
13125b0945b5SGregory Neil Shapiro 		if (err != NULL)
13135b0945b5SGregory Neil Shapiro 			*err = errno;
13145b0945b5SGregory Neil Shapiro 		if (herr != NULL)
13155b0945b5SGregory Neil Shapiro 			*herr = h_errno;
131640266059SGregory Neil Shapiro 		if (tTd(8, 16))
131740266059SGregory Neil Shapiro 		{
13185b0945b5SGregory Neil Shapiro 			sm_dprintf("dns_lookup_int(%s, %d, %s, %x)=%d, errno=%d, h_errno=%d"
13195b0945b5SGregory Neil Shapiro #  if DNSSEC_TEST
13205b0945b5SGregory Neil Shapiro 				" (%s)"
13215b0945b5SGregory Neil Shapiro #  endif
13225b0945b5SGregory Neil Shapiro 				"\n",
13235b0945b5SGregory Neil Shapiro 				domain, rr_class, dns_type_to_string(rr_type),
13245b0945b5SGregory Neil Shapiro 				options, len, errno, h_errno
13255b0945b5SGregory Neil Shapiro #  if DNSSEC_TEST
13265b0945b5SGregory Neil Shapiro 				, herrno2txt(h_errno)
13275b0945b5SGregory Neil Shapiro #  endif
13285b0945b5SGregory Neil Shapiro 				);
13295b0945b5SGregory Neil Shapiro 		}
13305b0945b5SGregory Neil Shapiro 	}
13315b0945b5SGregory Neil Shapiro 	else if (tTd(8, 16))
13325b0945b5SGregory Neil Shapiro 	{
13335b0945b5SGregory Neil Shapiro 		sm_dprintf("dns_lookup_int(%s, %d, %s, %x)=%d\n",
13345b0945b5SGregory Neil Shapiro 			domain, rr_class, dns_type_to_string(rr_type),
13355b0945b5SGregory Neil Shapiro 			options, len);
133640266059SGregory Neil Shapiro 	}
13376f9c8e5bSGregory Neil Shapiro 	if (len >= 0 && len < IP_MAXPACKET && reply != NULL)
13385b0945b5SGregory Neil Shapiro 		dr = parse_dns_reply(reply, len, flags);
13396f9c8e5bSGregory Neil Shapiro 	if (reply != (unsigned char *)&reply_buf && reply != NULL)
13406f9c8e5bSGregory Neil Shapiro 	{
13416f9c8e5bSGregory Neil Shapiro 		sm_free(reply);
13426f9c8e5bSGregory Neil Shapiro 		reply = NULL;
13436f9c8e5bSGregory Neil Shapiro 	}
134440266059SGregory Neil Shapiro 	if (retrans > 0)
134540266059SGregory Neil Shapiro 		_res.retrans = save_retrans;
134640266059SGregory Neil Shapiro 	if (retry > 0)
134740266059SGregory Neil Shapiro 		_res.retry = save_retry;
13485b0945b5SGregory Neil Shapiro 	return dr;
134940266059SGregory Neil Shapiro }
135040266059SGregory Neil Shapiro 
13515b0945b5SGregory Neil Shapiro /*
13525b0945b5SGregory Neil Shapiro **  DNS_LOOKUP_MAP -- perform DNS map lookup
13535b0945b5SGregory Neil Shapiro **
13545b0945b5SGregory Neil Shapiro **	Parameters:
13555b0945b5SGregory Neil Shapiro **		domain -- name to look up
13565b0945b5SGregory Neil Shapiro **		rr_class -- resource record class
13575b0945b5SGregory Neil Shapiro **		rr_type -- resource record type
13585b0945b5SGregory Neil Shapiro **		retrans -- retransmission timeout
13595b0945b5SGregory Neil Shapiro **		retry -- number of retries
13605b0945b5SGregory Neil Shapiro **		options -- DNS resolver options
13615b0945b5SGregory Neil Shapiro **
13625b0945b5SGregory Neil Shapiro **	Returns:
13635b0945b5SGregory Neil Shapiro **		result of lookup if succeeded.
13645b0945b5SGregory Neil Shapiro **		NULL otherwise.
13655b0945b5SGregory Neil Shapiro */
13665b0945b5SGregory Neil Shapiro 
136740266059SGregory Neil Shapiro DNS_REPLY_T *
dns_lookup_map(domain,rr_class,rr_type,retrans,retry,options)13685b0945b5SGregory Neil Shapiro dns_lookup_map(domain, rr_class, rr_type, retrans, retry, options)
136940266059SGregory Neil Shapiro 	const char *domain;
13705b0945b5SGregory Neil Shapiro 	int rr_class;
13715b0945b5SGregory Neil Shapiro 	int rr_type;
137240266059SGregory Neil Shapiro 	time_t retrans;
137340266059SGregory Neil Shapiro 	int retry;
13745b0945b5SGregory Neil Shapiro 	unsigned int options;
137540266059SGregory Neil Shapiro {
13765b0945b5SGregory Neil Shapiro 	return dns_lookup_int(domain, rr_class, rr_type, retrans, retry,
13775b0945b5SGregory Neil Shapiro 			options, RR_AS_TEXT, NULL, NULL);
13785b0945b5SGregory Neil Shapiro }
137940266059SGregory Neil Shapiro 
13805b0945b5SGregory Neil Shapiro #  if DANE
13815b0945b5SGregory Neil Shapiro /*
13825b0945b5SGregory Neil Shapiro **  DNS2HE -- convert DNS_REPLY_T list to hostent struct
13835b0945b5SGregory Neil Shapiro **
13845b0945b5SGregory Neil Shapiro **	Parameters:
13855b0945b5SGregory Neil Shapiro **		dr -- DNS lookup result
13865b0945b5SGregory Neil Shapiro **		family -- address family
13875b0945b5SGregory Neil Shapiro **
13885b0945b5SGregory Neil Shapiro **	Returns:
13895b0945b5SGregory Neil Shapiro **		hostent struct if succeeded.
13905b0945b5SGregory Neil Shapiro **		NULL otherwise.
13915b0945b5SGregory Neil Shapiro **
13925b0945b5SGregory Neil Shapiro **	Note:
13935b0945b5SGregory Neil Shapiro **		this returns a pointer to a static struct!
13945b0945b5SGregory Neil Shapiro */
13955b0945b5SGregory Neil Shapiro 
13965b0945b5SGregory Neil Shapiro struct hostent *
dns2he(dr,family)13975b0945b5SGregory Neil Shapiro dns2he(dr, family)
13985b0945b5SGregory Neil Shapiro 	DNS_REPLY_T *dr;
13995b0945b5SGregory Neil Shapiro 	int family;
140040266059SGregory Neil Shapiro {
14015b0945b5SGregory Neil Shapiro #   define SM_MAX_ADDRS	256
14025b0945b5SGregory Neil Shapiro 	static struct hostent he;
14035b0945b5SGregory Neil Shapiro 	static char *he_aliases[1];
14045b0945b5SGregory Neil Shapiro 	static char *he_addr_list[SM_MAX_ADDRS];
14055b0945b5SGregory Neil Shapiro #   ifdef IN6ADDRSZ
14065b0945b5SGregory Neil Shapiro #    define IN_ADDRSZ IN6ADDRSZ
14075b0945b5SGregory Neil Shapiro #   else
14085b0945b5SGregory Neil Shapiro #    define IN_ADDRSZ INADDRSZ
14095b0945b5SGregory Neil Shapiro #   endif
14105b0945b5SGregory Neil Shapiro 	static char he_addrs[SM_MAX_ADDRS * IN_ADDRSZ];
14112fb4f839SGregory Neil Shapiro 	static char he_name[MAXNAME_I];
14125b0945b5SGregory Neil Shapiro 	static bool he_init = false;
14135b0945b5SGregory Neil Shapiro 	struct hostent *h;
14145b0945b5SGregory Neil Shapiro 	int i;
14155b0945b5SGregory Neil Shapiro 	size_t sz;
14165b0945b5SGregory Neil Shapiro #   if NETINET6 && DNSSEC_TEST
14175b0945b5SGregory Neil Shapiro 	struct in6_addr ia6;
14185b0945b5SGregory Neil Shapiro 	char buf6[INET6_ADDRSTRLEN];
14195b0945b5SGregory Neil Shapiro #   endif
14205b0945b5SGregory Neil Shapiro 	RESOURCE_RECORD_T *rr;
14215b0945b5SGregory Neil Shapiro 
14225b0945b5SGregory Neil Shapiro 	if (dr == NULL)
142340266059SGregory Neil Shapiro 		return NULL;
14245b0945b5SGregory Neil Shapiro 
14255b0945b5SGregory Neil Shapiro 	h = &he;
14265b0945b5SGregory Neil Shapiro 	if (!he_init)
14275b0945b5SGregory Neil Shapiro 	{
14285b0945b5SGregory Neil Shapiro 		he_aliases[0] = NULL;
14295b0945b5SGregory Neil Shapiro 		he.h_aliases = he_aliases;
14305b0945b5SGregory Neil Shapiro 		he.h_addr_list = he_addr_list;
14315b0945b5SGregory Neil Shapiro 		he.h_name = he_name;
14325b0945b5SGregory Neil Shapiro 		he_init = true;
143340266059SGregory Neil Shapiro 	}
14345b0945b5SGregory Neil Shapiro 	h->h_addrtype = family;
14355b0945b5SGregory Neil Shapiro 
14365b0945b5SGregory Neil Shapiro 	if (tTd(8, 17))
14375b0945b5SGregory Neil Shapiro 		sm_dprintf("dns2he: ad=%d\n", dr->dns_r_h.ad);
14385b0945b5SGregory Neil Shapiro 
14395b0945b5SGregory Neil Shapiro 	/* do we want/need to copy the name? */
14405b0945b5SGregory Neil Shapiro 	rr = dr->dns_r_head;
14415b0945b5SGregory Neil Shapiro 	if (rr != NULL && rr->rr_domain != NULL)
14425b0945b5SGregory Neil Shapiro 		sm_strlcpy(h->h_name, rr->rr_domain, sizeof(he_name));
14435b0945b5SGregory Neil Shapiro 	else
14445b0945b5SGregory Neil Shapiro 		h->h_name[0] = '\0';
14455b0945b5SGregory Neil Shapiro 
14465b0945b5SGregory Neil Shapiro 	sz = 0;
14475b0945b5SGregory Neil Shapiro #   if NETINET
14485b0945b5SGregory Neil Shapiro 	if (family == AF_INET)
14495b0945b5SGregory Neil Shapiro 		sz = INADDRSZ;
14505b0945b5SGregory Neil Shapiro #   endif
14515b0945b5SGregory Neil Shapiro #   if NETINET6
14525b0945b5SGregory Neil Shapiro 	if (family == AF_INET6)
14535b0945b5SGregory Neil Shapiro 		sz = IN6ADDRSZ;
14545b0945b5SGregory Neil Shapiro #   endif
14555b0945b5SGregory Neil Shapiro 	if (sz == 0)
14565b0945b5SGregory Neil Shapiro 		return NULL;
14575b0945b5SGregory Neil Shapiro 	h->h_length = sz;
14585b0945b5SGregory Neil Shapiro 
14595b0945b5SGregory Neil Shapiro 	for (rr = dr->dns_r_head, i = 0; rr != NULL && i < SM_MAX_ADDRS - 1;
14605b0945b5SGregory Neil Shapiro 	     rr = rr->rr_next)
14615b0945b5SGregory Neil Shapiro 	{
14625b0945b5SGregory Neil Shapiro 		h->h_addr_list[i] = he_addrs + i * h->h_length;
14635b0945b5SGregory Neil Shapiro 		switch (rr->rr_type)
14645b0945b5SGregory Neil Shapiro 		{
14655b0945b5SGregory Neil Shapiro #   if NETINET
14665b0945b5SGregory Neil Shapiro 		  case T_A:
14675b0945b5SGregory Neil Shapiro 			if (family != AF_INET)
14685b0945b5SGregory Neil Shapiro 				continue;
14695b0945b5SGregory Neil Shapiro 			memmove(h->h_addr_list[i], rr->rr_u.rr_a, INADDRSZ);
14705b0945b5SGregory Neil Shapiro 			++i;
14715b0945b5SGregory Neil Shapiro 			break;
14725b0945b5SGregory Neil Shapiro #   endif /* NETINET */
14735b0945b5SGregory Neil Shapiro #   if NETINET6
14745b0945b5SGregory Neil Shapiro 		  case T_AAAA:
14755b0945b5SGregory Neil Shapiro 			if (family != AF_INET6)
14765b0945b5SGregory Neil Shapiro 				continue;
14775b0945b5SGregory Neil Shapiro 			memmove(h->h_addr_list[i], rr->rr_u.rr_aaaa, IN6ADDRSZ);
14785b0945b5SGregory Neil Shapiro 			++i;
14795b0945b5SGregory Neil Shapiro 			break;
14805b0945b5SGregory Neil Shapiro #   endif /* NETINET6 */
14815b0945b5SGregory Neil Shapiro 		  case T_CNAME:
14825b0945b5SGregory Neil Shapiro #   if DNSSEC_TEST
14835b0945b5SGregory Neil Shapiro 			if (tTd(8, 16))
14845b0945b5SGregory Neil Shapiro 				sm_dprintf("dns2he: cname: %s ttl=%d\n",
14855b0945b5SGregory Neil Shapiro 					rr->rr_u.rr_txt, rr->rr_ttl);
14865b0945b5SGregory Neil Shapiro #   endif
14875b0945b5SGregory Neil Shapiro 			break;
14885b0945b5SGregory Neil Shapiro 		  case T_MX:
14895b0945b5SGregory Neil Shapiro #   if DNSSEC_TEST
14905b0945b5SGregory Neil Shapiro 			if (tTd(8, 16))
14915b0945b5SGregory Neil Shapiro 				sm_dprintf("dns2he: mx: %d %s ttl=%d\n",
14925b0945b5SGregory Neil Shapiro 					rr->rr_u.rr_mx->mx_r_preference,
14935b0945b5SGregory Neil Shapiro 					rr->rr_u.rr_mx->mx_r_domain,
14945b0945b5SGregory Neil Shapiro 					rr->rr_ttl);
14955b0945b5SGregory Neil Shapiro #   endif
14965b0945b5SGregory Neil Shapiro 			break;
14975b0945b5SGregory Neil Shapiro 
14985b0945b5SGregory Neil Shapiro #   if defined(T_TLSA)
14995b0945b5SGregory Neil Shapiro 		  case T_TLSA:
15005b0945b5SGregory Neil Shapiro #    if DNSSEC_TEST
15015b0945b5SGregory Neil Shapiro 			if (tTd(8, 16))
15025b0945b5SGregory Neil Shapiro 			{
15035b0945b5SGregory Neil Shapiro 				char *tlsa;
15045b0945b5SGregory Neil Shapiro 				int len;
15055b0945b5SGregory Neil Shapiro 
15065b0945b5SGregory Neil Shapiro 				len = bin2hex(&tlsa, rr->rr_u.rr_data,
15075b0945b5SGregory Neil Shapiro 						rr->rr_size, 4);
15085b0945b5SGregory Neil Shapiro 				if (len > 0)
15095b0945b5SGregory Neil Shapiro 					sm_dprintf("dns2he: tlsa: %s ttl=%d\n",
15105b0945b5SGregory Neil Shapiro 						tlsa, rr->rr_ttl);
151140266059SGregory Neil Shapiro 			}
15125b0945b5SGregory Neil Shapiro #    endif
15135b0945b5SGregory Neil Shapiro 			break;
15145b0945b5SGregory Neil Shapiro #   endif /* T_TLSA */
15155b0945b5SGregory Neil Shapiro 		}
15165b0945b5SGregory Neil Shapiro 	}
15175b0945b5SGregory Neil Shapiro 
15185b0945b5SGregory Neil Shapiro 	/* complain if list is too long! */
15195b0945b5SGregory Neil Shapiro 	SM_ASSERT(i < SM_MAX_ADDRS);
15205b0945b5SGregory Neil Shapiro 	h->h_addr_list[i] = NULL;
15215b0945b5SGregory Neil Shapiro 
15225b0945b5SGregory Neil Shapiro #   if DNSSEC_TEST
15235b0945b5SGregory Neil Shapiro 	if (tTd(8, 16))
15245b0945b5SGregory Neil Shapiro 	{
15252fb4f839SGregory Neil Shapiro 		struct in_addr ia;
15262fb4f839SGregory Neil Shapiro 
15275b0945b5SGregory Neil Shapiro 		for (i = 0; h->h_addr_list[i] != NULL && i < SM_MAX_ADDRS; i++)
15285b0945b5SGregory Neil Shapiro 		{
15295b0945b5SGregory Neil Shapiro 			char *addr;
15305b0945b5SGregory Neil Shapiro 
15315b0945b5SGregory Neil Shapiro 			addr = NULL;
15325b0945b5SGregory Neil Shapiro #    if NETINET6
15335b0945b5SGregory Neil Shapiro 			if (h->h_addrtype == AF_INET6)
15345b0945b5SGregory Neil Shapiro 			{
15355b0945b5SGregory Neil Shapiro 				memmove(&ia6, h->h_addr_list[i], IN6ADDRSZ);
15365b0945b5SGregory Neil Shapiro 				addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
15375b0945b5SGregory Neil Shapiro 			}
15385b0945b5SGregory Neil Shapiro 			else
15395b0945b5SGregory Neil Shapiro #    endif /* NETINET6 */
15405b0945b5SGregory Neil Shapiro 			/* "else" in #if code above */
15415b0945b5SGregory Neil Shapiro 			{
15425b0945b5SGregory Neil Shapiro 				memmove(&ia, h->h_addr_list[i], INADDRSZ);
15435b0945b5SGregory Neil Shapiro 				addr = (char *) inet_ntoa(ia);
15445b0945b5SGregory Neil Shapiro 			}
15455b0945b5SGregory Neil Shapiro 			if (addr != NULL)
15465b0945b5SGregory Neil Shapiro 				sm_dprintf("dns2he: addr[%d]: %s\n", i, addr);
15475b0945b5SGregory Neil Shapiro 		}
15485b0945b5SGregory Neil Shapiro 	}
15495b0945b5SGregory Neil Shapiro #   endif /* DNSSEC_TEST */
15505b0945b5SGregory Neil Shapiro 	return h;
15515b0945b5SGregory Neil Shapiro }
15525b0945b5SGregory Neil Shapiro #  endif /* DANE */
15535b0945b5SGregory Neil Shapiro # endif /* DNSMAP || DANE */
1554*d39bd2c1SGregory Neil Shapiro 
1555*d39bd2c1SGregory Neil Shapiro # if DNSSEC_TEST || _FFR_NAMESERVER
1556*d39bd2c1SGregory Neil Shapiro /*
1557*d39bd2c1SGregory Neil Shapiro **  DNS_ADDNS -- add one NS in resolver context
1558*d39bd2c1SGregory Neil Shapiro **
1559*d39bd2c1SGregory Neil Shapiro **	Parameters:
1560*d39bd2c1SGregory Neil Shapiro **		ns -- (IPv4 address of) nameserver
1561*d39bd2c1SGregory Neil Shapiro **		port -- nameserver port (host order)
1562*d39bd2c1SGregory Neil Shapiro **
1563*d39bd2c1SGregory Neil Shapiro **	Returns:
1564*d39bd2c1SGregory Neil Shapiro **		None.
1565*d39bd2c1SGregory Neil Shapiro */
1566*d39bd2c1SGregory Neil Shapiro 
1567*d39bd2c1SGregory Neil Shapiro static void dns_addns __P((struct in_addr *, unsigned int));
1568*d39bd2c1SGregory Neil Shapiro static int nsidx = 0;
1569*d39bd2c1SGregory Neil Shapiro #ifndef MAXNS
1570*d39bd2c1SGregory Neil Shapiro # define MAXNS	3
1571*d39bd2c1SGregory Neil Shapiro #endif
1572*d39bd2c1SGregory Neil Shapiro static void
dns_addns(ns,port)1573*d39bd2c1SGregory Neil Shapiro dns_addns(ns, port)
1574*d39bd2c1SGregory Neil Shapiro 	struct in_addr *ns;
1575*d39bd2c1SGregory Neil Shapiro 	unsigned int port;
1576*d39bd2c1SGregory Neil Shapiro {
1577*d39bd2c1SGregory Neil Shapiro 	if (nsidx >= MAXNS)
1578*d39bd2c1SGregory Neil Shapiro 		syserr("too many NameServers defined (%d max)", MAXNS);
1579*d39bd2c1SGregory Neil Shapiro 	_res.nsaddr_list[nsidx].sin_family = AF_INET;
1580*d39bd2c1SGregory Neil Shapiro 	_res.nsaddr_list[nsidx].sin_addr = *ns;
1581*d39bd2c1SGregory Neil Shapiro 	if (port != 0)
1582*d39bd2c1SGregory Neil Shapiro 		_res.nsaddr_list[nsidx].sin_port = htons(port);
1583*d39bd2c1SGregory Neil Shapiro 	_res.nscount = ++nsidx;
1584*d39bd2c1SGregory Neil Shapiro 	if (tTd(8, 61))
1585*d39bd2c1SGregory Neil Shapiro 		sm_dprintf("dns_addns: nsidx=%d, ns=%s:%u\n",
1586*d39bd2c1SGregory Neil Shapiro 			   nsidx - 1, inet_ntoa(*ns), port);
1587*d39bd2c1SGregory Neil Shapiro }
1588*d39bd2c1SGregory Neil Shapiro 
1589*d39bd2c1SGregory Neil Shapiro /*
1590*d39bd2c1SGregory Neil Shapiro **  NSPORTIP -- parse port@IPv4 and set NS accordingly
1591*d39bd2c1SGregory Neil Shapiro **
1592*d39bd2c1SGregory Neil Shapiro **	Parameters:
1593*d39bd2c1SGregory Neil Shapiro **		p -- port@IPv4
1594*d39bd2c1SGregory Neil Shapiro **
1595*d39bd2c1SGregory Neil Shapiro **	Returns:
1596*d39bd2c1SGregory Neil Shapiro **		<0: error
1597*d39bd2c1SGregory Neil Shapiro **		>=0: ok
1598*d39bd2c1SGregory Neil Shapiro **
1599*d39bd2c1SGregory Neil Shapiro **	Side Effects:
1600*d39bd2c1SGregory Neil Shapiro **		sets NS for DNS lookups
1601*d39bd2c1SGregory Neil Shapiro */
1602*d39bd2c1SGregory Neil Shapiro 
1603*d39bd2c1SGregory Neil Shapiro /*
1604*d39bd2c1SGregory Neil Shapiro **  There should be a generic function for this...
1605*d39bd2c1SGregory Neil Shapiro **  milter_open(), socket_map_open(), others?
1606*d39bd2c1SGregory Neil Shapiro */
1607*d39bd2c1SGregory Neil Shapiro 
1608*d39bd2c1SGregory Neil Shapiro int
nsportip(p)1609*d39bd2c1SGregory Neil Shapiro nsportip(p)
1610*d39bd2c1SGregory Neil Shapiro 	char *p;
1611*d39bd2c1SGregory Neil Shapiro {
1612*d39bd2c1SGregory Neil Shapiro 	char *h;
1613*d39bd2c1SGregory Neil Shapiro 	int r;
1614*d39bd2c1SGregory Neil Shapiro 	unsigned short port;
1615*d39bd2c1SGregory Neil Shapiro 	struct in_addr nsip;
1616*d39bd2c1SGregory Neil Shapiro 
1617*d39bd2c1SGregory Neil Shapiro 	if (SM_IS_EMPTY(p))
1618*d39bd2c1SGregory Neil Shapiro 		return -1;
1619*d39bd2c1SGregory Neil Shapiro 
1620*d39bd2c1SGregory Neil Shapiro 	port = 0;
1621*d39bd2c1SGregory Neil Shapiro 	while (SM_ISSPACE(*p))
1622*d39bd2c1SGregory Neil Shapiro 		p++;
1623*d39bd2c1SGregory Neil Shapiro 	if (*p == '\0')
1624*d39bd2c1SGregory Neil Shapiro 		return -1;
1625*d39bd2c1SGregory Neil Shapiro 	h = strchr(p, '@');
1626*d39bd2c1SGregory Neil Shapiro 	if (h != NULL)
1627*d39bd2c1SGregory Neil Shapiro 	{
1628*d39bd2c1SGregory Neil Shapiro 		*h = '\0';
1629*d39bd2c1SGregory Neil Shapiro 		if (isascii(*p) && isdigit(*p))
1630*d39bd2c1SGregory Neil Shapiro 			port = atoi(p);
1631*d39bd2c1SGregory Neil Shapiro 		*h = '@';
1632*d39bd2c1SGregory Neil Shapiro 		p = h + 1;
1633*d39bd2c1SGregory Neil Shapiro 	}
1634*d39bd2c1SGregory Neil Shapiro 	h = strchr(p, ' ');
1635*d39bd2c1SGregory Neil Shapiro 	if (h != NULL)
1636*d39bd2c1SGregory Neil Shapiro 		*h = '\0';
1637*d39bd2c1SGregory Neil Shapiro 	r = inet_pton(AF_INET, p, &nsip);
1638*d39bd2c1SGregory Neil Shapiro 	if (r > 0)
1639*d39bd2c1SGregory Neil Shapiro 	{
1640*d39bd2c1SGregory Neil Shapiro 		if ((_res.options & RES_INIT) == 0)
1641*d39bd2c1SGregory Neil Shapiro 			(void) res_init();
1642*d39bd2c1SGregory Neil Shapiro 		dns_addns(&nsip, port);
1643*d39bd2c1SGregory Neil Shapiro 	}
1644*d39bd2c1SGregory Neil Shapiro 	if (h != NULL)
1645*d39bd2c1SGregory Neil Shapiro 		*h = ' ';
1646*d39bd2c1SGregory Neil Shapiro 	return r > 0 ? 0 : -1;
1647*d39bd2c1SGregory Neil Shapiro }
1648*d39bd2c1SGregory Neil Shapiro # endif /* DNSSEC_TEST || _FFR_NAMESERVER */
1649*d39bd2c1SGregory Neil Shapiro #endif /* NAMED_BIND */
1650