|
@@ -171,48 +171,52 @@ Query::addNXDOMAINProof(ZoneFinder& finder, ConstRRsetPtr nsec) {
|
|
|
// is broken, 'nsec3' should be a valid NSEC3 RR. Likewise, the call to
|
|
|
// findNSEC3() in this method should result an FindNSEC3Result that proves
|
|
|
// the Closest Encloser Proof and non existent of matching wildcard.
|
|
|
-// If these assumptions aren't met due to a buggy data source implementation
|
|
|
-// or a broken zone, we'll let underlying libdns++ modules throw an exception,
|
|
|
-// which would result in either an SERVFAIL response or just ignoring the
|
|
|
-// query. We at least prevent a complete crash due to such broken behavior.
|
|
|
+// Firstly, the call to findNSEC3() set the recursive to true in order to
|
|
|
+// get the an NSEC3 RR that matches the closest (provable) encloser and
|
|
|
+// an NSEC3 RR that covers the "next closer" name to the closest encloser.
|
|
|
+// This corresponds to Section 7.2.1 of RFC 5155.
|
|
|
+// Then,construct the wildcard domain, call to findNSEC3() set the recursive
|
|
|
+// to false to get the prove that the wildcard that could have matched QNAME
|
|
|
+// also does not exist.
|
|
|
void
|
|
|
Query::addNSEC3NXDOMAINProof(ZoneFinder& finder) {
|
|
|
// Firstly get the NSEC3 proves for Closest Encloser Proof
|
|
|
+ // See section 7.2.1 of RFC 5155.
|
|
|
const ZoneFinder::FindNSEC3Result fresult1 = finder.findNSEC3(qname_,
|
|
|
true);
|
|
|
- if (fresult1.closest_proof->getRdataCount() == 0) {
|
|
|
- isc_throw(BadNSEC3, "NSEC3 for NXDOMAIN proving that matches the "
|
|
|
+ if (!fresult1.closest_proof) {
|
|
|
+ isc_throw(BadNSEC3, "NSEC3 RR for NXDOMAIN proving that matches the "
|
|
|
"closest encloser is empty.");
|
|
|
}
|
|
|
// Add the NSEC3 proving that matches the closest (provable) encloser.
|
|
|
response_.addRRset(Message::SECTION_AUTHORITY,
|
|
|
boost::const_pointer_cast<AbstractRRset>(
|
|
|
- fresult1.closest_proof),
|
|
|
+ fresult1.closest_proof),
|
|
|
dnssec_);
|
|
|
- // Add the NSEC3 RR that covers the "next closer" name to the closest
|
|
|
- // encloser
|
|
|
- if (fresult1.next_proof) {
|
|
|
- response_.addRRset(Message::SECTION_AUTHORITY,
|
|
|
- boost::const_pointer_cast<AbstractRRset>(
|
|
|
- fresult1.next_proof),
|
|
|
- dnssec_);
|
|
|
+ if (!fresult1.next_proof) {
|
|
|
+ isc_throw(BadNSEC3, "NSEC3 RR for NXDOMAIN proving that covers the "
|
|
|
+ "next closer to the closest encloser is empty.");
|
|
|
}
|
|
|
+ // Add the NSEC3 RR that covers the "next closer" name to the closest
|
|
|
+ // encloser.
|
|
|
+ response_.addRRset(Message::SECTION_AUTHORITY,
|
|
|
+ boost::const_pointer_cast<AbstractRRset>(
|
|
|
+ fresult1.next_proof),
|
|
|
+ dnssec_);
|
|
|
// Next, identify the best possible wildcard name that would match
|
|
|
// the query name. It's the longer common suffix with the qname
|
|
|
- // between the owner or the next domain of the NSEC that proves NXDOMAIN,
|
|
|
- // prefixed by the wildcard label, "*".
|
|
|
- const Name wildname(Name("*").concatenate(qname_.split(1)));
|
|
|
+ // between the owner and the 'matched' domain of the NSEC3 that
|
|
|
+ // proves NXDOMAIN,prefixed by the wildcard label, "*".
|
|
|
+ const Name wildname(Name("*").concatenate(
|
|
|
+ qname_.split(qname_.getLabelCount() - fresult1.closest_labels)));
|
|
|
const ZoneFinder::FindNSEC3Result fresult2 =
|
|
|
finder.findNSEC3(wildname, false);
|
|
|
- if (fresult2.closest_proof->getRdataCount() == 0) {
|
|
|
+ if (!fresult2.closest_proof) {
|
|
|
isc_throw(BadNSEC3, "NSEC3 for NXDOMAIN covering the wildcard "
|
|
|
"RR at the closest encloser is empty.");
|
|
|
}
|
|
|
- // Add the (no-) wildcard proof only when it's different from the NSEC
|
|
|
- // that proves NXDOMAIN; sometimes they can be the same.
|
|
|
- // Note: name comparison is relatively expensive. When we are at the
|
|
|
- // stage of performance optimization, we should consider optimizing this
|
|
|
- // for some optimized data source implementations.
|
|
|
+ // Add the wildcard proof only when it's different from the NSEC3 RR
|
|
|
+ // that covers the "next closer" name to the closest encloser.
|
|
|
if (fresult1.next_proof->getName() != fresult2.closest_proof->getName()) {
|
|
|
response_.addRRset(Message::SECTION_AUTHORITY,
|
|
|
boost::const_pointer_cast<AbstractRRset>(
|