[svn] commit: r2493 - in /branches/trac232/src/lib: datasrc/sqlite3_datasrc.cc datasrc/sqlite3_datasrc.h datasrc/tests/sqlite3_unittest.cc dns/rrset.cc dns/tests/rrset_unittest.cc
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Jul 12 13:28:21 UTC 2010
Author: jelte
Date: Mon Jul 12 13:28:21 2010
New Revision: 2493
Log:
execute dynamic update (prereqs recognized but not checked yet)
had to hack libdns++ a little to allow for empty rrsets
currently only present in sqlite3 datasrc, but is probably general enough to move to base datasource.
Modified:
branches/trac232/src/lib/datasrc/sqlite3_datasrc.cc
branches/trac232/src/lib/datasrc/sqlite3_datasrc.h
branches/trac232/src/lib/datasrc/tests/sqlite3_unittest.cc
branches/trac232/src/lib/dns/rrset.cc
branches/trac232/src/lib/dns/tests/rrset_unittest.cc
Modified: branches/trac232/src/lib/datasrc/sqlite3_datasrc.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/sqlite3_datasrc.cc (original)
+++ branches/trac232/src/lib/datasrc/sqlite3_datasrc.cc Mon Jul 12 13:28:21 2010
@@ -1262,6 +1262,104 @@
}
}
-
-}
-}
+DataSrc::Result
+Sqlite3DataSrc::doUpdate(DataSrcTransaction& transaction UNUSED_PARAM,
+ isc::dns::Message& msg UNUSED_PARAM) {
+ if (msg.getOpcode() != isc::dns::Opcode::UPDATE()) {
+ return ERROR;
+ }
+
+ std::cout << "[XX] doUpdate(), message: " << std::endl;
+ std::cout << msg.toText() << std::endl;
+
+ // hmz, zone already in transaction. should we do transaction here?
+ // (and not as an argument) for now, simply check it
+ if (msg.getRRCount(isc::dns::Section::QUESTION()) != 1) {
+ return ERROR;
+ }
+ QuestionPtr question = *(msg.beginQuestion());
+ if (question->getName() != transaction.getZoneName()) {
+ return ERROR;
+ }
+ if (question->getType() != isc::dns::RRType::SOA()) {
+ return ERROR;
+ }
+
+ // check the prerequisites
+ RRsetIterator it;
+ for (it = msg.beginSection(isc::dns::Section::ANSWER());
+ it != msg.endSection(isc::dns::Section::ANSWER());
+ it++) {
+ RRsetPtr cur_prereq = *it;
+ cout << "[XX] PREREQ: " << cur_prereq->toText() << endl;
+ // should we check TTL too?
+ // zone class checked for IN right now, should be matched to actual zone class
+ if (cur_prereq->getRdataCount() == 0 &&
+ cur_prereq->getClass() == isc::dns::RRClass::IN() &&
+ cur_prereq->getType() != isc::dns::RRType::ANY()) {
+ // RRset Exists, value independent prerequisite (2.4.1)
+ cout << "[XX] rrset exists (value independent)" << endl;
+ } else if (cur_prereq->getRdataCount() > 0 &&
+ cur_prereq->getClass() == isc::dns::RRClass::IN() &&
+ cur_prereq->getType() != isc::dns::RRType::ANY()) {
+ // RRset Exists, value dependent prerequisite (2.4.2)
+ cout << "[XX] rrset exists (value dependent)" << endl;
+ } else if (cur_prereq->getRdataCount() == 0 &&
+ cur_prereq->getClass() == isc::dns::RRClass::NONE() &&
+ cur_prereq->getType() != isc::dns::RRType::ANY()) {
+ // RRset does not exist, value independent prerequisite (2.4.3)
+ cout << "[XX] rrset does not exist" << endl;
+ } else if (cur_prereq->getRdataCount() == 0 &&
+ cur_prereq->getClass() == isc::dns::RRClass::ANY() &&
+ cur_prereq->getType() == isc::dns::RRType::ANY()) {
+ // Name is in use (2.4.4)
+ cout << "[XX] name is in use" << endl;
+ } else if (cur_prereq->getRdataCount() == 0 &&
+ cur_prereq->getClass() == isc::dns::RRClass::NONE() &&
+ cur_prereq->getType() == isc::dns::RRType::ANY()) {
+ // Name is not in use (2.4.5)
+ cout << "[XX] name is not in use" << endl;
+ }
+ }
+
+ for (it = msg.beginSection(isc::dns::Section::AUTHORITY());
+ it != msg.endSection(isc::dns::Section::AUTHORITY());
+ it++) {
+ RRsetPtr cur_update = *it;
+ std::cout << "[XX] Update RR: " << cur_update->toText() << std::endl;
+ if (cur_update->getRdataCount() > 0 &&
+ cur_update->getClass() == isc::dns::RRClass::IN() &&
+ cur_update->getType() != isc::dns::RRType::ANY()) {
+ // add to rrset (2.5.1)
+ cout << "[XX] add to rrset" << endl;
+ addRRset(transaction, cur_update);
+ } else if (cur_update->getRdataCount() == 0 &&
+ cur_update->getClass() == isc::dns::RRClass::ANY() &&
+ cur_update->getType() != isc::dns::RRType::ANY()) {
+ // delete rrset (2.5.2)
+ cout << "[XX] delete rrset" << endl;
+ delRRset(transaction, cur_update);
+ } else if (cur_update->getRdataCount() == 0 &&
+ cur_update->getClass() == isc::dns::RRClass::ANY() &&
+ cur_update->getType() == isc::dns::RRType::ANY()) {
+ // delete all rrsets for name (2.5.3)
+ cout << "[XX] delete all rrsets for name" << endl;
+ delRRset(transaction, cur_update);
+ } else if (cur_update->getRdataCount() > 0 &&
+ cur_update->getClass() == isc::dns::RRClass::NONE() &&
+ cur_update->getType() != isc::dns::RRType::ANY()) {
+ // delete from rrset (2.5.4)
+ cout << "[XX] delete rr from rrset" << endl;
+ delRRset(transaction, cur_update);
+ }
+ //(*it)++;
+ }
+
+ // do we need to do anything with additional?
+
+ return SUCCESS;
+}
+
+
+}
+}
Modified: branches/trac232/src/lib/datasrc/sqlite3_datasrc.h
==============================================================================
--- branches/trac232/src/lib/datasrc/sqlite3_datasrc.h (original)
+++ branches/trac232/src/lib/datasrc/sqlite3_datasrc.h Mon Jul 12 13:28:21 2010
@@ -124,6 +124,8 @@
DataSrc::Result doIXFR(DataSrcTransaction& transaction,
const isc::dns::RRsetIterator start,
const isc::dns::RRsetIterator end);
+ DataSrc::Result doUpdate(DataSrcTransaction& transaction,
+ isc::dns::Message& msg);
private:
DataSrc::Result addRR(int zone_id,
Modified: branches/trac232/src/lib/datasrc/tests/sqlite3_unittest.cc
==============================================================================
--- branches/trac232/src/lib/datasrc/tests/sqlite3_unittest.cc (original)
+++ branches/trac232/src/lib/datasrc/tests/sqlite3_unittest.cc Mon Jul 12 13:28:21 2010
@@ -1249,13 +1249,27 @@
{
RRsetList result_sets;
uint32_t find_flags;
-
+
EXPECT_EQ(DataSrc::SUCCESS,
data_source.findRRset(name, rrclass, rrtype,
result_sets, find_flags, &zone_name));
- EXPECT_EQ(DataSrc::SUCCESS, find_flags);
- EXPECT_EQ(1, result_sets.size());
- EXPECT_EQ(expected, (*result_sets.begin())->toText());
+
+ if (result_sets.size() > 0) {
+ std::cout << "[XX] checkSingleRRset: " << (*result_sets.begin())->toText() << std::endl;
+ }
+
+ //EXPECT_EQ(DataSrc::SUCCESS, find_flags);
+ if (expected == "") {
+ // noerror/nodata gives an rdatalen=0 rrset back?
+ if (result_sets.size() == 1) {
+ EXPECT_EQ(0, (*result_sets.begin())->getRdataCount());
+ } else {
+ EXPECT_EQ(0, result_sets.size());
+ }
+ } else {
+ EXPECT_EQ(1, result_sets.size());
+ EXPECT_EQ(expected, (*result_sets.begin())->toText());
+ }
}
TEST_F(Sqlite3DataSourceTest, ixfr_ok) {
@@ -1335,4 +1349,125 @@
}
-}
+TEST_F(Sqlite3DataSourceTest, dynamic_update) {
+ // reset database
+ ASSERT_EQ(0, install_writable_database());
+
+ // use our copied writable datasource db
+ ASSERT_EQ(DataSrc::SUCCESS, data_source.close());
+ ASSERT_EQ(DataSrc::SUCCESS, data_source.init(SQLITE_DBFILE_WRITE));
+
+ Message update_msg(Message::RENDER);
+
+ DataSrcTransaction transaction1(&data_source, zone_name);
+ data_source.startTransaction(transaction1);
+ update_msg.setQid(1234);
+
+ // bad qtype
+ update_msg.setOpcode(isc::dns::Opcode::QUERY());
+ ASSERT_EQ(DataSrc::ERROR, data_source.doUpdate(transaction1, update_msg));
+
+ update_msg.setOpcode(isc::dns::Opcode::UPDATE());
+
+ // no/bad question section
+ ASSERT_EQ(DataSrc::ERROR, data_source.doUpdate(transaction1, update_msg));
+
+ QuestionPtr bad_question(new Question(Name("example.com"), RRClass::CH(), RRType::A()));
+ update_msg.addQuestion(bad_question);
+ ASSERT_EQ(DataSrc::ERROR, data_source.doUpdate(transaction1, update_msg));
+
+ // removeQuestion not implemented, reset msg
+ update_msg.clear(Message::RENDER);
+ update_msg.setQid(1234);
+ update_msg.setOpcode(isc::dns::Opcode::UPDATE());
+ QuestionPtr question(new Question(Name("example.com"), RRClass::IN(), RRType::SOA()));
+ update_msg.addQuestion(question);
+
+ // checks, we delete one set, one name, one rr, add a set, and add to a set
+ // delete ip46 A rrset
+ // delete all from www.example.com
+ // delete 1 mx record
+ // add newaddr.example.com 192.0.2.21
+ // add dns04.example.com
+
+ // check if they are (not) there first
+ checkSingleRRset(data_source,
+ "ip46.example.com. 3600 IN A 192.0.2.1\n",
+ Name("ip46.example.com"), RRClass::IN(), RRType::A());
+ checkSingleRRset(data_source,
+ "www.example.com. 3600 IN A 192.0.2.1\n",
+ www_name, RRClass::IN(), RRType::A());
+ checkSingleRRset(data_source,
+ "example.com. 3600 IN MX 10 mail.example.com.\n"
+ "example.com. 3600 IN MX 20 mail.subzone.example.com.\n",
+ Name("example.com"), RRClass::IN(), RRType::MX());
+ checkSingleRRset(data_source,
+ "",
+ Name("newaddr.example.com"), RRClass::IN(), RRType::A());
+ checkSingleRRset(data_source,
+ "example.com. 3600 IN NS dns01.example.com.\n"
+ "example.com. 3600 IN NS dns02.example.com.\n"
+ "example.com. 3600 IN NS dns03.example.com.\n"
+ ,
+ Name("example.com"), RRClass::IN(), RRType::NS());
+
+ RRsetPtr delete_a_record(new RRset(Name("ip46.example.com."),
+ RRClass::ANY(),
+ RRType::A(),
+ RRTTL(3600)));
+ //delete_a_record->addRdata(createRdata(RRType::A(), RRClass::IN(), "192.0.3.1"));
+ update_msg.addRRset(Section::AUTHORITY(), delete_a_record, false);
+
+ RRsetPtr delete_all_www(new RRset(Name("www.example.com."),
+ RRClass::ANY(),
+ RRType::ANY(),
+ RRTTL(0)));
+ update_msg.addRRset(Section::AUTHORITY(), delete_all_www, false);
+
+ RRsetPtr delete_mx_rr(new RRset(Name("example.com."),
+ RRClass::NONE(),
+ RRType::MX(),
+ RRTTL(0)));
+ delete_mx_rr->addRdata(createRdata(RRType::MX(), RRClass::IN(), "10 mail.example.com."));
+ update_msg.addRRset(Section::AUTHORITY(), delete_mx_rr, false);
+
+ RRsetPtr add_newaddr_rr(new RRset(Name("newaddr.example.com."),
+ RRClass::IN(),
+ RRType::A(),
+ RRTTL(3600)));
+ add_newaddr_rr->addRdata(createRdata(RRType::A(), RRClass::IN(), "192.0.2.12"));
+ update_msg.addRRset(Section::AUTHORITY(), add_newaddr_rr, false);
+
+ RRsetPtr add_ns_rr(new RRset(Name("example.com."),
+ RRClass::IN(),
+ RRType::NS(),
+ RRTTL(3600)));
+ add_ns_rr->addRdata(createRdata(RRType::NS(), RRClass::IN(), "dns04.example.com."));
+ update_msg.addRRset(Section::AUTHORITY(), add_ns_rr, false);
+
+ ASSERT_EQ(DataSrc::SUCCESS, data_source.doUpdate(transaction1, update_msg));
+
+ data_source.commitTransaction(transaction1);
+ checkSingleRRset(data_source,
+ "",
+ Name("ip46.example.com"), RRClass::IN(), RRType::A());
+ checkSingleRRset(data_source,
+ "",
+ www_name, RRClass::IN(), RRType::A());
+ checkSingleRRset(data_source,
+ "example.com. 3600 IN MX 20 mail.subzone.example.com.\n",
+ Name("example.com"), RRClass::IN(), RRType::MX());
+ checkSingleRRset(data_source,
+ "newaddr.example.com. 3600 IN A 192.0.2.12\n",
+ Name("newaddr.example.com"), RRClass::IN(), RRType::A());
+ checkSingleRRset(data_source,
+ "example.com. 3600 IN NS dns01.example.com.\n"
+ "example.com. 3600 IN NS dns02.example.com.\n"
+ "example.com. 3600 IN NS dns03.example.com.\n"
+ "example.com. 3600 IN NS dns04.example.com.\n"
+ ,
+ Name("example.com"), RRClass::IN(), RRType::NS());
+
+}
+
+}
Modified: branches/trac232/src/lib/dns/rrset.cc
==============================================================================
--- branches/trac232/src/lib/dns/rrset.cc (original)
+++ branches/trac232/src/lib/dns/rrset.cc Mon Jul 12 13:28:21 2010
@@ -48,7 +48,12 @@
it->first();
if (it->isLast()) {
- isc_throw(EmptyRRset, "ToText() is attempted for an empty RRset");
+ //isc_throw(EmptyRRset, "ToText() is attempted for an empty RRset");
+ // empty rrsets are possible in Update messages
+ s += getName().toText() + " " + getTTL().toText() + " " +
+ getClass().toText() + " " + getType().toText() + " " +
+ "\n";
+ return (s);
}
do {
@@ -71,7 +76,14 @@
it->first();
if (it->isLast()) {
- isc_throw(EmptyRRset, "ToWire() is attempted for an empty RRset");
+ //isc_throw(EmptyRRset, "ToWire() is attempted for an empty RRset");
+ // empty rrsets are possible in update messages (on wire 0 rdata length)
+ rrset.getName().toWire(output);
+ rrset.getType().toWire(output);
+ rrset.getClass().toWire(output);
+ rrset.getTTL().toWire(output);
+ output.writeUint16At(output.getLength(), 0);
+ return (1);
}
// sort the set of Rdata based on rrset-order and sortlist, and possible
Modified: branches/trac232/src/lib/dns/tests/rrset_unittest.cc
==============================================================================
--- branches/trac232/src/lib/dns/tests/rrset_unittest.cc (original)
+++ branches/trac232/src/lib/dns/tests/rrset_unittest.cc Mon Jul 12 13:28:21 2010
@@ -194,7 +194,7 @@
rrset_a.toText());
// toText() cannot be performed for an empty RRset.
- EXPECT_THROW(rrset_a_empty.toText(), EmptyRRset);
+ //EXPECT_THROW(rrset_a_empty.toText(), EmptyRRset);
}
TEST_F(RRsetTest, toWireBuffer)
@@ -206,8 +206,8 @@
buffer.getLength(), &wiredata[0], wiredata.size());
// toWire() cannot be performed for an empty RRset.
- buffer.clear();
- EXPECT_THROW(rrset_a_empty.toWire(buffer), EmptyRRset);
+ //buffer.clear();
+ //EXPECT_THROW(rrset_a_empty.toWire(buffer), EmptyRRset);
}
TEST_F(RRsetTest, toWireRenderer)
@@ -222,8 +222,8 @@
buffer.getLength(), &wiredata[0], wiredata.size());
// toWire() cannot be performed for an empty RRset.
- renderer.clear();
- EXPECT_THROW(rrset_a_empty.toWire(renderer), EmptyRRset);
+ //renderer.clear();
+ //EXPECT_THROW(rrset_a_empty.toWire(renderer), EmptyRRset);
}
// test operator<<. We simply confirm it appends the result of toText().
More information about the bind10-changes
mailing list