From: Mukund Sivaraman Date: Mon, 3 Feb 2014 08:10:13 +0000 (+0530) Subject: [2430] Support nibble mode with $GENERATE X-Git-Tag: bind10-1.2.0beta1-release~50^2~18 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=79c9b75382ddd24872d3eb4b23a354c24cb04087;p=thirdparty%2Fkea.git [2430] Support nibble mode with $GENERATE --- diff --git a/src/lib/dns/master_loader.cc b/src/lib/dns/master_loader.cc index 91fa41b03d..9a8d68858d 100644 --- a/src/lib/dns/master_loader.cc +++ b/src/lib/dns/master_loader.cc @@ -444,6 +444,39 @@ public: size_t rr_count_; // number of RRs successfully loaded }; +namespace { // begin unnamed namespace + +std::string +genNibbles(int i, unsigned int width, bool uppercase) { + static const char *hex = "0123456789abcdef0123456789ABCDEF"; + std::string rstr; + + do { + char ch = hex[(i & 0x0f) + (uppercase ? 16 : 0)]; + i >>= 4; + rstr.push_back(ch); + + if (width > 0) { + --width; + } + + // If width is non zero then we need to add a label seperator. + // If value is non zero then we need to add another label and + // that requires a label seperator. + if (width > 0 || i != 0) { + rstr.push_back('.'); + + if (width > 0) { + --width; + } + } + } while ((i != 0) || (width > 0)); + + return (rstr); +} + +} // end unnamed namespace + std::string MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, const int i) @@ -484,8 +517,7 @@ MasterLoader::MasterLoaderImpl::generateForIter(const std::string& str, case 3: if ((mode[0] == 'n') || (mode[0] == 'N')) { - // TODO: Handle nibble mode - assert(true); + rstr += genNibbles(i + delta, width, (mode[0] == 'N')); } else { const std::string fmt = boost::str(boost::format("%%0%u%c") % width % mode[0]); @@ -592,9 +624,11 @@ MasterLoader::MasterLoaderImpl::doGenerate() { return; } - const size_t name_length = generated_name.size(); - last_name_.reset(new Name(generated_name.c_str(), name_length, - &active_origin_)); + // generateForIter() can return a string with a trailing '.' in + // case of a nibble representation. So we cannot use the + // relative Name constructor. + last_name_.reset + (new Name(Name(generated_name).concatenate(active_origin_))); previous_name_ = true; const rdata::RdataPtr rdata = diff --git a/src/lib/dns/tests/master_loader_unittest.cc b/src/lib/dns/tests/master_loader_unittest.cc index 1bbfde7437..037564b64e 100644 --- a/src/lib/dns/tests/master_loader_unittest.cc +++ b/src/lib/dns/tests/master_loader_unittest.cc @@ -514,6 +514,15 @@ TEST_F(MasterLoaderTest, generateWithModifiers) { // case. "$GENERATE 42-43 host$ TXT \"Value ${0,4,X}\"\n" "$GENERATE 45-46 host${0,4,o} A 192.0.2.$\n" + // Here, the LHS has a trailing dot (which would result in an + // out-of-zone name), but that should be handled as a relative + // name. + "$GENERATE 90-92 ${0,8,n} A 192.0.2.$\n" + // Here, the LHS has no trailing dot, and results in the same + // number of labels as width=8 above. + "$GENERATE 94-96 ${0,7,n} A 192.0.2.$\n" + // Uppercase nibble + "$GENERATE 98-98 ${0,10,n} A 192.0.2.$\n" // Junk type will not parse and 'd' is assumed. "$GENERATE 100-101 host${0,4,j} A 192.0.2.$\n"; stringstream ss(input); @@ -545,6 +554,16 @@ TEST_F(MasterLoaderTest, generateWithModifiers) { checkRR("host0055.example.org", RRType::A(), "192.0.2.45"); checkRR("host0056.example.org", RRType::A(), "192.0.2.46"); + checkRR("a.5.0.0.example.org", RRType::A(), "192.0.2.90"); + checkRR("b.5.0.0.example.org", RRType::A(), "192.0.2.91"); + checkRR("c.5.0.0.example.org", RRType::A(), "192.0.2.92"); + + checkRR("e.5.0.0.example.org", RRType::A(), "192.0.2.94"); + checkRR("f.5.0.0.example.org", RRType::A(), "192.0.2.95"); + checkRR("0.6.0.0.example.org", RRType::A(), "192.0.2.96"); + + checkRR("2.6.0.0.0.example.org", RRType::A(), "192.0.2.98"); + checkRR("host0100.example.org", RRType::A(), "192.0.2.100"); checkRR("host0101.example.org", RRType::A(), "192.0.2.101"); }