const Name name(name_string.beg, name_string.len,
&zone_origin_);
- // TODO: Some more flexibility. We don't allow omitting
- // anything yet
+
+ // Find TTL, class and type. Both TTL and class are
+ // optional and may occur in any order if they exist. TTL
+ // and class come before type which must exist.
+ //
+ // [<TTL>] [<class>] <type> <RDATA>
+ // [<class>] [<TTL>] <type> <RDATA>
// The parameters
MasterToken rrparam_token = lexer_.getNextToken();
+ boost::scoped_ptr<RRClass> rrclass;
+ try {
+ rrclass.reset(new RRClass(rrparam_token.getString()));
+ rrparam_token = lexer_.getNextToken();
+ } catch (InvalidRRClass& e) {
+ // If it's not an rrclass here, continue and try again
+ // after the TTL below.
+ }
+
bool explicit_ttl = false;
if (rrparam_token.getType() == MasterToken::STRING) {
// Try TTL
}
}
- const RRClass rrclass(rrparam_token.getString());
+ if (!rrclass) {
+ try {
+ rrclass.reset(new RRClass(rrparam_token.getString()));
+ rrparam_token = lexer_.getNextToken();
+ } catch (InvalidRRClass& e) {
+ // If it's not an rrclass here, use the zone's class.
+ rrclass.reset(new RRClass(zone_class_));
+ }
+ }
+
+ // Return the last token
+ lexer_.ungetToken();
+
const RRType rrtype(getString());
// TODO: Some more validation?
- if (rrclass != zone_class_) {
+ if (*rrclass != zone_class_) {
// It doesn't really matter much what type of exception
// we throw, we catch it just below.
- isc_throw(isc::BadValue, "Class mismatch: " << rrclass <<
+ isc_throw(isc::BadValue, "Class mismatch: " << *rrclass <<
"vs. " << zone_class_);
}
// TODO: Check if it is SOA, it should be at the origin.
- const rdata::RdataPtr rdata(rdata::createRdata(rrtype, rrclass,
+ const rdata::RdataPtr rdata(rdata::createRdata(rrtype, *rrclass,
lexer_,
&zone_origin_,
options_,
// callbacks_ already. We need to decide if we want to continue
// or not.
if (rdata) {
- add_callback_(name, rrclass, rrtype,
+ add_callback_(name, *rrclass, rrtype,
getCurrentTTL(explicit_ttl, rrtype, rdata),
rdata);
checkCallbackMessage(warnings_.at(0), "using RFC1035 TTL semantics", 2);
}
+TEST_F(MasterLoaderTest, ttlClassTypeOrder) {
+ // We test the order and lack of TTL, class and type. Both TTL and
+ // class are optional and may occur in any order if they exist. TTL
+ // and class come before type which must exist.
+ //
+ // [<TTL>] [<class>] <type> <RDATA>
+ // [<class>] [<TTL>] <type> <RDATA>
+
+ stringstream zone_stream;
+ // <TTL> <class> <type> <RDATA>
+ zone_stream << "a.example.org. 1800 IN A 192.0.2.1\n";
+ // <type> <RDATA>
+ zone_stream << "b.example.org. A 192.0.2.2\n";
+ // <class> <TTL> <type> <RDATA>
+ zone_stream << "c.example.org. IN 3600 A 192.0.2.3\n";
+ // <TTL> <type> <RDATA>
+ zone_stream << "d.example.org. 7200 A 192.0.2.4\n";
+ // <class> <type> <RDATA>
+ zone_stream << "e.example.org. IN A 192.0.2.5\n";
+
+ setLoader(zone_stream, Name("example.org."), RRClass::IN(),
+ MasterLoader::DEFAULT);
+ loader_->load();
+ EXPECT_TRUE(loader_->loadedSucessfully());
+ checkRR("a.example.org", RRType::A(), "192.0.2.1", RRTTL(1800));
+ checkRR("b.example.org", RRType::A(), "192.0.2.2", RRTTL(1800));
+ checkRR("c.example.org", RRType::A(), "192.0.2.3", RRTTL(3600));
+ checkRR("d.example.org", RRType::A(), "192.0.2.4", RRTTL(7200));
+ checkRR("e.example.org", RRType::A(), "192.0.2.5", RRTTL(7200));
+
+ EXPECT_EQ(1, warnings_.size());
+ checkCallbackMessage(warnings_.at(0), "using RFC1035 TTL semantics", 2);
+}
+
TEST_F(MasterLoaderTest, ttlFromPreviousSOA) {
// Mixture of the previous two cases: SOA has explicit TTL, followed by
// an RR without an explicit TTL. In this case the minimum TTL won't be