/* 
 * 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
 */


#include "spf_alt/spf_sys_config.h"


#ifdef STDC_HEADERS
# include <stdio.h>        /* stdin / stdout */
# include <stdlib.h>       /* malloc / free */
#endif

#ifdef HAVE_STRING_H
# include <string.h>       /* strstr / strdup */
#else
# ifdef HAVE_STRINGS_H
#  include <strings.h>       /* strstr / strdup */
# endif
#endif

#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifndef HOST_NAME_MAX
#define HOST_NAME_MAX 255
#endif


#include "spf_alt/spf.h"
#include "spf_alt/spf_internal.h"


static SPF_c_results_t	SPF_default_whitelist;
static SPF_c_results_t	SPF_default_exp;
static char		*SPF_default_rec_dom;
		



SPF_config_t SPF_create_config() 
{
    SPF_iconfig_t *spfic;
        
    spfic = calloc( 1, sizeof(*spfic) );
    if ( spfic ) 
	SPF_reset_config( SPF_spfic2cid(spfic) );

    return SPF_spfic2cid(spfic);
}

void SPF_reset_config( SPF_config_t spfcid )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic(spfcid);


    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    spfic->client_ver = AF_UNSPEC;
    spfic->ipv4.s_addr = htonl( INADDR_ANY );
    spfic->ipv6 = in6addr_any;

    if ( spfic->env_from ) free( spfic->env_from );
    spfic->env_from = NULL;
    
    if ( spfic->helo_dom ) free( spfic->helo_dom );
    spfic->helo_dom = NULL;
    
    if ( spfic->rec_dom ) free( spfic->rec_dom );
    spfic->rec_dom = NULL;
    if ( SPF_default_rec_dom == NULL )
    {
	SPF_default_rec_dom = malloc( HOST_NAME_MAX );
	gethostname( SPF_default_rec_dom, HOST_NAME_MAX );
    }
    if ( SPF_default_rec_dom != NULL )
	spfic->rec_dom = strdup( SPF_default_rec_dom );

    /* if ( spfic->rcpt_to_dom ) free( spfic->rcpt_to_dom ); */
    spfic->rcpt_to_dom = NULL;		/* not malloced			*/
    spfic->found_2mx = FALSE;
    spfic->found_non_2mx = FALSE;
    SPF_free_output( &spfic->output_2mx );

    spfic->max_dns_mech = SPF_DEFAULT_MAX_DNS_MECH;
    spfic->max_dns_ptr = SPF_DEFAULT_MAX_DNS_PTR;
    spfic->max_dns_mx = SPF_DEFAULT_MAX_DNS_MX;
    spfic->sanitize = SPF_DEFAULT_SANITIZE;
    spfic->debug = 0;

    if ( spfic->lp_from ) free( spfic->lp_from );
    spfic->lp_from = NULL;
	
    if ( spfic->dp_from ) free( spfic->dp_from );
    spfic->dp_from = NULL;

    if ( spfic->cur_dom ) free( spfic->cur_dom );
    spfic->cur_dom = NULL;

    if ( spfic->client_dom ) free( spfic->client_dom );
    spfic->client_dom = NULL;

    /* must be always dealt with last because compiling uses the config */
    if ( SPF_default_whitelist.spfid == NULL
	 && SPF_default_whitelist.err == SPF_E_SUCCESS )
    {
	SPF_compile( spfcid, SPF_VER_STR " " SPF_DEFAULT_WHITELIST,
		     &SPF_default_whitelist );
    }
    spfic->local_policy = SPF_default_whitelist;

    if ( SPF_default_exp.spfid == NULL
	 && SPF_default_exp.err == SPF_E_SUCCESS )
    {
	SPF_compile_exp( spfcid, SPF_DEFAULT_EXP, &SPF_default_exp );
    }
    spfic->exp = SPF_default_exp;


    spfic->max_var_len = 0;		/* FIXME: this never shrinks	*/
}
    
void SPF_destroy_config( SPF_config_t spfcid )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic(spfcid);

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    SPF_reset_config( spfcid );
    if ( spfic->rec_dom ) free( spfic->rec_dom ); /* gets realloc on reset */
    free( spfic );
}

