diff options
Diffstat (limited to 'src/lib/dns/zone_checker.cc')
-rw-r--r-- | src/lib/dns/zone_checker.cc | 189 |
1 files changed, 0 insertions, 189 deletions
diff --git a/src/lib/dns/zone_checker.cc b/src/lib/dns/zone_checker.cc deleted file mode 100644 index f0a132ae84..0000000000 --- a/src/lib/dns/zone_checker.cc +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright (C) 2012-2024 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include <config.h> - -#include <dns/zone_checker.h> - -#include <dns/name.h> -#include <dns/rdataclass.h> -#include <dns/rrclass.h> -#include <dns/rrtype.h> -#include <dns/rrset.h> -#include <dns/rrset_collection_base.h> - -#include <boost/lexical_cast.hpp> - -#include <functional> -#include <string> - -using boost::lexical_cast; -using std::string; -namespace ph = std::placeholders; - -namespace isc { -namespace dns { - -namespace { -std::string -zoneText(const Name& zone_name, const RRClass& zone_class) { - return (zone_name.toText(true) + "/" + zone_class.toText()); -} - -void -checkSOA(const Name& zone_name, const RRClass& zone_class, - const RRsetCollectionBase& zone_rrsets, - ZoneCheckerCallbacks& callback) { - ConstRRsetPtr rrset = - zone_rrsets.find(zone_name, zone_class, RRType::SOA()); - size_t count = 0; - if (rrset) { - for (RdataIteratorPtr rit = rrset->getRdataIterator(); - !rit->isLast(); rit->next(), ++count) { - if (dynamic_cast<const rdata::generic::SOA*>(&rit->getCurrent()) == - NULL) { - isc_throw(Unexpected, "Zone checker found bad RDATA in SOA"); - } - } - if (count == 0) { - // this should be an implementation bug, not an operational error. - isc_throw(Unexpected, "Zone checker found an empty SOA RRset"); - } - } - if (count != 1) { - callback.error("zone " + zoneText(zone_name, zone_class) + ": has " + - lexical_cast<string>(count) + " SOA records"); - } -} - -// Check if a target name is beyond zone cut, either due to delegation or -// DNAME. Note that DNAME works on the origin but not on the name itself, -// while delegation works on the name itself (but the NS at the origin is not -// delegation). -ConstRRsetPtr -findZoneCut(const Name& zone_name, const RRClass& zone_class, - const RRsetCollectionBase& zone_rrsets, const Name& target_name) { - const unsigned int origin_count = zone_name.getLabelCount(); - const unsigned int target_count = target_name.getLabelCount(); - assert(origin_count <= target_count); - - for (unsigned int l = origin_count; l <= target_count; ++l) { - const Name& mid_name = (l == target_count) ? target_name : - target_name.split(target_count - l); - - ConstRRsetPtr found; - if (l != origin_count && - (found = zone_rrsets.find(mid_name, zone_class, RRType::NS())) != - NULL) { - return (found); - } - if (l != target_count && - (found = zone_rrsets.find(mid_name, zone_class, RRType::DNAME())) - != NULL) { - return (found); - } - } - return (ConstRRsetPtr()); -} - -// Check if each "in-zone" NS name has an address record, identifying some -// error cases. -void -checkNSNames(const Name& zone_name, const RRClass& zone_class, - const RRsetCollectionBase& zone_rrsets, - ConstRRsetPtr ns_rrset, ZoneCheckerCallbacks& callbacks) { - if (ns_rrset->getRdataCount() == 0) { - // this should be an implementation bug, not an operational error. - isc_throw(Unexpected, "Zone checker found an empty NS RRset"); - } - - for (RdataIteratorPtr rit = ns_rrset->getRdataIterator(); - !rit->isLast(); rit->next()) { - const rdata::generic::NS* ns_data = - dynamic_cast<const rdata::generic::NS*>(&rit->getCurrent()); - if (ns_data == NULL) { - isc_throw(Unexpected, "Zone checker found bad RDATA in NS"); - } - const Name& ns_name = ns_data->getNSName(); - const NameComparisonResult::NameRelation reln = - ns_name.compare(zone_name).getRelation(); - if (reln != NameComparisonResult::EQUAL && - reln != NameComparisonResult::SUBDOMAIN) { - continue; // not in the zone. we can ignore it. - } - - // Check if there's a zone cut between the origin and the NS name. - ConstRRsetPtr cut_rrset = findZoneCut(zone_name, zone_class, - zone_rrsets, ns_name); - if (cut_rrset) { - if (cut_rrset->getType() == RRType::NS()) { - continue; // delegation; making the NS name "out of zone". - } else if (cut_rrset->getType() == RRType::DNAME()) { - callbacks.error("zone " + zoneText(zone_name, zone_class) + - ": NS '" + ns_name.toText(true) + "' is " + - "below a DNAME '" + - cut_rrset->getName().toText(true) + - "' (illegal per RFC6672)"); - continue; - } else { - assert(false); - } - } - if (zone_rrsets.find(ns_name, zone_class, RRType::CNAME()) != NULL) { - callbacks.error("zone " + zoneText(zone_name, zone_class) + - ": NS '" + ns_name.toText(true) + "' is a CNAME " + - "(illegal per RFC2181)"); - continue; - } - if (zone_rrsets.find(ns_name, zone_class, RRType::A()) == NULL && - zone_rrsets.find(ns_name, zone_class, RRType::AAAA()) == NULL) { - callbacks.warn("zone " + zoneText(zone_name, zone_class) + - ": NS has no address records (A or AAAA)"); - } - } -} - -void -checkNS(const Name& zone_name, const RRClass& zone_class, - const RRsetCollectionBase& zone_rrsets, - ZoneCheckerCallbacks& callbacks) { - ConstRRsetPtr rrset = - zone_rrsets.find(zone_name, zone_class, RRType::NS()); - if (rrset == NULL) { - callbacks.error("zone " + zoneText(zone_name, zone_class) + - ": has no NS records"); - return; - } - checkNSNames(zone_name, zone_class, zone_rrsets, rrset, callbacks); -} - -// The following is a simple wrapper of checker callback so checkZone() -// can also remember any critical errors. -void -errorWrapper(const string& reason, const ZoneCheckerCallbacks* callbacks, - bool* had_error) { - *had_error = true; - callbacks->error(reason); -} -} - -bool -checkZone(const Name& zone_name, const RRClass& zone_class, - const RRsetCollectionBase& zone_rrsets, - const ZoneCheckerCallbacks& callbacks) { - bool had_error = false; - ZoneCheckerCallbacks my_callbacks( - std::bind(errorWrapper, ph::_1, &callbacks, &had_error), - std::bind(&ZoneCheckerCallbacks::warn, &callbacks, ph::_1)); - - checkSOA(zone_name, zone_class, zone_rrsets, my_callbacks); - checkNS(zone_name, zone_class, zone_rrsets, my_callbacks); - - return (!had_error); -} - -} // end namespace dns -} // end namespace isc |