diff -U 5 -Nar spfmilter-0.97.orig/configure.ac spfmilter-0.97/configure.ac
--- spfmilter-0.97.orig/configure.ac	2005-04-24 17:02:17.000000000 -0400
+++ spfmilter-0.97/configure.ac	2008-04-25 16:05:17.000000000 -0400
@@ -15,10 +15,80 @@
 AC_TYPE_UID_T
 AC_TYPE_SIZE_T
 
 AC_CHECK_FUNCS([daemon setsid getopt_long])
 
+# Check whether we require support for DNSSEC validation
+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)
+
+   dnl Check the openssl crypto library
+   AC_ARG_WITH(openssl,
+    [  --with-openssl=PATH     Look for openssl in PATH/{lib,include}.],
+    if test "x$withval" != "xyes"; then
+      if test "x$withval" != x -a -d $withval/lib; then
+          LDFLAGS="-L$withval/lib $LDFLAGS"
+      fi
+      if test "x$withval" != x -a -d $withval/include; then
+          CPPFLAGS="-I$withval/include $CPPFLAGS"
+      fi
+    fi
+   )   
+   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-threads, val_resolve_and_check, , [
+	echo "the validator library is required to build this program."
+        echo "see http://dnssec-tools.sourceforge.net"
+	exit 1;
+   ], -lcrypto -lpthread -lsres -L/usr/local/lib)
+
+   AC_DEFINE([SUPPORT_DNSSEC], [1], [Support DNSSEC validation])
+
+else
+   AC_MSG_RESULT(no)
+fi
+
 # Check for both SPF libraries.  If both are present, the .c file will
 # choose one.
 AC_SEARCH_LIBS([SPF_init],[spf])
 AC_SEARCH_LIBS([SPF_create_config],[spf2])
 
diff -U 5 -Nar spfmilter-0.97.orig/spfmilter.c spfmilter-0.97/spfmilter.c
--- spfmilter-0.97.orig/spfmilter.c	2005-06-20 21:28:57.000000000 -0400
+++ spfmilter-0.97/spfmilter.c	2008-04-25 16:15:21.000000000 -0400
@@ -95,10 +95,15 @@
 #define SPFMILTER_ACTION_UNKNOWN 0
 #define SPFMILTER_ACTION_REJECT 1
 #define SPFMILTER_ACTION_MARK 2
 #define SPFMILTER_ACTION_TEMPFAIL 3
 
+#if SUPPORT_DNSSEC
+#define SPFMILTER_DNSSEC_POLICY_IGNORE 0
+#define SPFMILTER_DNSSEC_POLICY_WARN 1
+#define SPFMILTER_DNSSEC_POLICY_REJECT 2
+#endif /* SUPPORT_DNSSEC */
 
 /* Structs. */
 
 
 /* Fallback list. */
@@ -211,10 +216,15 @@
 static int lib_do_check_recipient( lib_data_t* ld, const char* to );
 static int lib_do_check_final( lib_data_t* ld );
 static int lib_get_result( 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 /* SUPPORT_DNSSEC */
 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 );
 static void lib_fini( void );
 
@@ -233,10 +243,14 @@
 static char* local_hostname;
 static int local_hostname_len;
 
 static int header_name_len;
 
+#ifdef SUPPORT_DNSSEC
+static int dnssec_policy;
+#endif /* SUPPORT_DNSSEC */
+
 static struct smfiDesc smfilter = {
     "SPF",				/* filter name */
     SMFI_VERSION,			/* version code -- do not change */
     SMFIF_CHGHDRS|SMFIF_ADDHDRS,	/* flags */
     spf_connect,			/* connection info filter */
@@ -264,20 +278,27 @@
     { "user",			required_argument,	NULL,	'u', },
     { "pidfile",		required_argument,	NULL,	'p', },
     { "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 /* SUPPORT_DNSSEC */
     { 0, 0, 0, 0 },
 };
 #define DOC_LONGOPT(l, v, t, p1) \
     do { \
 	(void) fprintf( stderr, "    --%s%c%s%*s" t "\n", l, (v ? '=' : ' '),  (v ? v : ""), p1, "" ); \
     } while( 0 )
 #else /* HAVE_GETOPT_LONG */
 #define DOC_LONGOPT(l, v, t, p1) do { } while( 0 )
 #endif /* HAVE_GETOPT_LONG */
+#ifdef SUPPORT_DNSSEC
+static const char* shortopts = "l:tg:f:w:re:mu:p:Xhd:s:";
+#else /* SUPPORT_DNSSEC */
 static const char* shortopts = "l:tg:f:w:re:mu:p:Xhd::";
+#endif /* SUPPORT_DNSSEC */
 
 #define DOC_OPT(s, l, v, t, p0, p1) \
     do { \
 	(void) fprintf( stderr, "    -%c%c%s%*s" t "\n", s, (v ? ' ' : ' '), (v ? v : ""), p0, "" ); \
 	DOC_LONGOPT(l, v, t, p1); \
@@ -309,10 +330,13 @@
     markonly = 0;
     user = (char*) 0;
     pidfile = (char*) 0;
     nodaemon = 0;
     debug = 0;
+#ifdef SUPPORT_DNSSEC
+    dnssec_policy = SPFMILTER_DNSSEC_POLICY_IGNORE;
+#endif /* SUPPORT_DNSSEC */
 
     /* Figure out the program's name. */
     argv0 = strrchr( argv[0], '/' );
     if ( argv0 != (char*) 0 )
 	++argv0;
@@ -373,10 +397,28 @@
 		if ( optarg )
 		    debug = atoi( optarg );
 		else
 		    debug = 1;
 		break;
+#ifdef SUPPORT_DNSSEC
+	    case 's':
+	        if ( optarg )
+		    {
+		    if ( strncasecmp( optarg, "ignore", 6 ) == 0 )
+		        dnssec_policy = SPFMILTER_DNSSEC_POLICY_IGNORE;
+		    else if ( strncasecmp( optarg, "warn", 4 ) == 0 )
+		        dnssec_policy = SPFMILTER_DNSSEC_POLICY_WARN;
+		    else if ( strncasecmp( optarg, "reject", 6 ) == 0 )
+		        dnssec_policy = SPFMILTER_DNSSEC_POLICY_REJECT;
+		    else
+			{
+		        (void) fprintf( stderr, "Unrecognized option argument '%s'\n", optarg );
+			exit( 1 );
+			}
+		    }
+		break;
+#endif /* SUPPORT_DNSSEC */
 	    default:
 		(void) fprintf( stderr, "Unrecognised option '%c'\n", c );
 		exit( 1 );
 	    }
 	}