SPF_config_t SPF_dup_config( SPF_config_t src_spfcid )
{
    SPF_iconfig_t	*src_spfic = SPF_cid2spfic( src_spfcid );
    SPF_config_t	dst_spfcid;
    SPF_iconfig_t	*dst_spfic;

    if ( src_spfcid == NULL )
	SPF_error( "src_spfcid is NULL" );


    dst_spfcid = SPF_create_config();
    dst_spfic = SPF_cid2spfic( dst_spfcid );

    if ( dst_spfic )
    {

	dst_spfic->client_ver = src_spfic->client_ver;
	dst_spfic->ipv4 = src_spfic->ipv4;
	dst_spfic->ipv6 = src_spfic->ipv6;

	if ( src_spfic->env_from )
	{
	    dst_spfic->env_from = strdup( src_spfic->env_from );
	    if ( !dst_spfic->env_from )
		goto error;
	}
	
	if ( src_spfic->helo_dom )
	{
	    dst_spfic->helo_dom = strdup( src_spfic->helo_dom );
	    if ( !dst_spfic->helo_dom )
		goto error;
	}
    
	if ( src_spfic->rec_dom )
	{
	    dst_spfic->rec_dom = strdup( src_spfic->rec_dom );
	    if ( !dst_spfic->rec_dom )
		goto error;
	}
    
	if ( src_spfic->rcpt_to_dom )
	{
	    dst_spfic->rcpt_to_dom = strdup( src_spfic->rcpt_to_dom );
	    if ( !dst_spfic->rcpt_to_dom )
		goto error;
	}
	dst_spfic->found_2mx = src_spfic->found_2mx;
	dst_spfic->found_non_2mx = src_spfic->found_non_2mx;
	dst_spfic->output_2mx = SPF_dup_output( src_spfic->output_2mx );

	dst_spfic->max_dns_mech = src_spfic->max_dns_mech;
	dst_spfic->max_dns_ptr = src_spfic->max_dns_ptr;
	dst_spfic->max_dns_mx = src_spfic->max_dns_mx;
	dst_spfic->sanitize = src_spfic->sanitize;
	dst_spfic->debug = src_spfic->debug;

	/* note:  these two spfid variable's allocation are controlled
	 *        by calling routines and can only be freed when all
	 *        configs that use them are freed
	 */
	dst_spfic->local_policy = src_spfic->local_policy;
	dst_spfic->exp = src_spfic->exp;

	if ( src_spfic->lp_from )
	{
	    dst_spfic->lp_from = strdup( src_spfic->lp_from );
	    if ( !dst_spfic->lp_from )
		goto error;
	}
    
	if ( src_spfic->dp_from )
	{
	    dst_spfic->dp_from = strdup( src_spfic->dp_from );
	    if ( !dst_spfic->dp_from )
		goto error;
	}
    
	if ( src_spfic->cur_dom )
	{
	    dst_spfic->cur_dom = strdup( src_spfic->cur_dom );
	    if ( !dst_spfic->cur_dom )
		goto error;
	}
    
	if ( src_spfic->client_dom )
	{
	    dst_spfic->client_dom = strdup( src_spfic->client_dom );
	    if ( !dst_spfic->client_dom )
		goto error;
	}


	dst_spfic->max_var_len = src_spfic->max_var_len;
    }
    
    return dst_spfcid;

  error:
    
    SPF_destroy_config( dst_spfcid );
    return NULL;

}

void SPF_destroy_default_config()
{
    SPF_free_c_results( &SPF_default_whitelist );
    SPF_free_c_results( &SPF_default_exp );
    if ( SPF_default_rec_dom ) free( SPF_default_rec_dom );
    SPF_default_rec_dom = NULL;
}





int SPF_set_ip_str( SPF_config_t spfcid, const char *ip_address )
{
    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    if ( ip_address == NULL )
	ip_address = "0.0.0.0";

    if ( strchr( ip_address, ':' ) )
	return SPF_set_ipv6_str( spfcid, ip_address );
    else
	return SPF_set_ipv4_str( spfcid, ip_address );
}

int SPF_set_ipv4_str( SPF_config_t spfcid, const char *ipv4_address )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic(spfcid);

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    if ( ipv4_address == NULL )
	ipv4_address = "0.0.0.0";

    if ( spfic->client_dom ) free( spfic->client_dom );
    spfic->client_dom = NULL;
    spfic->found_2mx = FALSE;
    spfic->found_non_2mx = FALSE;

    spfic->client_ver = AF_INET;
    return inet_pton( AF_INET, ipv4_address, &spfic->ipv4) <= 0;
}

