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