@@ -442,10 +484,13 @@
     DOC_OPT( 'u', "user", "<user|uid>", "Run as specified user or UID.", 10, 16 );
     DOC_OPT( 'p', "pidfile", "<filename>", "Write the process i.d. to the specified file.", 10, 16 );
     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 /* SUPPORT_DNSSEC */
     }
 
 
 static void
 init_fallback( const char* fallback_filename, const char* guess_str )
@@ -1318,10 +1363,16 @@
     {
     connection_data_t* cd;
     const char* exp;
     char exp_escaped[1000];
 
+#ifdef SUPPORT_DNSSEC
+    const char* errmsg;
+    char exp_errmsg[1000];
+    char err_reply[2048];
+#endif /* SUPPORT_DNSSEC */
+
     cd = (connection_data_t*) smfi_getpriv( ctx );
 
     switch ( cd->result )
 	{
 	case SPFMILTER_RESULT_PASS:
@@ -1348,11 +1399,25 @@
 	    syslog( LOG_INFO, "rejecting mail from [%s] - %s", cd->ip_str, result_str( cd->result ) );
 	    if ( exp != (char*) 0 )
 		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 /* SUPPORT_DNSSEC */
 	    smfi_setreply( ctx, "550", "5.7.1", exp_escaped );
+#endif /* SUPPORT_DNSSEC */
 	    fini_message_data( cd );
 	    return SMFIS_REJECT;
 
 	case SPFMILTER_ACTION_TEMPFAIL:
 	    syslog( LOG_INFO, "temporarily failing mail from [%s] - %s", cd->ip_str, lib_get_error( cd->lib_data ) );
@@ -1472,10 +1537,18 @@
 static void
 build_header( connection_data_t* cd, char* header, size_t header_size, const char* reason )
     {
     int len;
 
+#ifdef SUPPORT_DNSSEC
+    int i;
+    char *err_msg;
+    char **err_msgs;
+    size_t num_errs;
+    int first_err;
+#endif /* SUPPORT_DNSSEC */
+
     (void) snprintf( header, header_size, "%s", result_str( cd->result ) );
     len = strlen( header );
     if ( reason != (char*) 0 )
 	{
 	(void) snprintf( &header[len], header_size - len, " (%s)", reason );
@@ -1499,11 +1572,88 @@
     if ( cd->mail_from != (char*) 0 )
 	{
 	(void) snprintf( &header[len], header_size - len, " envelope-from=%s;", cd->mail_from );
 	len = strlen( header );
 	}
+
+#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 );
+	}
+#else /* SUPPORT_DNSSEC */
     /*!!! Do something about the problem= field. */
+#endif /* SUPPORT_DNSSEC */
+
     (void) snprintf( &header[len], header_size - len, " x-software=%s %s %s with %s;", SPFMILTER_PROGRAM, SPFMILTER_VERSION, SPFMILTER_URL, lib_version() );
     }
 
 
 static connection_data_t*
@@ -1841,10 +1991,33 @@
     {
     return ld->peer_info->error;
     }
 
 
+#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 /* SUPPORT_DNSSEC */
+
 static void
 lib_fini_message_data( lib_data_t* ld )
     {
     }
 
@@ -2176,22 +2349,49 @@
 
 
 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;
+	}
+
+#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 )
+			{
+			retval = SPFMILTER_RESULT_FAIL;
+			break;
+			}
+		    }
+		}
+	    }
+#endif /* SUPPORT_DNSSEC */
+    return retval;
     }
 
 
 static const char*
 lib_get_explanation( lib_data_t* ld )
@@ -2204,10 +2404,32 @@
 lib_get_error( lib_data_t* ld )
     {
     return SPF_strerror( ld->output.err );
     }
 
+#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 /* SUPPORT_DNSSEC */
 
 static void
 lib_fini_message_data( lib_data_t* ld )
     {
     if ( ld->from != (char*) 0 )
@@ -2638,10 +2860,36 @@
     /*!!!*/
     return (char*) 0;
     }
 
 
+#ifdef SUPPORT_DNSSEC
+static const char*
+lib_get_error_msg( lib_data_t* ld )
+    {
+    /*!!!*/
+    return (char*) 0;
+    }
+
+
+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 (char**) 0;
+    }
+#endif /* SUPPORT_DNSSEC */
+
+
 static void
 lib_fini_message_data( lib_data_t* ld )
     {
     /*!!!*/
     }