int SPF_set_ipv6_str( SPF_config_t spfcid, const char *ipv6_address )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic(spfcid);
    int		err;

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    if ( ipv6_address == NULL )
	ipv6_address = "::";

    if ( spfic->client_dom ) free( spfic->client_dom );
    spfic->client_dom = NULL;
    spfic->found_2mx = FALSE;
    spfic->found_non_2mx = FALSE;

    spfic->client_ver = AF_INET6;
    err = inet_pton( AF_INET6, ipv6_address, &spfic->ipv6) <= 0;
    if ( err )
	return err;
    
    if ( IN6_IS_ADDR_V4MAPPED( &spfic->ipv6 ) )
    {
	struct in_addr ipv4;

	memcpy( &ipv4, &spfic->ipv6.s6_addr[12], sizeof( ipv4 ) );
	return SPF_set_ipv4( spfcid, ipv4 );
    }

    return err;
}


int SPF_set_ipv4( SPF_config_t spfcid, struct in_addr ipv4 )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic(spfcid);

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    if ( spfic->client_dom ) free( spfic->client_dom );
    spfic->client_dom = NULL;
    spfic->found_2mx = FALSE;
    spfic->found_non_2mx = FALSE;

    spfic->client_ver = AF_INET;
    spfic->ipv4 = ipv4;
    return 0;
}

int SPF_set_ipv6( SPF_config_t spfcid, struct in6_addr ipv6 )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic(spfcid);

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    if ( spfic->client_dom ) free( spfic->client_dom );
    spfic->client_dom = NULL;
    spfic->found_2mx = FALSE;
    spfic->found_non_2mx = FALSE;

    spfic->client_ver = AF_INET6;
    spfic->ipv6 = ipv6;
    return 0;
}


int SPF_set_env_from( SPF_config_t spfcid, const char *envelope_from )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic(spfcid);
    char	*pos;
    size_t	len;

    /* FIXME: validate charset/format  (local-part will be a bitch)*/

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );


    if ( spfic->env_from ) free( spfic->env_from );
    spfic->env_from = NULL;

    if ( envelope_from == NULL || *envelope_from == '\0' )
    {
	if ( spfic->helo_dom )
	    envelope_from = spfic->helo_dom;
	else
	    return 0;
    }
    
    spfic->env_from = strdup( envelope_from );
    if ( spfic->env_from == NULL )
	return 1;

    len = strlen( envelope_from );
    if ( spfic->max_var_len < len ) spfic->max_var_len = len;
    
    if ( spfic->lp_from ) free( spfic->lp_from );
    if ( spfic->dp_from ) free( spfic->dp_from );
    if ( spfic->cur_dom ) free( spfic->cur_dom );


    /* FIXME is this supposed to be the last @ sign? */
    pos = strrchr( spfic->env_from, '@' );
    if ( pos == NULL )
    {
	
	spfic->lp_from = strdup( "postmaster" );
	spfic->dp_from = strdup( spfic->env_from );
	spfic->cur_dom = strdup( spfic->env_from );
	free( spfic->env_from );
	len = sizeof( "postmaster@" ) + strlen( spfic->dp_from );
	spfic->env_from = malloc( len );
	if ( spfic->env_from )
	    snprintf( spfic->env_from, len, "postmaster@%s", spfic->dp_from );
    } else {
	spfic->lp_from = malloc( pos - spfic->env_from + 1 );
	if ( spfic->lp_from )
	{
	    memcpy( spfic->lp_from, spfic->env_from,
		    pos - spfic->env_from );
	    spfic->lp_from[ pos - spfic->env_from ] = '\0';
	}
	spfic->dp_from = strdup( pos + 1 );
	spfic->cur_dom = strdup( pos + 1 );
    }

    
    if ( spfic->env_from == NULL
	 || spfic->lp_from == NULL
	 || spfic->dp_from == NULL
	 || spfic->cur_dom == NULL)
    {
	free( spfic->env_from );
	spfic->env_from = NULL;

	if ( spfic->lp_from ) free( spfic->lp_from );
	spfic->lp_from = NULL;
	
	if ( spfic->dp_from ) free( spfic->dp_from );
	spfic->dp_from = NULL;

	if ( spfic->cur_dom ) free( spfic->cur_dom );
	spfic->cur_dom = NULL;

	return 1;
    }
    
    return 0;
}


