/* 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of either:
 * 
 *   a) The GNU Lesser General Public License as published by the Free
 *      Software Foundation; either version 2.1, or (at your option) any
 *      later version,
 * 
 *   OR
 * 
 *   b) The two-clause BSD license.
 *
 * These licenses can be found with the distribution in the file LICENSES
 */




#ifndef INC_SPF_DNS
#define INC_SPF_DNS


/*
 * This library has the ability to use one or more of any of a number
 * of DNS "layers" to obtain DNS information.  These layers all have
 * compatible APIs, with only minor differences that relate to their
 * specific functions.  So, they can be mixed and matched in any order
 * to do what you want.
 *
 * When you create a new DNS layer, you can (optionally) specify the
 * layer below it.  If the current DNS layer is not able to resolve
 * the query, it will automatically call the lower layer.
 *
 * Some of the DNS layers allow for debugging information to be
 * printed, some do caching, and, of course, some return actual DNS
 * results either by query the network or by looking up the query in a
 * database.
 *
 * For details about each DNS layer, see the appropriate
 * spf_dns_<layer>.h include file.
 *
 *
 * For example, there is a caching DNS layer that saves the compiled
 * SPF records for future use.  While it takes a small amount of time
 * to compile the AOL SPF record, you will more than make up for it by
 * not having to parse the record every time you get a message from
 * AOL.
 * 
 * If you wanted to, you can even run the SPF system without using
 * real DNS lookups at all.  For testing, I used a DNS layer that
 * contained a built-in zone file.  This idea could easily be extended
 * to being able to read the zone file from disk, or to use a database
 * to access information.
 * 
 * One example of what you could do with such a zone file would be to
 * create your own SPF records for the many free-email providers.
 * Depending on whether you layer this local zone file before or after
 * the real DNS lookups, you can either override published SPF
 * records, or you can provide defaults until SPF records are
 * published.
 * 
 */


/*
 * For those who don't have <arpa/nameserv.h>
 */

#if !defined( HAVE_NS_TYPE )

#define	ns_t_invalid	0
#define	ns_t_a		1
#define	ns_t_ns		2
#define	ns_t_cname	5
#define	ns_t_ptr	12
#define	ns_t_mx		15
#define	ns_t_txt	16
#define ns_t_aaaa	28
/* #define ns_t_a6		38 */
#define	ns_t_any        255		/* Wildcard match. */

typedef int	ns_type;
#endif

#ifndef ns_t_invalid
#define	ns_t_invalid	0
#endif


/*
 * For those who don't have <netdb.h>
 */

#if !defined(HAVE_NETDB_H) && !defined(_WIN32)
#define NETDB_SUCCESS	0
#define	HOST_NOT_FOUND 	1		/* NXDOMAIN (authoritative answer)*/
#define	TRY_AGAIN	2		/* SERVFAIL (no authoritative answer)*/
#define	NO_RECOVERY	3		/* invalid/unimplmeneted query	*/
#define	NO_DATA		4		/* host found, but no RR of req type*/
#endif
typedef int SPF_dns_stat_t;

typedef struct SPF_dns_server_struct SPF_dns_server_t;

#include "spf_request.h"
#include "spf_dns_rr.h"

/*
 * bundle up the info needed to use a dns method
 */

typedef void (*SPF_dns_destroy_t)(SPF_dns_server_t *spf_dns_server);
typedef SPF_dns_rr_t *(*SPF_dns_lookup_t)(
				SPF_dns_server_t *spf_dns_server,
				const char *domain,
				ns_type ns_type, int should_cache
					);
typedef SPF_errcode_t (*SPF_dns_get_spf_t)( SPF_server_t *spf_server,
					SPF_request_t *spf_request,
					SPF_response_t *spf_response,
					SPF_record_t **spf_recordp);
typedef SPF_errcode_t (*SPF_dns_get_exp_t)( SPF_server_t *spf_server,
					const char *domain,
					char **buf, size_t *buf_len );
typedef int (*SPF_dns_add_cache_t)( SPF_server_t *spf_server,
				    SPF_dns_rr_t spfrr );

struct SPF_dns_server_struct
{
    SPF_dns_destroy_t	 destroy;

    SPF_dns_lookup_t	 lookup;
    SPF_dns_get_spf_t	 get_spf;
    SPF_dns_get_exp_t	 get_exp;
    SPF_dns_add_cache_t  add_cache;

    /* the next DNS layer down to call if this layer can't give an answer */
    SPF_dns_server_t	*layer_below;

    const char			*name;		/* name of the layer		*/
	int					 debug;
    void				*hook;		/* server-specific data */
};


void			 SPF_dns_free( SPF_dns_server_t *spf_dns_server );
SPF_dns_rr_t	*SPF_dns_lookup( SPF_dns_server_t *spf_dns_server,
			      const char *domain, ns_type rr_type,
			      int should_cache );
SPF_dns_rr_t	*SPF_dns_rlookup( SPF_dns_server_t *spf_dns_server,
			       struct in_addr ipv4, ns_type rr_type,
			       int should_cache );
SPF_dns_rr_t	*SPF_dns_rlookup6( SPF_dns_server_t *spf_dns_server,
				struct in6_addr ipv6, ns_type rr_type,
				int should_cache );


/* The client domain is the validated domain name of the client IP
 * address.  This is not just the domain name(s) found in the reverse
 * DNS tree, but involves checking to make sure these name(s) use the
 * client IP address.  The complete validation procedure is described
 * in section 5.4 of the SPF spec.
 */
char		*SPF_dns_get_client_dom(SPF_dns_server_t *spf_dns_server,
				SPF_request_t *sr);

/*
 * helper functions
 */


#if 0
#ifdef WORDS_BIGENDIAN
#define SPF_IPV4(a,b,c,d) ((unsigned long)((((unsigned long)a)<<24) + (((unsigned long)b)<<16) + (((unsigned long)c)<<8) + (unsigned long)d))
#else
#define SPF_IPV4(a,b,c,d) ((unsigned long)((((unsigned long)d)<<24) + (((unsigned long)c)<<16) + (((unsigned long)b)<<8) + (unsigned long)a))
#endif
#endif


#endif


syntax highlighted by Code2HTML, v. 0.9.1