|
@@ -12,6 +12,9 @@
|
|
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
// PERFORMANCE OF THIS SOFTWARE.
|
|
// PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
|
|
|
+#include "rdataset.h"
|
|
|
|
+#include "rdata_serialization.h"
|
|
|
|
+
|
|
#include <exceptions/exceptions.h>
|
|
#include <exceptions/exceptions.h>
|
|
|
|
|
|
#include <dns/rdata.h>
|
|
#include <dns/rdata.h>
|
|
@@ -19,11 +22,10 @@
|
|
#include <dns/rrclass.h>
|
|
#include <dns/rrclass.h>
|
|
#include <dns/rrtype.h>
|
|
#include <dns/rrtype.h>
|
|
#include <dns/rrset.h>
|
|
#include <dns/rrset.h>
|
|
-
|
|
|
|
-#include "rdataset.h"
|
|
|
|
-#include "rdata_serialization.h"
|
|
|
|
|
|
+#include <util/buffer.h>
|
|
|
|
|
|
#include <boost/static_assert.hpp>
|
|
#include <boost/static_assert.hpp>
|
|
|
|
+#include <boost/bind.hpp>
|
|
|
|
|
|
#include <stdint.h>
|
|
#include <stdint.h>
|
|
#include <algorithm>
|
|
#include <algorithm>
|
|
@@ -74,12 +76,16 @@ lowestTTL(const RdataSet* rdataset, ConstRRsetPtr& rrset,
|
|
sig_rrset->getTTL());
|
|
sig_rrset->getTTL());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-}
|
|
|
|
|
|
|
|
-RdataSet*
|
|
|
|
-RdataSet::create(util::MemorySegment& mem_sgmt, RdataEncoder& encoder,
|
|
|
|
- ConstRRsetPtr rrset, ConstRRsetPtr sig_rrset,
|
|
|
|
- const RdataSet* old_rdataset)
|
|
|
|
|
|
+// Do some sanity checks on params of create and substract. Return the
|
|
|
|
+// target rrclass and rrtype (as they are produced as side effect of the
|
|
|
|
+// checks).
|
|
|
|
+//
|
|
|
|
+// The only reason for this function is to reuse common code of the
|
|
|
|
+// methods.
|
|
|
|
+std::pair<RRClass, RRType>
|
|
|
|
+sanityChecks(const ConstRRsetPtr& rrset, const ConstRRsetPtr &sig_rrset,
|
|
|
|
+ const RdataSet *old_rdataset)
|
|
{
|
|
{
|
|
// Check basic validity
|
|
// Check basic validity
|
|
if (!rrset && !sig_rrset) {
|
|
if (!rrset && !sig_rrset) {
|
|
@@ -91,6 +97,9 @@ RdataSet::create(util::MemorySegment& mem_sgmt, RdataEncoder& encoder,
|
|
if (sig_rrset && sig_rrset->getRdataCount() == 0) {
|
|
if (sig_rrset && sig_rrset->getRdataCount() == 0) {
|
|
isc_throw(BadValue, "Empty SIG RRset");
|
|
isc_throw(BadValue, "Empty SIG RRset");
|
|
}
|
|
}
|
|
|
|
+ if (sig_rrset && sig_rrset->getType() != RRType::RRSIG()) {
|
|
|
|
+ isc_throw(BadValue, "SIG RRset doesn't have type RRSIG");
|
|
|
|
+ }
|
|
if (rrset && sig_rrset && rrset->getClass() != sig_rrset->getClass()) {
|
|
if (rrset && sig_rrset && rrset->getClass() != sig_rrset->getClass()) {
|
|
isc_throw(BadValue, "RR class doesn't match between RRset and RRSIG");
|
|
isc_throw(BadValue, "RR class doesn't match between RRset and RRSIG");
|
|
}
|
|
}
|
|
@@ -98,9 +107,45 @@ RdataSet::create(util::MemorySegment& mem_sgmt, RdataEncoder& encoder,
|
|
const RRClass rrclass = rrset ? rrset->getClass() : sig_rrset->getClass();
|
|
const RRClass rrclass = rrset ? rrset->getClass() : sig_rrset->getClass();
|
|
const RRType rrtype = rrset ? rrset->getType() :
|
|
const RRType rrtype = rrset ? rrset->getType() :
|
|
getCoveredType(sig_rrset->getRdataIterator()->getCurrent());
|
|
getCoveredType(sig_rrset->getRdataIterator()->getCurrent());
|
|
|
|
+
|
|
if (old_rdataset && old_rdataset->type != rrtype) {
|
|
if (old_rdataset && old_rdataset->type != rrtype) {
|
|
- isc_throw(BadValue, "RR type doesn't match for merging RdataSet");
|
|
|
|
|
|
+ isc_throw(BadValue, "RR type doesn't match between RdataSets");
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ return (std::pair<RRClass, RRType>(rrclass, rrtype));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+} // Anonymous namespace
|
|
|
|
+
|
|
|
|
+RdataSet*
|
|
|
|
+RdataSet::packSet(util::MemorySegment& mem_sgmt, RdataEncoder& encoder,
|
|
|
|
+ size_t rdata_count, size_t rrsig_count, const RRType& rrtype,
|
|
|
|
+ const RRTTL& rrttl)
|
|
|
|
+{
|
|
|
|
+ const size_t ext_rrsig_count_len =
|
|
|
|
+ rrsig_count >= MANY_RRSIG_COUNT ? sizeof(uint16_t) : 0;
|
|
|
|
+ const size_t data_len = encoder.getStorageLength();
|
|
|
|
+ void* p = mem_sgmt.allocate(sizeof(RdataSet) + ext_rrsig_count_len +
|
|
|
|
+ data_len);
|
|
|
|
+ RdataSet* rdataset = new(p) RdataSet(rrtype, rdata_count, rrsig_count,
|
|
|
|
+ rrttl);
|
|
|
|
+ if (rrsig_count >= RdataSet::MANY_RRSIG_COUNT) {
|
|
|
|
+ *rdataset->getExtSIGCountBuf() = rrsig_count;
|
|
|
|
+ }
|
|
|
|
+ encoder.encode(rdataset->getDataBuf(), data_len);
|
|
|
|
+ return (rdataset);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+RdataSet*
|
|
|
|
+RdataSet::create(util::MemorySegment& mem_sgmt, RdataEncoder& encoder,
|
|
|
|
+ ConstRRsetPtr rrset, ConstRRsetPtr sig_rrset,
|
|
|
|
+ const RdataSet* old_rdataset)
|
|
|
|
+{
|
|
|
|
+ const std::pair<RRClass, RRType>& rrparams =
|
|
|
|
+ sanityChecks(rrset, sig_rrset, old_rdataset);
|
|
|
|
+ const RRClass& rrclass = rrparams.first;
|
|
|
|
+ const RRType& rrtype = rrparams.second;
|
|
|
|
+
|
|
const RRTTL rrttl = lowestTTL(old_rdataset, rrset, sig_rrset);
|
|
const RRTTL rrttl = lowestTTL(old_rdataset, rrset, sig_rrset);
|
|
if (old_rdataset) {
|
|
if (old_rdataset) {
|
|
encoder.start(rrclass, rrtype, old_rdataset->getDataBuf(),
|
|
encoder.start(rrclass, rrtype, old_rdataset->getDataBuf(),
|
|
@@ -148,18 +193,99 @@ RdataSet::create(util::MemorySegment& mem_sgmt, RdataEncoder& encoder,
|
|
<< MAX_RRSIG_COUNT);
|
|
<< MAX_RRSIG_COUNT);
|
|
}
|
|
}
|
|
|
|
|
|
- const size_t ext_rrsig_count_len =
|
|
|
|
- rrsig_count >= MANY_RRSIG_COUNT ? sizeof(uint16_t) : 0;
|
|
|
|
- const size_t data_len = encoder.getStorageLength();
|
|
|
|
- void* p = mem_sgmt.allocate(sizeof(RdataSet) + ext_rrsig_count_len +
|
|
|
|
- data_len);
|
|
|
|
- RdataSet* rdataset = new(p) RdataSet(rrtype, rdata_count, rrsig_count,
|
|
|
|
- rrttl);
|
|
|
|
- if (rrsig_count >= MANY_RRSIG_COUNT) {
|
|
|
|
- *rdataset->getExtSIGCountBuf() = rrsig_count;
|
|
|
|
|
|
+ return (packSet(mem_sgmt, encoder, rdata_count, rrsig_count, rrtype,
|
|
|
|
+ rrttl));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+namespace {
|
|
|
|
+
|
|
|
|
+void writeName(util::OutputBuffer* buffer, const LabelSequence& name,
|
|
|
|
+ RdataNameAttributes)
|
|
|
|
+{
|
|
|
|
+ size_t len;
|
|
|
|
+ const uint8_t* data = name.getData(&len);
|
|
|
|
+ buffer->writeData(data, len);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void writeData(util::OutputBuffer* buffer, const void* data, size_t len) {
|
|
|
|
+ buffer->writeData(data, len);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+size_t subtractIterate(const dns::ConstRRsetPtr& subtract,
|
|
|
|
+ const RRClass& rrclass, const RRType& rrtype,
|
|
|
|
+ boost::function<bool ()> iterator,
|
|
|
|
+ boost::function<void (const Rdata& rdata)> inserter,
|
|
|
|
+ util::OutputBuffer& buffer)
|
|
|
|
+{
|
|
|
|
+ size_t count = 0;
|
|
|
|
+ while (iterator()) {
|
|
|
|
+ util::InputBuffer input(buffer.getData(), buffer.getLength());
|
|
|
|
+ const RdataPtr& rdata(createRdata(rrtype, rrclass, input,
|
|
|
|
+ buffer.getLength()));
|
|
|
|
+ buffer.clear();
|
|
|
|
+
|
|
|
|
+ bool insert = true;
|
|
|
|
+ if (subtract) {
|
|
|
|
+ for (RdataIteratorPtr it = subtract->getRdataIterator();
|
|
|
|
+ !it->isLast(); it->next()) {
|
|
|
|
+ if (rdata->compare(it->getCurrent()) == 0) {
|
|
|
|
+ insert = false;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (insert) {
|
|
|
|
+ inserter(*rdata);
|
|
|
|
+ ++count;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- encoder.encode(rdataset->getDataBuf(), data_len);
|
|
|
|
- return (rdataset);
|
|
|
|
|
|
+ return (count);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+} // Anonymous namespace
|
|
|
|
+
|
|
|
|
+RdataSet*
|
|
|
|
+RdataSet::subtract(util::MemorySegment& mem_sgmt, RdataEncoder& encoder,
|
|
|
|
+ const dns::ConstRRsetPtr& rrset,
|
|
|
|
+ const dns::ConstRRsetPtr& sig_rrset,
|
|
|
|
+ const RdataSet& old_rdataset)
|
|
|
|
+{
|
|
|
|
+ const std::pair<RRClass, RRType>& rrparams =
|
|
|
|
+ sanityChecks(rrset, sig_rrset, &old_rdataset);
|
|
|
|
+ const RRClass& rrclass = rrparams.first;
|
|
|
|
+ const RRType& rrtype = rrparams.second;
|
|
|
|
+
|
|
|
|
+ // Do the encoding
|
|
|
|
+ encoder.start(rrclass, rrtype);
|
|
|
|
+ util::OutputBuffer buffer(1024);
|
|
|
|
+ RdataReader reader(rrclass, rrtype, old_rdataset.getDataBuf(),
|
|
|
|
+ old_rdataset.getRdataCount(),
|
|
|
|
+ old_rdataset.getSigRdataCount(),
|
|
|
|
+ boost::bind(writeName, &buffer, _1, _2),
|
|
|
|
+ boost::bind(writeData, &buffer, _1, _2));
|
|
|
|
+
|
|
|
|
+ // Copy over the Rdata (except for the subtracted)
|
|
|
|
+ const size_t rdata_count =
|
|
|
|
+ subtractIterate(rrset, rrclass, rrtype,
|
|
|
|
+ boost::bind(&RdataReader::iterateRdata, &reader),
|
|
|
|
+ boost::bind(&RdataEncoder::addRdata, &encoder, _1),
|
|
|
|
+ buffer);
|
|
|
|
+ // Copy over the signatures (except for the subtracted)
|
|
|
|
+ const size_t rrsig_count =
|
|
|
|
+ subtractIterate(sig_rrset, rrclass, RRType::RRSIG(),
|
|
|
|
+ boost::bind(&RdataReader::iterateSingleSig, &reader),
|
|
|
|
+ boost::bind(&RdataEncoder::addSIGRdata, &encoder, _1),
|
|
|
|
+ buffer);
|
|
|
|
+
|
|
|
|
+ // Note that we don't need to check for overflow, if it fitted before, it
|
|
|
|
+ // fits after removal of something too.
|
|
|
|
+
|
|
|
|
+ if (rdata_count == 0 && rrsig_count == 0) {
|
|
|
|
+ return (NULL); // It is left empty
|
|
|
|
+ }
|
|
|
|
+ return (packSet(mem_sgmt, encoder, rdata_count, rrsig_count, rrtype,
|
|
|
|
+ restoreTTL(old_rdataset.getTTLData())));
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
void
|