int SPF_set_helo_dom( SPF_config_t spfcid, const char *helo_domain )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic(spfcid);
    size_t	len;

    /* FIXME: validate charset/format */

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    if ( spfic->helo_dom ) free( spfic->helo_dom );
    spfic->helo_dom = NULL;
    if ( helo_domain == NULL )
	return 0;

    spfic->helo_dom = strdup( helo_domain );
    if ( spfic->helo_dom == NULL ) return 1;

    if ( spfic->cur_dom == NULL )
	spfic->cur_dom = strdup( spfic->helo_dom );

    if ( spfic->env_from == NULL )
	SPF_set_env_from( spfcid, spfic->helo_dom );

    len = strlen( helo_domain );
    if ( spfic->max_var_len < len ) spfic->max_var_len = len;
    
    return 0;
}


int SPF_set_cur_dom( SPF_config_t spfcid, const char *current_domain )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic(spfcid);
    size_t	len;

    /* FIXME: validate charset/format */

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    if ( spfic->cur_dom ) free( spfic->cur_dom );
    spfic->cur_dom = NULL;
    if ( current_domain == NULL )
	return 0;

    spfic->cur_dom = strdup( current_domain );
    if ( spfic->cur_dom == NULL ) return 1;

    len = strlen( current_domain );
    if ( spfic->max_var_len < len ) spfic->max_var_len = len;
    
    return 0;
}


int SPF_set_max_dns_mech( SPF_config_t spfcid, int max_dns_mech )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic(spfcid);


    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    /* If you want to go beyond the spec, you need to recompile the
     * the library. */
    if ( max_dns_mech > SPF_MAX_DNS_MECH ) 
    {
	spfic->max_dns_mech = SPF_MAX_DNS_MECH;
	return 1;
    }
    

    spfic->max_dns_mech = max_dns_mech;
    return 0;
}


int SPF_set_max_dns_ptr( SPF_config_t spfcid, int max_dns_ptr )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic(spfcid);


    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    /* If you want to go beyond the spec, you need to recompile the
     * the library. */
    if ( max_dns_ptr > SPF_MAX_DNS_PTR ) 
    {
	spfic->max_dns_ptr = SPF_MAX_DNS_PTR;
	return 1;
    }
    

    spfic->max_dns_ptr = max_dns_ptr;
    return 0;
}


int SPF_set_max_dns_mx( SPF_config_t spfcid, int max_dns_mx )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic(spfcid);


    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    /* If you want to go beyond the spec, you need to recompile the
     * the library. */
    if ( max_dns_mx > SPF_MAX_DNS_MX ) 
    {
	spfic->max_dns_mx = SPF_MAX_DNS_MX;
	return 1;
    }
    

    spfic->max_dns_mx = max_dns_mx;
    return 0;
}


int SPF_set_sanitize( SPF_config_t spfcid, int sanitize )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic(spfcid);

    /* FIXME: validate? */

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    spfic->sanitize = sanitize;
    return 0;
}


int SPF_set_rec_dom( SPF_config_t spfcid, const char *receiving_hostname )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic(spfcid);
    size_t	len;

    /* FIXME: validate charset/format */

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    if ( spfic->rec_dom ) free( spfic->rec_dom );
    spfic->rec_dom = NULL;
    if ( receiving_hostname == NULL )
	return 0;
    spfic->rec_dom = strdup( receiving_hostname );
    if ( spfic->rec_dom == NULL ) return 1;

    len = strlen( receiving_hostname );
    if ( spfic->max_var_len < len ) spfic->max_var_len = len;
    
    return 0;
}


SPF_err_t SPF_compile_local_policy( SPF_config_t spfcid, const char *spf_record,
				int use_default_whitelist,
				SPF_c_results_t *c_results )
{
    SPF_iconfig_t	*spfic = SPF_cid2spfic(spfcid);

    char		*buf;
    size_t		len;

    SPF_err_t		err;
    
    

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    if ( c_results == NULL )
	SPF_error( "c_results is NULL" );

    if ( spf_record == NULL  &&  !use_default_whitelist )
	return SPF_E_SUCCESS;
    
    if ( spf_record == NULL )
	spf_record = "";


    len = strlen( spf_record )
	+ sizeof( SPF_VER_STR " " SPF_DEFAULT_WHITELIST " " );
    buf = malloc( len );
    
    if ( use_default_whitelist )
	snprintf( buf, len, "%s %s %s",
		      SPF_VER_STR, spf_record, SPF_DEFAULT_WHITELIST );
    else if ( *spf_record != '\0' )
	snprintf( buf, len, "%s %s",
		      SPF_VER_STR, spf_record );

    err = SPF_compile( spfcid, buf, c_results );

    free( buf );
    
    if ( err  &&  c_results->spfid )
    {
	if ( spfic->debug > 0 )
	    SPF_warning( c_results->err_msg );

	return err;
    }
    
    return SPF_E_SUCCESS;
}


