Fix DNSSEC caching problems: incomplete RRSIG RRsets.
diff --git a/src/cache.c b/src/cache.c
index 66b52d2..9407636 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -460,7 +460,7 @@
     return NULL;
   
   /* First remove any expired entries and entries for the name/address we
-     are currently inserting. Fail is we attempt to delete a name from
+     are currently inserting. Fail if we attempt to delete a name from
      /etc/hosts or DHCP. */
   if (!cache_scan_free(name, addr, now, flags))
     {
diff --git a/src/dnssec.c b/src/dnssec.c
index 8263b3e..b97f47b 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -1168,6 +1168,7 @@
 			       type_covered == T_DNSKEY || type_covered == T_PTR)) 
 			    {
 			      a.addr.dnssec.type = type_covered;
+			      a.addr.dnssec.class = class1;
 			      
 			      algo = *p2++;
 			      p2 += 13; /* labels, orig_ttl, expiration, inception */
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 5515ea5..e0bf47e 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1551,37 +1551,33 @@
 	}
 
 #ifdef HAVE_DNSSEC
-      if (option_bool(OPT_DNSSEC_VALID) && (qtype == T_DNSKEY || qtype == T_DS || qtype == T_RRSIG))
+      if (option_bool(OPT_DNSSEC_VALID) && (qtype == T_DNSKEY || qtype == T_DS))
 	{
-	  int gotone = 0, have_rrsig = 0;
+	  int gotone = 0;
 	  struct blockdata *keydata;
 
 	  /* Do we have RRSIG? Can't do DS or DNSKEY otherwise. */
-	  crecp = NULL;
-	  while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS)))
-	    if (crecp->uid == qclass && (qtype == T_RRSIG || crecp->addr.sig.type_covered == qtype))
-	      {
-		have_rrsig = 1;
-		break;
-	      }
-	  
-	  if (qtype == T_RRSIG && have_rrsig)
+	  if (sec_reqd)
 	    {
-	      ans = gotone = 1;
-	      auth = 0;
-	    }
-	  else if (qtype == T_DS && have_rrsig)
-	    {
-	      auth = 0;
 	      crecp = NULL;
-	      while ((crecp = cache_find_by_name(crecp, name, now, F_DS)))
-		if (crecp->uid == qclass)
-		  {
-		    ans = gotone = 1;
-		    if (!dryrun && (keydata = blockdata_retrieve(crecp->addr.ds.keydata, crecp->addr.ds.keylen, NULL)))
-		      {			     			      
-			struct all_addr a;
-			a.addr.keytag =  crecp->addr.ds.keytag;
+	      while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS)))
+		if (crecp->uid == qclass && crecp->addr.sig.type_covered == qtype)
+		  break;
+	    }
+	  
+	  if (!sec_reqd || crecp)
+	    {
+	      if (qtype == T_DS)
+		{
+		  crecp = NULL;
+		  while ((crecp = cache_find_by_name(crecp, name, now, F_DS)))
+		    if (crecp->uid == qclass)
+		      {
+			gotone = 1;
+			if (!dryrun && (keydata = blockdata_retrieve(crecp->addr.ds.keydata, crecp->addr.ds.keylen, NULL)))
+			  {			     			      
+			    struct all_addr a;
+			    a.addr.keytag =  crecp->addr.ds.keytag;
 			    log_query(F_KEYTAG | (crecp->flags & F_CONFIG), name, &a, "DS keytag %u");
 			    if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
 						    crec_ttl(crecp, now), &nameoffset,
@@ -1589,52 +1585,52 @@
 						    crecp->addr.ds.keytag, crecp->addr.ds.algo, crecp->addr.ds.digest, crecp->addr.ds.keylen, keydata))
 			      anscount++;
 			    
-		      } 
-		  }
-	    }
-	  else if (qtype == T_DNSKEY)
-	    {
-	      crecp = NULL;
-	      while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY)))
-		if (crecp->uid == qclass)
-		  {
-		    if ((crecp->flags & F_CONFIG) || have_rrsig) /* Return configured keys without an RRISG */
+			  } 
+		      }
+		}
+	      else /* DNSKEY */
+		{
+		  crecp = NULL;
+		  while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY)))
+		    if (crecp->uid == qclass)
 		      {
-			if (!(crecp->flags & F_CONFIG))
-			  auth = 0, gotone = 1;
-			ans = 1;
-			if (!dryrun && (keydata = blockdata_retrieve(crecp->addr.key.keydata, crecp->addr.key.keylen, NULL)))
-			  {			     			      
-			    struct all_addr a;
-			    a.addr.keytag =  crecp->addr.key.keytag;
-			    log_query(F_KEYTAG | (crecp->flags & F_CONFIG), name, &a, "DNSKEY keytag %u");
-			    if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
-						    crec_ttl(crecp, now), &nameoffset,
-						    T_DNSKEY, qclass, "sbbt", 
-						    crecp->addr.key.flags, 3, crecp->addr.key.algo, crecp->addr.key.keylen, keydata))
-			      anscount++;
+			if (!(crecp->flags & F_CONFIG)) /* Don't return configured keys - send upstream instead */
+			  {
+			    gotone = 1;
+			    if (!dryrun && (keydata = blockdata_retrieve(crecp->addr.key.keydata, crecp->addr.key.keylen, NULL)))
+			      {			     			      
+				struct all_addr a;
+				a.addr.keytag =  crecp->addr.key.keytag;
+				log_query(F_KEYTAG | (crecp->flags & F_CONFIG), name, &a, "DNSKEY keytag %u");
+				if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
+							crec_ttl(crecp, now), &nameoffset,
+							T_DNSKEY, qclass, "sbbt", 
+							crecp->addr.key.flags, 3, crecp->addr.key.algo, crecp->addr.key.keylen, keydata))
+				  anscount++;
+			      }
 			  }
 		      }
-		  }
+		}
 	    }
-	      
+	  
 	  /* Now do RRSIGs */
 	  if (gotone)
 	    {
-	      crecp = NULL;
-	      while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS)))
-		if (crecp->uid == qclass && (qtype == T_RRSIG || (sec_reqd && crecp->addr.sig.type_covered == qtype)) &&
-		    !dryrun &&
-		    (keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL)))
-		  {
-		    if (qtype == T_RRSIG)
-		      log_query(F_RRNAME, name, NULL, querystr("rrsig", crecp->addr.sig.type_covered));
-		    if ((keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL)) &&
+	      ans = 1;
+	      auth = 0;
+	      if (!dryrun && sec_reqd)
+		{
+		  crecp = NULL;
+		  while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS)))
+		    if (crecp->uid == qclass && crecp->addr.sig.type_covered == qtype &&
+			(keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL)))
+		      {
 			add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
 					    crec_ttl(crecp, now), &nameoffset,
-					    T_RRSIG, qclass, "t", crecp->addr.sig.keylen, keydata))
-		      anscount++;
-		  }
+					    T_RRSIG, qclass, "t", crecp->addr.sig.keylen, keydata);
+			anscount++;
+		      }
+		}
 	    }
 	}
 #endif