Index: config.h.in
===================================================================
--- config.h.in	2005-03-01 11:02:52.000000000 -0500
+++ config.h.in	2006-01-11 13:32:49.000000000 -0500
@@ -24,6 +24,9 @@
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
+/* Define to 1 if you have the `crypto' library (-lcrypto). */
+#undef HAVE_LIBCRYPTO
+
 /* Define to 1 if you have the `milter' library (-lmilter). */
 #undef HAVE_LIBMILTER
 
@@ -42,6 +45,12 @@
 /* Define to 1 if you have the `spf2' library (-lspf2). */
 #undef HAVE_LIBSPF2
 
+/* Define to 1 if you have the `sres' library (-lsres). */
+#undef HAVE_LIBSRES
+
+/* Define to 1 if you have the `val' library (-lval). */
+#undef HAVE_LIBVAL
+
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
@@ -123,9 +132,15 @@
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
+/* Support DNSSEC validation */
+#undef SUPPORT_DNSSEC
+
 /* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
 #undef TIME_WITH_SYS_TIME
 
+/* libspf2 version 1.2.x */
+#undef USE_LIBSPF2_1_2_X
+
 /* Version number of package */
 #undef VERSION
 
Index: configure.ac
===================================================================
--- configure.ac	2005-02-11 11:03:53.000000000 -0500
+++ configure.ac	2006-04-13 18:13:31.000000000 -0400
@@ -54,24 +54,97 @@
 AC_CHECK_FUNC(socket, ,
 	AC_CHECK_LIB(socket, socket, ,
 		AC_CHECK_LIB(nsl, socket)))