int SPF_set_local_policy( SPF_config_t spfcid,
			  SPF_c_results_t c_results )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic(spfcid);

    /* FIXME: validate local_policy? */

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    spfic->local_policy = c_results;
    return 0;
}



SPF_err_t SPF_compile_exp( SPF_config_t spfcid, const char *exp, SPF_c_results_t *c_results )
{
    char	*spf_rec;
    SPF_err_t	err;
    size_t	len;
    char	*p;
    const char	*s;

    
#define SPF_EXP_MOD	SPF_VER_STR " " SPF_EXP_MOD_NAME "="

    len = strlen( exp );
    spf_rec = malloc( len * 2 + sizeof( SPF_EXP_MOD ) );
    if ( spf_rec == NULL )
	return SPF_E_NO_MEMORY;
	
    strcpy( spf_rec, SPF_EXP_MOD );
	
    p = spf_rec + sizeof( SPF_EXP_MOD ) - 1;
    s = exp;

    while( *s != '\0' )
    {
	if ( *s == ' ' )
	{
	    *p++ = '%';
	    *p++ = '_';
	}
	else
	    *p++ = *s;
	s++;
    }
    *p = *s;
    
    err = SPF_compile( spfcid, spf_rec, c_results );

    free( spf_rec );

    return err;
}

int SPF_set_exp( SPF_config_t spfcid, SPF_c_results_t c_results )
{
    SPF_iconfig_t	*spfic = SPF_cid2spfic(spfcid);

    /* FIXME: validate exp? */

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    spfic->exp = c_results;
    return 0;
}




int SPF_set_debug( SPF_config_t spfcid, int debug_level )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic(spfcid);

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    spfic->debug = debug_level;

    if ( spfic->debug > 0 )
    {
	if ( SPF_default_whitelist.err )
	    SPF_warning( SPF_default_whitelist.err_msg );

	if ( SPF_default_exp.err )
	    SPF_warning( SPF_default_exp.err_msg );
    }
    
    return 0;
}



int SPF_get_client_ver( SPF_config_t spfcid )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic( spfcid );

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    return spfic->client_ver;
}


struct in_addr SPF_get_ipv4( SPF_config_t spfcid )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic( spfcid );
    struct in_addr  any;

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    if ( spfic->client_ver != AF_INET )
    {
	any.s_addr = htonl( INADDR_ANY ); 
	return any;
    }
    

    return spfic->ipv4;
}


struct in6_addr SPF_get_ipv6( SPF_config_t spfcid )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic( spfcid );

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    if ( spfic->client_ver != AF_INET6 )
	return in6addr_any;

    return spfic->ipv6;
}


char *SPF_get_env_from( SPF_config_t spfcid )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic( spfcid );

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    return spfic->env_from;
}


char *SPF_get_helo_dom( SPF_config_t spfcid )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic( spfcid );

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    return spfic->helo_dom;
}


char *SPF_get_cur_dom( SPF_config_t spfcid )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic( spfcid );

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    return spfic->cur_dom;
}


char *SPF_get_client_dom( SPF_config_t spfcid, SPF_dns_config_t spfdcid )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic( spfcid );

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    if( spfic->client_dom == NULL )
	SPF_set_client_dom( spfcid, spfdcid );

    return spfic->client_dom;
}


int  SPF_get_max_dns_mech( SPF_config_t spfcid )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic( spfcid );

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    return spfic->max_dns_mech;
}


int  SPF_get_max_dns_ptr( SPF_config_t spfcid )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic( spfcid );

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    return spfic->max_dns_ptr;
}


int  SPF_get_max_dns_mx( SPF_config_t spfcid )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic( spfcid );

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    return spfic->max_dns_mx;
}


int  SPF_get_sanitize( SPF_config_t spfcid )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic( spfcid );

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    return spfic->sanitize;
}


char *SPF_get_rec_dom( SPF_config_t spfcid )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic( spfcid );

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    return spfic->rec_dom;
}


SPF_c_results_t SPF_get_local_policy( SPF_config_t spfcid )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic( spfcid );

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    return spfic->local_policy;
}


int  SPF_get_debug( SPF_config_t spfcid )
{
    SPF_iconfig_t *spfic = SPF_cid2spfic( spfcid );

    if ( spfcid == NULL )
	SPF_error( "spfcid is NULL" );

    return spfic->debug;
}



syntax highlighted by Code2HTML, v. 0.9.1