/*
 * 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.
 *
 *	$Id: dns-int.h,v 1.32 2006/10/05 04:27:35 ca Exp $
 */

#ifndef SM_DNS_INT_H
#define SM_DNS_INT_H 1

/* Note: this is also used by smar/ to access dns_res */

#include "sm/generic.h"
#include "sm/types.h"
#include "sm/cstr.h"
#include "sm/queue.h"
#include "sm/str.h"
#include "sm/cstr.h"
#include "sm/time.h"
#include "sm/net.h"
#include "sm/nameser.h"
#include <resolv.h>
#include "sm/uio.h"	/* for writev() in sndrcv.c */
#include "sm/pthread.h"

#ifndef MTA_LIBDNS_DEBUG
# define MTA_LIBDNS_DEBUG	0
#endif

#if MTA_LIBDNS_DEBUG
# define MTA_LIBDNS_DBG_DPRINTF(x)	sm_io_fprintf x
#else
# define MTA_LIBDNS_DBG_DPRINTF(x)
#endif

TAILQ_HEAD(dns_mxl_S, dns_mxe_S);
TAILQ_HEAD(dns_resl_S, dns_rese_S);

#if 0
// /*
// **  DNS resolver context.
// **	Not really used (yet).
// */
// 
// struct dns_rslv_ctx_S
// {
// 	uint	dnsrslv_flags;
// };
#endif /* 0 */

#if 0
// typedef struct dns_header_S	dns_header_T, *dns_header_P;
// typedef struct dns_rr_S		dns_rr_T, *dns_rr_P;
// 
// struct dns_header_S
// {
// 	dns_type_T	dnsh_type;	/* T_A, T_CNAME, etc. */
// 	ushort		dnsh_class;	/* C_IN, etc. */
// 	uint		dnsh_ttl;	/* always */
// 	uint		dnsh_length;	/* record length */
// };
// 
// struct dns_rr_S
// {
// 	sm_cstr_P	 dnsrr_query;	/* query */
// 	dns_type_T	 dnsrr_type;	/* T_A, T_CNAME, etc. */
// 	ushort		 dnsrr_class;	/* C_IN, etc. */
// 	uint		 dnsrr_ttl;	/* always */
// 	ushort		 dnsrr_pref;	/* T_MX only */
// };
#endif /* 0 */

/*
**  DNS request context.
**	This should be internal to the system, since the dnsreq_link
**	is something that is required by the dns_mgr, but not by the
**	application. Hence the application should pass those elements
**	directly as parameters to a dns_req_new() function.
*/

struct dns_req_S
{
	sm_cstr_P	 dnsreq_query;	/* the query itself */
	time_T		 dnsreq_endt;	/* start time + timeout */
	ushort		 dnsreq_tries;	/* retries */
	dns_type_T	 dnsreq_type;	/* query type */
	uint16_t	 dnsreq_id;	/* dns request id */
	ushort		 dnsreq_flags;	/* currently: is in request list? */
	ushort		 dnsreq_idx;	/* number of DNS task */
	sm_str_P	 dnsreq_key;	/* key for hash table: query + type */
	dns_callback_F	*dnsreq_fct;	/* callback into application */
	void		*dnsreq_ctx;	/* context for application callback */
	TAILQ_ENTRY(dns_req_S)	dnsreq_link;	/* next entry */
#if DNS_STATISTICS
	timeval_T	 dnsreq_startt;	/* start time */
#endif
};

/* flags: in which list is the request stored: none, incoming, wait? */
#define DNSREQ_FL_NONE		0x0000u
#define DNSREQ_FL_IN_INC	0x0001u
#define DNSREQ_FL_IN_WAIT	0x0002u

#define DNSREQ_IS_INANYLIST(dns_req)	((dns_req)->dnsreq_flags != 0)
#define DNSREQ_IS_ININCLIST(dns_req)	((dns_req)->dnsreq_flags == DNSREQ_FL_IN_INC)
#define DNSREQ_IS_INWAITLIST(dns_req)	((dns_req)->dnsreq_flags == DNSREQ_FL_IN_WAIT)
#define DNSREQ_SET_INLIST(dns_req, list)	(dns_req)->dnsreq_flags = (list)
#define DNSREQ_CLR_INLIST(dns_req)	(dns_req)->dnsreq_flags = 0