-AC_CHECK_FUNCS(inet_ntop, ,
+
+AC_MSG_CHECKING(whether we need to support DNSSEC validation)
+AC_ARG_ENABLE(dnssec-support,
+[  --enable-dnssec-support Support DNSSEC validation.],
+    support_dnssec=yes)
+
+if test "x$support_dnssec" = "xyes"; then
+
+   AC_MSG_RESULT(yes)
+
+   AC_CHECK_FUNCS(inet_ntop, ,
+	AC_CHECK_LIB(nsl, inet_ntop, ,
+		AC_CHECK_LIB(socket, inet_ntop)))
+
+   dnl Check the openssl crypto library
+   AC_CHECK_LIB(crypto, RSA_verify, , [
+	echo "the openssl crypto library is required to build this program."
+	exit 1;
+   ])
+
+   dnl Check libsres
+   AC_ARG_WITH(libsres,
+	[  --with-libsres=PATH     Look for the libsres library in PATH],
+	if test "x$withval" != "xyes"; then
+	  if test "x$withval" != x -a -d $withval; then
+	      LDFLAGS="-L$withval $LDFLAGS"
+	      AC_MSG_CHECKING(libsres)
+	      AC_MSG_RESULT("$withval")
+	  fi
+	fi
+   )
+
+   dnl Check Secure Resolver Library libsres
+   AC_CHECK_LIB(sres, query_send, , [
+	echo "the secure resolver library is required to build this program."
+	echo "see http://dnssec-tools.sourceforge.net"
+	exit 1;
+   ], -L/usr/local/lib)
+
+   dnl Check libval
+   AC_ARG_WITH(libval,
+	[  --with-libval=PATH      Look for the libval library in PATH],
+	if test "x$withval" != "xyes"; then
+	  if test "x$withval" != x -a -d $withval; then
+	      LDFLAGS="-L$withval $LDFLAGS"
+	      AC_MSG_CHECKING(libval)
+	      AC_MSG_RESULT("$withval")
+	  fi
+	fi
+   )
+
+   dnl Check DNSSEC Validator library
+   AC_CHECK_LIB(val, val_query, , [
+	echo "the validator library is required to build this program."
+        echo "see http://dnssec-tools.sourceforge.net"
+	exit 1;
+   ], -lsres -lcrypto -lpthread -L/usr/local/lib)
+
+   AC_DEFINE([SUPPORT_DNSSEC], [], [Support DNSSEC validation])
+
+else
+   AC_MSG_RESULT(no)
+
+   AC_CHECK_FUNCS(inet_ntop, ,
 	AC_CHECK_LIB(nsl, inet_ntop, ,
 		AC_CHECK_LIB(socket, inet_ntop, ,
 			AC_CHECK_LIB(resolv, inet_ntop))))
-AC_CHECK_FUNC(gethostbyname, ,
+   AC_CHECK_FUNC(gethostbyname, ,
 	AC_CHECK_LIB(nsl, gethostbyname, ,
 		AC_CHECK_LIB(socket, gethostbyname, ,
 			AC_CHECK_LIB(resolv, gethostbyname))))
+fi
 
 AC_CHECK_HEADER(spf2/spf.h, , [
 	echo "libspf2 is required to build this program."
 	exit 1;
+], [
+#include <netinet/in.h>
 ])
-AC_CHECK_LIB(spf2, SPF_destroy_config, , [
-	echo "libspf2 is required to build this program."
-	exit 1;
+
+dnl Check for newer version (1.2.x) of libspf2 header files
+AC_CHECK_HEADER(spf2/spf_server.h, [AC_DEFINE([USE_LIBSPF2_1_2_X], [], [libspf2 version 1.2.x])], , [
+#include <netinet/in.h>
 ])
 
+AC_CHECK_LIB(spf2, SPF_destroy_config, ,
+        AC_CHECK_LIB(spf2, SPF_server_new, , [
+	     echo "libspf2 is required to build this program."
+	     exit 1;
+]))
+
 AC_CHECK_HEADER(libmilter/mfapi.h, , [
 	echo "sendmail's libmilter is required to build this program."
 	exit 1;
Index: spfmilter.c
===================================================================
--- spfmilter.c	2005-06-03 14:04:05.000000000 -0400
+++ spfmilter.c	2006-02-09 11:44:27.000000000 -0500
@@ -27,8 +27,13 @@
 ** For commentary on this license please see http://www.acme.com/license.html
 */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else
+#include "port.h"
+#endif
 
-#if ! ( defined(USE_LIBSPF) || defined(USE_LIBSPF2) )
+#if ! ( defined(USE_LIBSPF) || defined(USE_LIBSPF2) || defined(USE_LIBSPF2_1_2_X))
 #define USE_LIBSPF2	/* default library is libspf2 */
 #endif
 
@@ -36,13 +41,11 @@
 #error "both USE_LIBSPF and USE_LIBSPF2 are defined - please pick one"
 #endif
 
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#else
-#include "port.h"
+#ifdef USE_LIBSPF2_1_2_X
+#undef USE_LIBSPF2
 #endif
 
+
 #ifdef STDC_HEADERS
 #include <stdio.h>
 #include <stdlib.h>
@@ -106,6 +109,7 @@
 /* Defines. */
 
 #define HEADER_NAME "Received-SPF"
+#define PID_FILE "/var/run/spfmilter.pid"
 
 #define SPFMILTER_RESULT_PASS 0
 #define SPFMILTER_RESULT_FAIL 1
@@ -121,6 +125,11 @@
 #define SPFMILTER_ACTION_MARK 2
 #define SPFMILTER_ACTION_TEMPFAIL 3
 
+#ifdef SUPPORT_DNSSEC
+#define SPFMILTER_DNSSEC_POLICY_IGNORE 0
+#define SPFMILTER_DNSSEC_POLICY_WARN 1
+#define SPFMILTER_DNSSEC_POLICY_REJECT 2
+#endif
 
 /* Structs. */
 
@@ -234,6 +243,11 @@
 static const char* lib_get_reason( lib_data_t* ld );
 static const char* lib_get_explanation( lib_data_t* ld );
 static const char* lib_get_error( lib_data_t* ld );
+#ifdef SUPPORT_DNSSEC
+static const char* lib_get_error_msg( lib_data_t* ld );
+static const size_t lib_get_num_errors( lib_data_t* ld );
+static const char** lib_get_error_msgs( lib_data_t* ld );
+#endif
 static void lib_fini_message_data( lib_data_t* ld );
 static void lib_fini_connection_data( lib_data_t* ld );
 static void lib_fini_fallback( lib_fallback_t* lf );
@@ -254,6 +268,10 @@
 static char* local_hostname;
 static int local_hostname_len;
 
+#ifdef SUPPORT_DNSSEC
+static int dnssec_policy;
+#endif
+
 static int header_name_len;
 
 static struct smfiDesc smfilter = {
@@ -287,6 +305,11 @@
     { "nodaemon",		no_argument,		NULL,	'X', },
     { "help",			no_argument,		NULL,	'h', },
     { "debug",			optional_argument,	NULL,	'd', },
+
+#ifdef SUPPORT_DNSSEC
+    { "dnssec_policy",          required_argument,      NULL,   's', },
+#endif
+
     { 0, 0, 0, 0 },
 };
 #define DOC_LONGOPT(l, v, t, p1) \
@@ -296,7 +319,11 @@
 #else
 #define DOC_LONGOPT(l, v, t, p1) do { } while( 0 )
 #endif
+#ifdef SUPPORT_DNSSEC
+static const char* shortopts = "l:tg:f:w:re:mu:p:Xhd:s:";
+#else
 static const char* shortopts = "l:tg:f:w:re:mu:p:Xhd::";
+#endif
 
 #define DOC_OPT(s, l, v, t, p0, p1) \
     do { \
@@ -329,10 +356,14 @@
     explanation_str = (char*) 0;
     markonly = 0;
     user = (char*) 0;
-    pidfile = (char*) 0;
+    pidfile = PID_FILE;
     nodaemon = 0;
     debug = 0;
 
+#ifdef SUPPORT_DNSSEC
+    dnssec_policy = SPFMILTER_DNSSEC_POLICY_IGNORE;
+#endif
+
     /* Figure out the program's name. */
     argv0 = strrchr( argv[0], '/' );
     if ( argv0 != (char*) 0 )
@@ -396,6 +427,37 @@
 		else
 		    debug = 1;
 		break;
+
+#ifdef SUPPORT_DNSSEC
+	    case 's':
+	        if ( optarg )
+		    {
+		    if ( strncasecmp( optarg, "ignore", 6 ) == 0 )
+			{
+		        if ( debug )
+	 		    printf( "DNSSEC policy = ignore\n" );
+		        dnssec_policy = SPFMILTER_DNSSEC_POLICY_IGNORE;
+			}
+		    else if ( strncasecmp( optarg, "warn", 4 ) == 0 )
+			{
+		        if ( debug )
+	 		    printf( "DNSSEC policy = warn\n" );
+		        dnssec_policy = SPFMILTER_DNSSEC_POLICY_WARN;
+			}
+		    else if ( strncasecmp( optarg, "reject", 6 ) == 0 )
+			{
+		        if ( debug )
+	 		    printf( "DNSSEC policy = reject\n" );
+		        dnssec_policy = SPFMILTER_DNSSEC_POLICY_REJECT;
+			}
+		    else
+			{
+		        fprintf( stderr, "Unrecognized option argument '%s'\n", optarg );
+			}
+		}
+		break;
+#endif
+
 	    default:
 		(void) fprintf( stderr, "Unrecognised option '%c'\n", c );
 		exit( 1 );
@@ -465,6 +527,11 @@
     DOC_OPT( 'X', "nodaemon", (char*) 0, "Do not fork into the background.", 20, 26 );
     DOC_OPT( 'h', "help", (char*) 0, "Show this help.", 20, 26 );
     DOC_OPT( 'd', "debug", "[<int>]", "Enable debugging to syslog.", 13, 18 );
+
+#ifdef SUPPORT_DNSSEC
+    DOC_OPT( 's', "dnssec_policy", "<ignore|warn|reject>", "Action in the event of DNSSEC validation failure", 16, 3 );
+#endif
+
     }
 
 
@@ -1288,6 +1355,12 @@
     const char* exp;
     char exp_escaped[1000];
 
+#ifdef SUPPORT_DNSSEC
+    const char* errmsg;
+    char exp_errmsg[1000];
+    char err_reply[2048];
+#endif
+
     cd = (connection_data_t*) smfi_getpriv( ctx );
 
     switch ( cd->result )
@@ -1318,7 +1391,22 @@
 		escape_percents( exp, exp_escaped, sizeof(exp_escaped) );
 	    else
 		(void) strncpy( exp_escaped, "rejected by spfmilter", sizeof(exp_escaped) - 1 );
+
+#ifdef SUPPORT_DNSSEC
+	    strncpy( err_reply, exp_escaped, sizeof(err_reply) - 1 );
+
+	    errmsg = lib_get_error_msg( cd->lib_data );
+	    if ( errmsg != (char*) 0 )
+		{
+	        escape_percents( errmsg, exp_errmsg, sizeof(exp_errmsg) );
+		strncpy( err_reply + strlen( exp_escaped ), ".  Error: ", sizeof(err_reply) - strlen( exp_escaped ) - 1 );
+		strncpy( err_reply + strlen( err_reply ), exp_errmsg, sizeof(err_reply) - strlen( err_reply ) - 1 );
+		}
+
+	    smfi_setreply( ctx, "550", "5.7.1", err_reply );
+#else
 	    smfi_setreply( ctx, "550", "5.7.1", exp_escaped );
+#endif
 	    fini_message_data( cd );
 	    return SMFIS_REJECT;
 
@@ -1443,6 +1531,14 @@
     {
     int len;
 
+#ifdef SUPPORT_DNSSEC
+    int i;
+    char *err_msg;
+    char **err_msgs;
+    size_t num_errs;
+    int first_err;
+#endif
+
     (void) snprintf( header, header_size, "%s", result_str( cd->result ) );
     len = strlen( header );
     if ( reason != (char*) 0 )
@@ -1471,6 +1567,82 @@
 	len = strlen( header );
 	}
     /*!!! Do something about the problem= field. */
+
+#ifdef SUPPORT_DNSSEC
+    err_msg = (char *) ( lib_get_error_msg( cd->lib_data ) );
+    err_msgs = (char **) ( lib_get_error_msgs( cd->lib_data ) );
+    num_errs = lib_get_num_errors( cd->lib_data );
+    first_err = 1;
+    if ( ( err_msg != (char*) 0 ) && ( strstr( err_msg, "DNSSEC" ) == NULL ) )
+        {
+	(void) snprintf( &header[len], header_size - len, " problem=%s;", err_msg );
+	first_err = 0;
+	len = strlen( header );
+	}
+
+    for( i = 0; i < num_errs; i++ )
+	{
+	if( ( err_msgs[i] != NULL ) &&
+	    ( strstr( err_msgs[i], "DNSSEC" ) == NULL ) &&
+	    ( ( err_msg == NULL ) || ( strcmp( err_msgs[i], err_msg ) != 0 ) )
+	  )
+	    {
+	    if ( first_err == 1 )
+		{
+		(void) snprintf( &header[len], header_size - len, " problem=%s;", err_msgs[i] );
+		first_err = 0;
+		}
+	    else
+		{
+	        (void) snprintf( &header[len], header_size - len, "%s;", err_msgs[i] );
+		}
+	    len = strlen( header );
+	    }
+	}
+    
+    first_err = 1;
+    for( i = 0; i < num_errs; i++ )
+	{
+	if ( ( err_msgs[i] != NULL ) && ( strstr( err_msgs[i], "DNSSEC") != NULL ) )
+	    {
+	    if ( first_err == 1 )
+		{
+		(void) snprintf( &header[len], header_size - len,
+				 " x-dnssec=\"fail (%s", err_msgs[i] );
+		first_err = 0;
+		}
+	    else
+		{
+		(void) snprintf( &header[len], header_size - len,
+				 ", %s", err_msgs[i] );
+		}
+	    len = strlen(header);
+	    }
+	}
+
+    if ( first_err == 1 )
+	{
+	if ( ( dnssec_policy == SPFMILTER_DNSSEC_POLICY_IGNORE ) 
+	     || ( cd->result == SPFMILTER_RESULT_NONE ) )
+	    {
+	    (void) snprintf( &header[len], header_size - len,
+			     " x-dnssec=\"none\";" );
+	    len = strlen( header );
+	    }
+	else
+	    {
+	    (void) snprintf( &header[len], header_size - len,
+			     " x-dnssec=\"pass\";" );
+	    len = strlen( header );
+	    }
+	}
+    else
+	{
+	(void) snprintf( &header[len], header_size - len, ")\";" );
+	len = strlen( header );
+	}
+#endif
+
     (void) snprintf( &header[len], header_size - len, " x-software=%s %s %s;", SPFMILTER_PROGRAM, SPFMILTER_VERSION, SPFMILTER_URL );
     }
 
@@ -1749,6 +1921,29 @@
     }
 
 
+#ifdef SUPPORT_DNSSEC
+static const char*
+lib_get_error_msg( lib_data_t* ld )
+    {
+    return lib_get_error( ld );
+    }
+
+
+static const size_t
+lib_get_num_errors( lib_data_t* ld )
+    {
+    return 0;
+    }
+
+
+static const char**
+lib_get_error_msgs( lib_data_t* ld )
+    {
+    return NULL;
+    }
+
+#endif
+
 static void
 lib_fini_message_data( lib_data_t* ld )
     {
@@ -1785,7 +1980,7 @@
 
 #ifdef USE_LIBSPF2
 
-/* Libspf2 data and routines. */
+/* Libspf2 Version 1.0.X and lower versions data and routines. */
 
 
 #include <spf2/spf.h>
@@ -2062,18 +2257,48 @@
 static int
 lib_get_result( lib_data_t* ld )
     {
+    int retval;
     /* Convert libspf2 result to spfmilter result. */
     switch ( ld->output.result )
 	{
-	case SPF_RESULT_PASS: return SPFMILTER_RESULT_PASS;
-	case SPF_RESULT_FAIL: return SPFMILTER_RESULT_FAIL;
-	case SPF_RESULT_SOFTFAIL: return SPFMILTER_RESULT_SOFTFAIL;
-	case SPF_RESULT_NEUTRAL: return SPFMILTER_RESULT_NEUTRAL;
-	case SPF_RESULT_UNKNOWN: return SPFMILTER_RESULT_UNKNOWN;
-	case SPF_RESULT_ERROR: return SPFMILTER_RESULT_ERROR;
-	case SPF_RESULT_NONE: return SPFMILTER_RESULT_NONE;
-	default: return -1;
-	}
+	case SPF_RESULT_PASS:    retval = SPFMILTER_RESULT_PASS;     break;
+	case SPF_RESULT_FAIL:    retval = SPFMILTER_RESULT_FAIL;     break;
+	case SPF_RESULT_SOFTFAIL:retval = SPFMILTER_RESULT_SOFTFAIL; break;
+	case SPF_RESULT_NEUTRAL: retval = SPFMILTER_RESULT_NEUTRAL;  break;
+	case SPF_RESULT_UNKNOWN: retval = SPFMILTER_RESULT_UNKNOWN;  break;
+	case SPF_RESULT_ERROR:   retval = SPFMILTER_RESULT_ERROR;    break;
+	case SPF_RESULT_NONE:    retval = SPFMILTER_RESULT_NONE;     break;
+	default:                 retval = -1;                        break;
+	}
+
+#ifdef SUPPORT_DNSSEC
+        /* Check if there was a DNSSEC validation failure */
+        if ( dnssec_policy == SPFMILTER_DNSSEC_POLICY_REJECT )
+	    {
+	    int i;
+	    int num_errs;
+	    const char **err_msgs;
+
+	    num_errs = lib_get_num_errors( ld );
+	    err_msgs = lib_get_error_msgs( ld );
+
+	    for ( i = 0; i < num_errs; i++ )
+		{
+		if ( err_msgs[i] )
+		    {
+		    if ( strstr( err_msgs[i], "DNSSEC" ) != NULL )
+			{
+			if ( debug )
+			    printf( "spfmilter: DNSSEC validation failure occured.  Rejecting mail.\n" );
+			retval = SPFMILTER_RESULT_FAIL;
+			break;
+			}
+		    }
+		}
+	    }
+#endif
+
+	return retval;
     }
 
 
@@ -2098,6 +2323,29 @@
     }
 
 
+#ifdef SUPPORT_DNSSEC
+static const char*
+lib_get_error_msg( lib_data_t* ld )
+    {
+    return  ld->output.err_msg ;
+    }
+
+
+static const size_t
+lib_get_num_errors( lib_data_t* ld )
+    {
+    return ld->output.num_errs;
+    }
+
+
+static const char**
+lib_get_error_msgs( lib_data_t* ld )
+    {
+    return (const char**) (ld->output.err_msgs);
+    }
+
+#endif
+
 static void
 lib_fini_message_data( lib_data_t* ld )
     {
@@ -2203,7 +2451,20 @@
 	if ( resolvers[r].initialized )
 	    {
 	    SPF_dns_destroy_config_cache( resolvers[r].spfdcid );
-	    SPF_dns_destroy_config_resolv( resolvers[r].spfdcid_r );
+
+#ifdef SUPPORT_DNSSEC
+	    if ( ( dnssec_policy == SPFMILTER_DNSSEC_POLICY_REJECT ) ||
+		 ( dnssec_policy == SPFMILTER_DNSSEC_POLICY_WARN ) )
+		{
+		SPF_dns_destroy_config_sresolv( resolvers[r].spfdcid_r );
+		}
+	    else
+		{
+#endif
+		SPF_dns_destroy_config_resolv( resolvers[r].spfdcid_r );
+#ifdef SUPPORT_DNSSEC
+		}
+#endif
 	    }
     pthread_mutex_destroy( &resolver_mutex );
     }
@@ -2259,7 +2520,19 @@
     if ( ! resolvers[r].initialized )
 	{
 	/* Create the DNS objects. */
-	resolvers[r].spfdcid_r = SPF_dns_create_config_resolv( (SPF_dns_config_t) 0, debug );
+#ifdef SUPPORT_DNSSEC
+	if ( ( dnssec_policy == SPFMILTER_DNSSEC_POLICY_REJECT ) ||
+	     ( dnssec_policy == SPFMILTER_DNSSEC_POLICY_WARN ) )
+	    {
+	    resolvers[r].spfdcid_r = SPF_dns_create_config_sresolv( (SPF_dns_config_t) 0, debug, 1 );
+	    }
+	else
+	    {
+#endif
+	    resolvers[r].spfdcid_r = SPF_dns_create_config_resolv( (SPF_dns_config_t) 0, debug );
+#ifdef SUPPORT_DNSSEC
+	    }
+#endif
 	if ( resolvers[r].spfdcid_r == (SPF_dns_config_t) 0 )
 	    {
 	    syslog( LOG_ERR, "SPF_dns_create_config_resolv() failed" );
@@ -2299,3 +2572,393 @@
     }
 
 #endif /* USE_LIBSPF2 */
+
+
+#ifdef USE_LIBSPF2_1_2_X
+
+/* Libspf2 Version 1.2.X data and routines. */
+
+#include <spf2/spf.h>
+
+static SPF_server_t   *spf_server;
+static SPF_request_t  *spf_localpolicy_requestp;
+static SPF_response_t *spf_localpolicy_responsep;
+static SPF_request_t  *spf_explanation_requestp;
+static SPF_response_t *spf_explanation_responsep;
+
+struct lib_fallback_s {
+    SPF_response_t *responsep;
+    SPF_request_t *requestp;
+};
+
+struct lib_data_s {
+    SPF_server_t *spf_server;
+    char *from;
+    SPF_response_t *responsep;
+    SPF_request_t *requestp;
+    int got_response;
+    char **err_msgs;
+};
+
+static int lib_init( void )
+{
+#ifdef SUPPORT_DNSSEC
+    if ( dnssec_policy == SPFMILTER_DNSSEC_POLICY_IGNORE )
+	{
+#endif
+	spf_server = SPF_server_new(SPF_DNS_CACHE, debug);
+#ifdef SUPPORT_DNSSEC
+	}
+    else
+	{
+	spf_server = SPF_server_new( SPF_DNS_DNSSEC_RESOLV, debug );
+	}
+#endif
+    if (spf_server == NULL)
+	{
+	fprintf( stderr, "%s: SPF_server_new() failed\n", argv0 );
+	return 0;
+	}
+
+    if (localpolicy_str != NULL)
+	{
+	spf_localpolicy_requestp = SPF_request_new (spf_server);
+	spf_localpolicy_responsep = SPF_response_new(spf_localpolicy_requestp);
+	if (SPF_server_set_localpolicy(spf_server, localpolicy_str,
+				       trustedforwarders,
+				       &spf_localpolicy_responsep))
+	    {
+	    fprintf( stderr, "%s: error setting local policy - %s\n", argv0,
+		     localpolicy_str);
+	    return 0;
+	    }
+	}
+
+    if (explanation_str != NULL)
+	{
+	spf_explanation_requestp = SPF_request_new (spf_server);
+	spf_explanation_responsep = SPF_response_new(spf_explanation_requestp);
+	if (SPF_server_set_explanation(spf_server, explanation_str,
+				       &spf_explanation_responsep))
+	    {
+	    fprintf( stderr, "%s: error setting explanation - %s\n", argv0,
+		     explanation_str);
+	    return 0;
+	    }
+	}
+
+    return 1;
+}
+
+static lib_fallback_t* lib_init_fallback( const char* str )
+{
+    lib_fallback_t *lf;
+
+    lf = (lib_fallback_t*) malloc (sizeof(lib_fallback_t));
+    if (lf == NULL)
+	{
+	return NULL;
+	}
+
+    lf->requestp = SPF_request_new(spf_server);
+    lf->responsep = SPF_response_new(lf->requestp);
+
+    if (SPF_server_set_localpolicy(spf_server, str, trustedforwarders,
+				   &lf->responsep))
+	{
+	
+	fprintf( stderr, "%s: error setting fallback - %s\n", argv0,
+		 str);
+	free(lf);
+	return NULL;
+	}
+    
+    return lf;
+}
+
+static int lib_set_local_hostname( lib_data_t* ld )
+{
+    if (SPF_server_set_rec_dom (spf_server, local_hostname))
+	{
+	return 0;
+	}
+    
+    return 1;
+}
+
+static lib_data_t* lib_init_connection_data( void )
+{
+    lib_data_t* ld;
+
+    ld = (lib_data_t*) malloc( sizeof(lib_data_t) );
+    if ( ld == (lib_data_t*) 0 )
+	return (lib_data_t*) 0;
+
+    /* Create the per-connection server object creating a new one */
+#ifdef SUPPORT_DNSSEC
+    if ( dnssec_policy == SPFMILTER_DNSSEC_POLICY_IGNORE )
+	{
+#endif
+	ld->spf_server = SPF_server_new( SPF_DNS_CACHE, debug );
+#ifdef SUPPORT_DNSSEC
+	}
+    else
+	{
+	ld->spf_server = SPF_server_new( SPF_DNS_DNSSEC_RESOLV, debug );
+	}
+#endif
+    ld->from = NULL;
+    ld->got_response = 0;
+    ld->requestp = SPF_request_new(ld->spf_server);
+    ld->responsep = SPF_response_new(ld->requestp);
+    ld->err_msgs = NULL;
+
+    return ld;
+}
+
+static int lib_init_message_data( lib_data_t* ld )
+{
+    ld->from = NULL;
+    return 1;
+}
+
+static int lib_set_ipv4( lib_data_t* ld,
+			 struct in_addr ipv4_addr,
+			 char* ipv4_str )
+{
+    SPF_request_set_ipv4(ld->requestp, ipv4_addr);
+    SPF_request_set_ipv4_str(ld->requestp, ipv4_str);
+    return 1;
+}
+
+static int lib_set_ipv6( lib_data_t* ld,
+			 struct in6_addr ipv6_addr,
+			 char* ipv6_str )
+{
+    SPF_request_set_ipv6(ld->requestp, ipv6_addr);
+    SPF_request_set_ipv6_str(ld->requestp, ipv6_str);
+    return 1;
+}
+
+static int lib_set_helo_hostname( lib_data_t* ld, char* helo_hostname )
+{
+    SPF_request_set_helo_dom(ld->requestp, helo_hostname);
+    return 1;
+}
+
+static int lib_set_from( lib_data_t* ld, const char* from )
+{
+    SPF_request_set_env_from(ld->requestp, from);
+    return 1;
+}
+
+static int lib_do_check( lib_data_t* ld, const char* from )
+{
+    int retval;
+    lib_set_from(ld, from);
+    if ((retval = SPF_request_query_mailfrom(ld->requestp, &ld->responsep))
+	!= SPF_E_SUCCESS)
+	{
+	fprintf(stderr, "Error in lib_do_check(): SPF_request_query_mailfrom() returned %d\n", retval);
+	}
+
+    return 1;
+}
+
+static int lib_do_check_recipient( lib_data_t* ld, const char* to )
+{
+    if(SPF_request_query_rcptto(ld->requestp, &ld->responsep, to)
+	== SPF_E_SUCCESS) {
+	return 1;
+    }
+    else {
+	return 1;
+    }
+}
+
+static int lib_do_check_final( lib_data_t* ld )
+{
+    if (SPF_request_query_mailfrom(ld->requestp, &ld->responsep)
+	== SPF_E_SUCCESS) {
+	return 1;
+    }
+    else {
+	return 1;
+    }
+}
+
+static int lib_get_result( lib_data_t* ld )
+{
+    SPF_result_t res = SPF_response_result(ld->responsep);
+    int retval;
+    /* Convert libspf result to spfmilter result. */
+    switch ( res )
+	{
+	case SPF_RESULT_NEUTRAL:
+	    if (debug)
+		printf("libspf2 returned SPF_RESULT_NEUTRAL\n");
+	    retval = SPFMILTER_RESULT_NEUTRAL;
+	    break;
+
+	case SPF_RESULT_PASS:
+	    if (debug)
+		printf("libspf2 returned SPF_RESULT_PASS\n");
+	    retval = SPFMILTER_RESULT_PASS;
+	    break;
+
+	case SPF_RESULT_FAIL:
+	    if (debug)
+		printf("libspf2 returned SPF_RESULT_FAIL\n");
+	    retval = SPFMILTER_RESULT_FAIL;
+	    break;
+
+	case SPF_RESULT_SOFTFAIL:
+	    if (debug)
+		printf("libspf2 returned SPF_RESULT_SOFTFAIL\n");
+	    retval = SPFMILTER_RESULT_SOFTFAIL;
+	    break;
+
+	case SPF_RESULT_NONE:
+	    if (debug)
+		printf("libspf2 returned SPF_RESULT_NONE\n");
+	    retval = SPFMILTER_RESULT_NONE;
+	    break;
+
+	case SPF_RESULT_TEMPERROR:
+	    if (debug)
+		printf("libspf2 returned SPF_RESULT_TEMPERROR\n");
+	    retval = SPFMILTER_RESULT_ERROR;
+	    break;
+
+	case SPF_RESULT_PERMERROR:
+	    if (debug)
+		printf("libspf2 returned SPF_RESULT_PERMERROR\n");
+	    retval = SPFMILTER_RESULT_UNKNOWN;
+	    break;
+
+	default: retval = -1;
+	}
+
+#ifdef SUPPORT_DNSSEC
+        /* Check if there was a DNSSEC validation failure */
+        if ( dnssec_policy == SPFMILTER_DNSSEC_POLICY_REJECT )
+	    {
+	    int i;
+	    int num_errs;
+
+	    num_errs = lib_get_num_errors( ld );
+	    for ( i = 0; i < num_errs; i++ )
+		{
+		SPF_error_t *err;
+		err = SPF_response_message( ld->responsep, i );
+		if ( err )
+		    {
+		    if ( SPF_error_code( err ) == SPF_E_DNSSEC_FAILURE )
+			{
+			if ( debug )
+			    printf( "spfmilter: DNSSEC validation failure occured.  Rejecting mail.\n" );
+			retval = SPFMILTER_RESULT_FAIL;
+			break;
+			}
+		    }
+		}
+	    }
+#endif
+
+        return retval;
+}
+
+static const char* lib_get_reason( lib_data_t* ld )
+{
+    int spf_reason = SPF_response_reason (ld->responsep);
+    return SPF_strreason (spf_reason);
+}
+
+static const char* lib_get_explanation( lib_data_t* ld )
+{
+    return SPF_response_get_explanation (ld->responsep);
+}
+
+static const char* lib_get_error( lib_data_t* ld )
+{
+    SPF_error_t *err;
+    err = SPF_response_message (ld->responsep, 0);
+    if (err)
+	{
+	return SPF_error_message(err);
+	}
+    else
+	{
+	return NULL;
+	}
+}
+
+static const char* lib_get_error_msg( lib_data_t* ld )
+{
+    return lib_get_error(ld);
+}
+
+static const size_t lib_get_num_errors( lib_data_t* ld )
+{
+    return SPF_response_warnings(ld->responsep);
+}
+
+static const char** lib_get_error_msgs( lib_data_t* ld )
+{
+    int i;
+    int num_errs;
+    char ** err_msgs;
+    
+    num_errs = lib_get_num_errors(ld);
+    err_msgs = (char **) malloc(num_errs * sizeof(char*));
+
+    if (err_msgs == NULL)
+	{
+	return NULL;
+	}
+
+    for (i = 0; i < num_errs; i++)
+	{
+	SPF_error_t *err;
+	char *errmsg = NULL;
+	
+	err = SPF_response_message(ld->responsep, i);
+	if (err)
+	    {
+	    errmsg = (char *)(SPF_error_message (err));
+	    }
+	err_msgs[i] = errmsg;
+	}
+
+    if (ld->err_msgs) free(ld->err_msgs);
+    ld->err_msgs = err_msgs;
+
+    return (const char **) err_msgs;
+}
+
+static void lib_fini_message_data( lib_data_t* ld )
+{
+    free(ld->from);
+}
+
+static void lib_fini_connection_data( lib_data_t* ld )
+{
+    if (ld->err_msgs) free(ld->err_msgs);
+    SPF_response_free (ld->responsep);
+    SPF_request_free (ld->requestp);
+    SPF_server_free(ld->spf_server);
+}
+
+static void lib_fini_fallback( lib_fallback_t* lf )
+{
+    SPF_response_free (lf->responsep);
+    SPF_request_free (lf->requestp);
+    free(lf);
+}
+
+static void lib_fini( void )
+{
+    SPF_server_free(spf_server);
+}
+
+#endif /* USE_LIBSPF2_1_2_X */
