|
@@ -76,6 +76,7 @@ masterLoad(istream& input, const Name& origin, const RRClass& zone_class,
|
|
|
isc_throw(MasterError, "Leading space at line " << line_count);
|
|
|
}
|
|
|
|
|
|
+ // Parse a single RR
|
|
|
istringstream iss(line);
|
|
|
string owner_txt, ttl_txt, rrclass_txt, rrtype_txt;
|
|
|
stringbuf rdatabuf;
|
|
@@ -92,7 +93,15 @@ masterLoad(istream& input, const Name& origin, const RRClass& zone_class,
|
|
|
<< line_count);
|
|
|
}
|
|
|
|
|
|
- // XXX: this part is a bit tricky (and less efficient).
|
|
|
+ // XXX: this part is a bit tricky (and less efficient). We are going
|
|
|
+ // to validate the text for the RR parameters, and throw an exception
|
|
|
+ // if any of them is invalid by converting an underlying exception
|
|
|
+ // to MasterError. To do that, we need to define the corresponding
|
|
|
+ // variables used for RRset construction outside the try-catch block,
|
|
|
+ // but we don't like to use a temporary variable with a meaningless
|
|
|
+ // initial value. So we define pointers outside the try block
|
|
|
+ // and allocate/initialize the actual objects within the block.
|
|
|
+ // To make it exception safe we use Boost.scoped_ptr.
|
|
|
scoped_ptr<const Name> owner;
|
|
|
scoped_ptr<const RRTTL> ttl;
|
|
|
scoped_ptr<const RRClass> rrclass;
|
|
@@ -109,6 +118,9 @@ masterLoad(istream& input, const Name& origin, const RRClass& zone_class,
|
|
|
<< ": " << ex.what());
|
|
|
}
|
|
|
|
|
|
+ // Origin related validation:
|
|
|
+ // - reject out-of-zone data
|
|
|
+ // - reject SOA whose owner is not at the top of zone
|
|
|
const NameComparisonResult cmp_result = owner->compare(origin);
|
|
|
if (cmp_result.getRelation() != NameComparisonResult::EQUAL &&
|
|
|
cmp_result.getRelation() != NameComparisonResult::SUBDOMAIN) {
|
|
@@ -120,14 +132,19 @@ masterLoad(istream& input, const Name& origin, const RRClass& zone_class,
|
|
|
<< line_count);
|
|
|
}
|
|
|
|
|
|
+ // Reject RR class mismatching
|
|
|
if (*rrclass != zone_class) {
|
|
|
isc_throw(MasterError, "RR class (" << rrclass_txt
|
|
|
<< ") does not match the zone class (" << zone_class
|
|
|
<< ") at line " << line_count);
|
|
|
}
|
|
|
|
|
|
+ // Everything is okay. Now create/update RRset with the new RR.
|
|
|
+ // If this is the first RR or the RR type/name is new, we are seeing
|
|
|
+ // a new RRset.
|
|
|
if (!prev_rrset || prev_rrset->getType() != *rrtype ||
|
|
|
prev_rrset->getName() != *owner) {
|
|
|
+ // Commit the previous RRset, if any.
|
|
|
if (rrset) {
|
|
|
callback(rrset);
|
|
|
}
|
|
@@ -137,6 +154,7 @@ masterLoad(istream& input, const Name& origin, const RRClass& zone_class,
|
|
|
prev_rrset = rrset;
|
|
|
} while (++line_count, !input.eof());
|
|
|
|
|
|
+ // Commit the last RRset, if any.
|
|
|
if (rrset) {
|
|
|
callback(rrset);
|
|
|
}
|