#define DNSIRQL_INIT(dns_mgr_ctx)	TAILQ_INIT(&((dns_mgr_ctx)->dnsmgr_increq_hd))
#define DNSIRQL_FIRST(dns_mgr_ctx)	TAILQ_FIRST(&((dns_mgr_ctx)->dnsmgr_increq_hd))
#define DNSIRQL_LAST(dns_mgr_ctx)	TAILQ_LAST(&((dns_mgr_ctx)->dnsmgr_increq_hd), dns_rql_S)
#define DNSIRQL_EMPTY(dns_mgr_ctx)	TAILQ_EMPTY(&((dns_mgr_ctx)->dnsmgr_increq_hd))
#define DNSIRQL_END(dns_mgr_ctx)	TAILQ_END(&((dns_mgr_ctx)->dnsmgr_increq_hd))
#define DNSIRQL_NEXT(dns_increq)	TAILQ_NEXT(dns_increq, dnsreq_link)
#define DNSIRQL_PREV(dns_increq)	TAILQ_PREV(dns_increq, dns_rql_S, dnsreq_link)
#define DNSIRQL_INSERT_TAIL(dns_mgr_ctx, dns_increq) TAILQ_INSERT_TAIL(&((dns_mgr_ctx)->dnsmgr_increq_hd), dns_increq, dnsreq_link)
#define DNSIRQL_REMOVE(dns_mgr_ctx, dns_increq)	TAILQ_REMOVE(&((dns_mgr_ctx)->dnsmgr_increq_hd), dns_increq, dnsreq_link)

#define DNSWRQL_INIT(dns_mgr_ctx)	TAILQ_INIT(&((dns_mgr_ctx)->dnsmgr_waitreq_hd))
#define DNSWRQL_FIRST(dns_mgr_ctx)	TAILQ_FIRST(&((dns_mgr_ctx)->dnsmgr_waitreq_hd))
#define DNSWRQL_LAST(dns_mgr_ctx)	TAILQ_LAST(&((dns_mgr_ctx)->dnsmgr_waitreq_hd), dns_rql_S)
#define DNSWRQL_EMPTY(dns_mgr_ctx)	TAILQ_EMPTY(&((dns_mgr_ctx)->dnsmgr_waitreq_hd))
#define DNSWRQL_END(dns_mgr_ctx)	TAILQ_END(&((dns_mgr_ctx)->dnsmgr_waitreq_hd))
#define DNSWRQL_NEXT(dns_waitreq)	TAILQ_NEXT(dns_waitreq, dnsreq_link)
#define DNSWRQL_PREV(dns_waitreq)	TAILQ_PREV(dns_waitreq, dns_rql_S, dnsreq_link)
#define DNSWRQL_INSERT_TAIL(dns_mgr_ctx, dns_waitreq) TAILQ_INSERT_TAIL(&((dns_mgr_ctx)->dnsmgr_waitreq_hd), dns_waitreq, dnsreq_link)
#define DNSWRQL_INSERT_BEFORE(dns_mgr_ctx, dns_waitreq, dns_waitreqnew) TAILQ_INSERT_BEFORE(dns_waitreq, dns_waitreqnew, dnsreq_link)
#define DNSWRQL_INSERT_AFTER(dns_mgr_ctx, dns_waitreq, dns_waitreqnew) TAILQ_INSERT_AFTER(&((dns_mgr_ctx)->dnsmgr_waitreq_hd), dns_waitreq, dns_waitreqnew, dnsreq_link)
#define DNSWRQL_REMOVE(dns_mgr_ctx, dns_waitreq)	TAILQ_REMOVE(&((dns_mgr_ctx)->dnsmgr_waitreq_hd), dns_waitreq, dnsreq_link)

#define RQL_INIT(hd)	TAILQ_INIT(hd)
#define RQL_FIRST(hd)	TAILQ_FIRST(hd)
#define RQL_EMPTY(hd)	TAILQ_EMPTY(hd)
#define RQL_END(hd)	TAILQ_END(hd)
#define RQL_NEXT(dns_req)	TAILQ_NEXT(dns_req, dnsreq_link)
#define RQL_INSERT_TAIL(hd, dns_req) TAILQ_INSERT_TAIL(hd, dns_req, dnsreq_link)
#define RQL_REMOVE(hd, dns_req)	TAILQ_REMOVE(hd, dns_req, dnsreq_link)


/*
**  DNS result data
*/

typedef union
{
	ipv4_T		 dnsresu_a;
	sm_cstr_P	 dnsresu_name;	/* name from DNS */
} dns_resu_T;

/*
**  DNS result context
*/

struct dns_res_S
{
	/*
	**  Note: original query is ONLY assigned when the callback is invoked,
	**  otherwise it's invalid (NULL)!
	*/

	sm_cstr_P	 dnsres_query;		/* original query */

