/*
 * Copyright (c) 2002-2004 Sendmail, Inc. and its suppliers.
 *      All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: dnsres.c,v 1.24 2006/12/28 03:31:40 ca Exp $")
#include "sm/ctype.h"
#include "sm/dns.h"
#include "sm/dns-int.h"

/*
**  DNS_RESE_NEW -- create a new DNS result entry and fill in data
**
**	Parameters:
**		rrname -- name of query
**		type -- DNS type
**		ttl -- TTL
**		pref -- preference
**		weight -- weight (result of mxrand())
**		reshost -- hostname
**		n -- len of reshost
**		ipv4 -- IPv4 address
**		pdns_rese -- new DNS result entry (output)
**
**	Returns:
**		usual sm_error code
*/

sm_ret_T
dns_rese_new(const uchar *rrname, size_t l, dns_type_T type, uint ttl, ushort pref, ushort weight, const uchar *reshost, size_t n, ipv4_T ipv4, dns_rese_P *pdns_rese)
{
	dns_rese_P dns_rese;
	sm_ret_T ret;

	SM_REQUIRE(pdns_rese != NULL);
	ret = sm_error_temp(SM_EM_DNS, ENOMEM);
	dns_rese = (dns_rese_P) sm_zalloc(sizeof(*dns_rese));
	if (NULL == dns_rese)
		return ret;
	if (rrname != NULL) {
		dns_rese->dnsrese_name = sm_cstr_scpyn0(rrname, l);
		if (NULL == dns_rese->dnsrese_name)
			goto error;
	}
	dns_rese->dnsrese_ttl = ttl;
	dns_rese->dnsrese_type = type;
	switch (type) {
	  case T_MX:
		dns_rese->dnsrese_val.dnsresu_name = sm_cstr_scpyn0(reshost, n);
		if (dns_rese->dnsrese_val.dnsresu_name == NULL)
			goto error;
		dns_rese->dnsrese_pref = pref;
		dns_rese->dnsrese_weight = weight;
		break;

	  case T_A:
		dns_rese->dnsrese_val.dnsresu_a = ipv4;
		break;

	  case T_PTR:
		dns_rese->dnsrese_val.dnsresu_name = sm_cstr_scpyn0(reshost, n);
		if (dns_rese->dnsrese_val.dnsresu_name == NULL)
			goto error;
		break;

	  case T_CNAME:
		dns_rese->dnsrese_val.dnsresu_name = sm_cstr_scpyn0(reshost, n);
		if (dns_rese->dnsrese_val.dnsresu_name == NULL)
			goto error;
		break;

	  default:
		ret = sm_error_perm(SM_EM_DNS, EINVAL);
		break;
	}
	*pdns_rese = dns_rese;
	return SM_SUCCESS;

  error:
	if (dns_rese != NULL) {
		SM_CSTR_FREE(dns_rese->dnsrese_name);
		sm_free_size(dns_rese, sizeof(*dns_rese));
	}
	return ret;
}

/*
**  DNS_RESE_FREE -- free a DNS result entry
**
**	Parameters:
**		dns_rese -- DNS result entry
**
**	Returns:
**		usual sm_error code
*/

sm_ret_T
dns_rese_free(dns_rese_P dns_rese)
{
	if (NULL == dns_rese)
		return SM_SUCCESS;
	SM_CSTR_FREE(dns_rese->dnsrese_name);
	if (T_MX == dns_rese->dnsrese_type ||
	    T_CNAME == dns_rese->dnsrese_type ||
	    T_PTR == dns_rese->dnsrese_type)
		SM_CSTR_FREE(dns_rese->dnsrese_val.dnsresu_name);
	sm_free_size(dns_rese, sizeof(*dns_rese));
	return SM_SUCCESS;
}

/*
**  DNS_RES_NEW -- create a new DNS result structure
**
**	Parameters:
**		maxentries -- maximum number of DNS result records to add
**		pdns_res -- new DNS result struct (output)
**
**	Returns:
**		usual sm_error code
*/

sm_ret_T
dns_res_new(uint maxentries, dns_res_P *pdns_res)
{
	dns_res_P dns_res;

	SM_REQUIRE(pdns_res != NULL);
	/* pdns_res = NULL; */
	dns_res = (dns_res_P) sm_zalloc(sizeof(*dns_res));
	if (NULL == dns_res)
		return sm_error_temp(SM_EM_DNS, ENOMEM);
	DRESL_INIT(dns_res);
	dns_res->dnsres_maxentries = (maxentries == 0) ? MAXRESHOSTS
							: maxentries;
	*pdns_res = dns_res;
	return SM_SUCCESS;
}

/*
**  DNS_RESL_FREE -- free DNS result list
**
**	Parameters:
**		dns_res -- DNS result header
**
**	Returns:
**		usual sm_error code (currently: always SM_SUCCESS)
*/

sm_ret_T
dns_resl_free(dns_res_P dns_res)
{
	dns_rese_P dns_rese, dns_rese_next;

	if (NULL == dns_res)
		return SM_SUCCESS;

	/* free list... */
	for (dns_rese = DRESL_FIRST(dns_res);
	     dns_rese != DRESL_END(dns_res);
	     dns_rese = dns_rese_next)
	{
		dns_rese_next = DRESL_NEXT(dns_rese);
		dns_rese_free(dns_rese);
	}
	DRESL_INIT(dns_res);
	return SM_SUCCESS;
}

/*
**  DNS_RES_FREE -- free an entire DNS result struct
**
**	Parameters:
**		dns_res -- DNS result entry
**
**	Returns:
**		usual sm_error code (currently: always SM_SUCCESS)
*/

sm_ret_T
dns_res_free(dns_res_P dns_res)
{
	sm_ret_T ret;

	if (NULL == dns_res)
		return SM_SUCCESS;
	ret = dns_resl_free(dns_res);
	if (sm_is_err(ret))
		return ret;
	sm_free_size(dns_res, sizeof(*dns_res));
	return SM_SUCCESS;
}


syntax highlighted by Code2HTML, v. 0.9.1