Introduce Denial-of-Existence (DoE) for Nack response.
Note this commit changes how names are stored in the database, compliant
to the canonical order.
Change-Id: I9857aaefc1f7da08ff53eff43c8f8c8bd5443953
Refs: #4152
diff --git a/src/daemon/db-mgr.cpp b/src/daemon/db-mgr.cpp
index b925f2d..5652de2 100644
--- a/src/daemon/db-mgr.cpp
+++ b/src/daemon/db-mgr.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
- * Copyright (c) 2014-2017, Regents of the University of California.
+ * Copyright (c) 2014-2018, Regents of the University of California.
*
* This file is part of NDNS (Named Data Networking Domain Name Service).
* See AUTHORS.md for complete list of NDNS authors and contributors.
@@ -125,6 +125,37 @@
NDNS_LOG_INFO("clear all the data in the database: " << m_dbFile);
}
+
+void
+DbMgr::saveName(const Name& name, sqlite3_stmt* stmt, int iCol, bool isStatic)
+{
+ const Block& wire = name.wireEncode();
+ sqlite3_bind_blob(stmt, iCol, wire.value(), wire.value_size(), isStatic ? SQLITE_STATIC : SQLITE_TRANSIENT);
+}
+
+Name
+DbMgr::restoreName(sqlite3_stmt* stmt, int iCol)
+{
+ Name name;
+
+ const uint8_t* buffer = static_cast<const uint8_t*>(sqlite3_column_blob(stmt, iCol));
+ size_t nBytesLeft = sqlite3_column_bytes(stmt, iCol);
+
+ while (nBytesLeft > 0) {
+ bool hasDecodingSucceeded;
+ name::Component component;
+ std::tie(hasDecodingSucceeded, component) = Block::fromBuffer(buffer, nBytesLeft);
+ if (!hasDecodingSucceeded) {
+ BOOST_THROW_EXCEPTION(Error("Error while decoding name from the database"));
+ }
+ name.append(component);
+ buffer += component.size();
+ nBytesLeft -= component.size();
+ }
+
+ return name;
+}
+
///////////////////////////////////////////////////////////////////////////////////////////////////
// Zone
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -142,8 +173,8 @@
BOOST_THROW_EXCEPTION(PrepareError(sql));
}
- const Block& zoneName = zone.getName().wireEncode();
- sqlite3_bind_blob(stmt, 1, zoneName.wire(), zoneName.size(), SQLITE_STATIC);
+
+ saveName(zone.getName(), stmt, 1);
sqlite3_bind_int(stmt, 2, zone.getTtl().count());
rc = sqlite3_step(stmt);
@@ -233,8 +264,7 @@
BOOST_THROW_EXCEPTION(PrepareError(sql));
}
- const Block& zoneName = zone.getName().wireEncode();
- sqlite3_bind_blob(stmt, 1, zoneName.wire(), zoneName.size(), SQLITE_STATIC);
+ saveName(zone.getName(), stmt, 1);
if (sqlite3_step(stmt) == SQLITE_ROW) {
zone.setId(sqlite3_column_int64(stmt, 0));
@@ -266,8 +296,7 @@
Zone& zone = vec.back();
zone.setId(sqlite3_column_int64(stmt, 0));
zone.setTtl(time::seconds(sqlite3_column_int(stmt, 2)));
- zone.setName(Name(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 1)),
- sqlite3_column_bytes(stmt, 1))));
+ zone.setName(restoreName(stmt, 1));
}
sqlite3_finalize(stmt);
@@ -331,8 +360,7 @@
sqlite3_bind_int64(stmt, 1, rrset.getZone()->getId());
- const Block& label = rrset.getLabel().wireEncode();
- sqlite3_bind_blob(stmt, 2, label.wire(), label.size(), SQLITE_STATIC);
+ saveName(rrset.getLabel(), stmt, 2);
sqlite3_bind_blob(stmt, 3, rrset.getType().wire(), rrset.getType().size(), SQLITE_STATIC);
sqlite3_bind_blob(stmt, 4, rrset.getVersion().wire(), rrset.getVersion().size(), SQLITE_STATIC);
sqlite3_bind_int64(stmt, 5, rrset.getTtl().count());
@@ -374,8 +402,52 @@
sqlite3_bind_int64(stmt, 1, rrset.getZone()->getId());
- const Block& label = rrset.getLabel().wireEncode();
- sqlite3_bind_blob(stmt, 2, label.wire(), label.size(), SQLITE_STATIC);
+ saveName(rrset.getLabel(), stmt, 2);
+ sqlite3_bind_blob(stmt, 3, rrset.getType().wire(), rrset.getType().size(), SQLITE_STATIC);
+
+ if (sqlite3_step(stmt) == SQLITE_ROW) {
+ rrset.setId(sqlite3_column_int64(stmt, 0));
+ rrset.setTtl(time::seconds(sqlite3_column_int64(stmt, 1)));
+ rrset.setVersion(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 2)),
+ sqlite3_column_bytes(stmt, 2)));
+ rrset.setData(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 3)),
+ sqlite3_column_bytes(stmt, 3)));
+ }
+ else {
+ rrset.setId(0);
+ }
+ sqlite3_finalize(stmt);
+
+ return rrset.getId() != 0;
+}
+
+bool
+DbMgr::findLowerBound(Rrset& rrset)
+{
+ if (rrset.getZone() == 0) {
+ BOOST_THROW_EXCEPTION(RrsetError("Rrset has not been assigned to a zone"));
+ }
+
+ if (rrset.getZone()->getId() == 0) {
+ bool isFound = find(*rrset.getZone());
+ if (!isFound) {
+ return false;
+ }
+ }
+
+ sqlite3_stmt* stmt;
+ const char* sql =
+ "SELECT id, ttl, version, data FROM rrsets"
+ " WHERE zone_id=? and label<? and type=? ORDER BY label DESC";
+ int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
+
+ if (rc != SQLITE_OK) {
+ BOOST_THROW_EXCEPTION(PrepareError(sql));
+ }
+
+ sqlite3_bind_int64(stmt, 1, rrset.getZone()->getId());
+
+ saveName(rrset.getLabel(), stmt, 2);
sqlite3_bind_blob(stmt, 3, rrset.getType().wire(), rrset.getType().size(), SQLITE_STATIC);
if (sqlite3_step(stmt) == SQLITE_ROW) {
@@ -406,7 +478,7 @@
std::vector<Rrset> vec;
sqlite3_stmt* stmt;
const char* sql = "SELECT id, ttl, version, data, label, type "
- "FROM rrsets where zone_id=? ";
+ "FROM rrsets where zone_id=? ORDER BY label";
int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
if (rc != SQLITE_OK) {
@@ -424,8 +496,7 @@
sqlite3_column_bytes(stmt, 2)));
rrset.setData(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 3)),
sqlite3_column_bytes(stmt, 3)));
- rrset.setLabel(Name(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 4)),
- sqlite3_column_bytes(stmt, 4))));
+ rrset.setLabel(restoreName(stmt, 4));
rrset.setType(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 5)),
sqlite3_column_bytes(stmt, 5)));
}
@@ -434,6 +505,33 @@
return vec;
}
+void
+DbMgr::removeRrsetsOfZoneByType(Zone& zone, const name::Component& type)
+{
+ if (zone.getId() == 0)
+ find(zone);
+
+ if (zone.getId() == 0)
+ BOOST_THROW_EXCEPTION(RrsetError("Attempting to find all the rrsets with a zone does not in the database"));
+
+ sqlite3_stmt* stmt;
+ const char* sql = "DELETE FROM rrsets WHERE zone_id = ? AND type = ?";
+ int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, 0);
+
+ if (rc != SQLITE_OK) {
+ BOOST_THROW_EXCEPTION(PrepareError(sql));
+ }
+
+ sqlite3_bind_int64(stmt, 1, zone.getId());
+ sqlite3_bind_blob(stmt, 2, type.wire(), type.size(), SQLITE_STATIC);
+
+ rc = sqlite3_step(stmt);
+ if (rc != SQLITE_DONE) {
+ sqlite3_finalize(stmt);
+ BOOST_THROW_EXCEPTION(ExecuteError(sql));
+ }
+ sqlite3_finalize(stmt);
+}
void
DbMgr::remove(Rrset& rrset)