	sm_ret_T	 dnsres_ret;		/* error code */
	dns_type_T	 dnsres_qtype;		/* original query type */
	uint		 dnsres_entries;	/* number of entries */
	uint		 dnsres_maxentries;	/* max. number of entries */
	uint16_t	 dnsres_id;		/* dns result id */
	dns_resl_T	 dnsres_hd;	/* head of list of DNS result entries */
};

struct dns_rese_S
{
	dns_type_T	dnsrese_type;	/* result type */
	uint		dnsrese_ttl;	/* TTL from DNS */
	ushort		dnsrese_pref;	/* preference from DNS */
	ushort		dnsrese_weight;	/* for internal randomization */
	sm_cstr_P	dnsrese_name;	/* RR name */
	TAILQ_ENTRY(dns_rese_S)	dnsrese_link;	/* next entry */
	dns_resu_T	dnsrese_val;
};

#define DRESL_INIT(dns_res)	TAILQ_INIT(&((dns_res)->dnsres_hd))
#define DRESL_FIRST(dns_res)	TAILQ_FIRST(&((dns_res)->dnsres_hd))
#define DRESL_END(dns_res)	TAILQ_END(&((dns_res)->dnsres_hd))
#define DRESL_NEXT(dns_rese)	TAILQ_NEXT(dns_rese, dnsrese_link)
#define DRESL_INSERT_TAIL(dns_res, dns_rese) TAILQ_INSERT_TAIL(&((dns_res)->dnsres_hd), dns_rese, dnsrese_link)
#define DRESL_INSERT_HEAD(dns_res, dns_rese) TAILQ_INSERT_HEAD(&((dns_res)->dnsres_hd), dns_rese, dnsrese_link)
#define DRESL_INSERT_AFTER(dns_res, dns_rese_cur, dns_rese) TAILQ_INSERT_AFTER(&((dns_res)->dnsres_hd), dns_rese_cur, dns_rese, dnsrese_link)
#define DRESL_INSERT_BEFORE(dns_res, dns_rese_cur, dns_rese) TAILQ_INSERT_BEFORE(dns_rese_cur, dns_rese, dnsrese_link)
#define DRESL_REMOVE(dns_res, dns_rese)	TAILQ_REMOVE(&((dns_res)->dnsres_hd), dns_rese, dnsrese_link)


#if 0
struct dns_mx_S
{
	uint		dnsmx_entries;		/* number of entries */
	uint		dnsmx_maxentries;	/* max. number of entries */
	dns_mxl_T	dnsmx_hd;		/* head of list of mx entries */
};

struct dns_mxe_S
{
	uint		dnsmxe_ttl;	/* TTL from DNS */
	ushort		dnsmxe_pref;	/* preference from DNS */
	ushort		dnsmxe_weight;	/* for internal randomization */
	TAILQ_ENTRY(dns_mxe_S)	dnsmxe_link;	/* next entry */
	sm_cstr_P	dnsmxe_name;	/* name from DNS */
};

#define DMXL_INIT(dns_mx)	TAILQ_INIT(&((dns_mx)->dnsmx_hd))
#define DMXL_FIRST(dns_mx)	TAILQ_FIRST(&((dns_mx)->dnsmx_hd))
#define DMXL_END(dns_mx)	TAILQ_END(&((dns_mx)->dnsmx_hd))
#define DMXL_NEXT(dns_mxe)	TAILQ_NEXT(dns_mxe, dnsmxe_link)
#define DMXL_INSERT_TAIL(dns_mx, dns_mxe) TAILQ_INSERT_TAIL(&((dns_mx)->dnsmx_hd), dns_mxe, dnsmxe_link)
#define DMXL_INSERT_HEAD(dns_mx, dns_mxe) TAILQ_INSERT_HEAD(&((dns_mx)->dnsmx_hd), dns_mxe, dnsmxe_link)
#define DMXL_INSERT_AFTER(dns_mx, dns_mxe_cur, dns_mxe) TAILQ_INSERT_AFTER(&((dns_mx)->dnsmx_hd), dns_mxe_cur, dns_mxe, dnsmxe_link)
#define DMXL_INSERT_BEFORE(dns_mx, dns_mxe_cur, dns_mxe) TAILQ_INSERT_BEFORE(dns_mxe_cur, dns_mxe, dnsmxe_link)
#define DMXL_REMOVE(dns_mx, dns_mxe)	TAILQ_REMOVE(&((dns_mx)->dnsmx_hd), dns_mxe, dnsmxe_link)
#endif /* 0 */

#endif /* SM_DNS_INT_H */


syntax highlighted by Code2HTML, v. 0.9.1