BOOST_AUTO_TEST_SUITE(reczones_helpers)
-static const std::array<std::string, 5> hostLines = {
+static const std::array<std::string, 9> hostLines = {
"192.168.0.1 foo bar\n",
"192.168.0.1 dupfoo\n",
"192.168.0.2 baz\n",
"1.1.1.1 fancy\n",
"2.2.2.2 more.fancy\n",
+ "2001:db8::567:89ab foo6 bar6\n",
+ "2001:db8::567:89ab dupfoo6\n",
+ "::1 localhost self\n",
+ "2001:db8::567:89ac some.address.somewhere some some.address\n",
};
struct Fixture
DNSRecord("2.2.2.2.in-addr.arpa", makeLocalhostRootDRC(), QType::SOA),
DNSRecord("2.2.2.2.in-addr.arpa", makePtrDRC("more.fancy."), QType::PTR),
});
+
+ addDomainMapFixtureEntry("foo6", QType::AAAA, "2001:db8::567:89ab");
+ addDomainMapFixtureEntry("bar6", QType::AAAA, "2001:db8::567:89ab");
+ addDomainMapFixtureEntry("dupfoo6", QType::AAAA, "2001:db8::567:89ab");
+ addDomainMapFixtureEntry(
+ "b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa",
+ {
+ DNSRecord("b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa", makeLocalhostDRC(), QType::NS),
+ DNSRecord("b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa", makeLocalhostRootDRC(), QType::SOA),
+ DNSRecord("b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa", makePtrDRC("foo6."), QType::PTR),
+ DNSRecord("b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa", makePtrDRC("bar6."), QType::PTR),
+ });
+
+ addDomainMapFixtureEntry("localhost", QType::AAAA, "::1");
+ addDomainMapFixtureEntry("self", QType::AAAA, "::1");
+ addDomainMapFixtureEntry(
+ "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa",
+ {
+ DNSRecord("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa", makeLocalhostDRC(), QType::NS),
+ DNSRecord("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa", makeLocalhostRootDRC(), QType::SOA),
+ DNSRecord("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa", makePtrDRC("localhost."), QType::PTR),
+ DNSRecord("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa", makePtrDRC("self."), QType::PTR),
+ });
+
+ addDomainMapFixtureEntry("some", QType::AAAA, "2001:db8::567:89ac");
+ addDomainMapFixtureEntry("some.address.somewhere", QType::AAAA, "2001:db8::567:89ac");
+ addDomainMapFixtureEntry("some.address", QType::AAAA, "2001:db8::567:89ac");
+ addDomainMapFixtureEntry(
+ "c.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa",
+ {
+ DNSRecord("c.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa", makeLocalhostDRC(), QType::NS),
+ DNSRecord("c.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa", makeLocalhostRootDRC(), QType::SOA),
+ DNSRecord("c.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa", makePtrDRC("some.address.somewhere."), QType::PTR),
+ DNSRecord("c.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa", makePtrDRC("some."), QType::PTR),
+ DNSRecord("c.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa", makePtrDRC("some.address."), QType::PTR),
+ });
}
using DomainMapEntry = std::pair<DNSName, SyncRes::AuthDomain>;
std::vector<std::string> parts{};
for (auto line : hostLines) {
BOOST_REQUIRE(parseEtcHostsLine(parts, line));
- addForwardAndReverseLookupEntries(domainMap, "", parts, log);
+ addForwardAndReverseLookupEntries(*domainMap, "", parts, log);
}
auto actual = sortDomainMap(*domainMap);
BOOST_CHECK(actual[i].first == expected[i].first);
BOOST_CHECK(actual[i].second == expected[i].second);
}
-
- // BOOST_CHECK_EQUAL(actual, expected);
- // BOOST_CHECK(actualSorted == expectedSorted);
}
BOOST_AUTO_TEST_SUITE_END()
#include "syncres.hh"
#include "reczones-helpers.hh"
-static void makeNameToIPZone(const std::shared_ptr<SyncRes::domainmap_t>& newMap,
- const DNSName& hostname,
- const string& ip,
- Logr::log_t log)
+template <typename T>
+static SyncRes::AuthDomain makeSOAAndNSNodes(DNSRecord& dr, T content)
{
- SyncRes::AuthDomain ad;
- ad.d_rdForward = false;
-
- DNSRecord dr;
- dr.d_name = hostname;
+ dr.d_class = 1;
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_ttl = 86400;
dr.d_type = QType::SOA;
- dr.d_class = 1;
dr.d_content = DNSRecordContent::mastermake(QType::SOA, 1, "localhost. root 1 604800 86400 2419200 604800");
+ SyncRes::AuthDomain ad;
+ ad.d_rdForward = false;
ad.d_records.insert(dr);
dr.d_type = QType::NS;
- dr.d_content = std::make_shared<NSRecordContent>("localhost.");
-
+ dr.d_content = std::make_shared<NSRecordContent>(content);
ad.d_records.insert(dr);
- dr.d_type = QType::A;
- dr.d_content = DNSRecordContent::mastermake(QType::A, 1, ip);
- ad.d_records.insert(dr);
+ return ad;
+}
- if (newMap->count(dr.d_name) != 0) {
- SLOG(g_log << Logger::Warning << "Hosts file will not overwrite zone '" << dr.d_name << "' already loaded" << endl,
- log->info(Logr::Warning, "Hosts file will not overwrite already loaded zone", "zone", Logging::Loggable(dr.d_name)));
+static void addToDomainMap(SyncRes::domainmap_t& newMap,
+ SyncRes::AuthDomain ad,
+ DNSName& name,
+ Logr::log_t log,
+ const bool partial = false,
+ const bool reverse = false)
+{
+ if (newMap.count(name) != 0) {
+ SLOG(g_log << Logger::Warning << "Will not overwrite zone '" << name << "' already loaded" << endl,
+ log->info(Logr::Warning, "Will not overwrite already loaded zone", "zone",
+ Logging::Loggable(name)));
}
else {
- SLOG(g_log << Logger::Warning << "Inserting forward zone '" << dr.d_name << "' based on hosts file" << endl,
- log->info(Logr::Notice, "Inserting forward zone based on hosts file", "zone", Logging::Loggable(dr.d_name)));
- ad.d_name = dr.d_name;
- (*newMap)[ad.d_name] = ad;
+ if (!partial) {
+ const auto direction = reverse ? std::string{"reverse"} : std::string{"forward"};
+ SLOG(g_log << Logger::Warning << "Inserting " << direction << " zone '" << name << "' based on hosts file" << endl,
+ log->info(Logr::Notice, "Inserting " + direction + " zone based on hosts file", "zone", Logging::Loggable(name)));
+ }
+ ad.d_name = name;
+ newMap[ad.d_name] = ad;
}
}
-//! parts[0] must be an IP address, the rest must be host names
-void makeIPToNamesZone(const std::shared_ptr<SyncRes::domainmap_t>& newMap,
- const vector<string>& parts,
- Logr::log_t log)
+static void makeNameToIPZone(SyncRes::domainmap_t& newMap,
+ const DNSName& hostname,
+ const ComboAddress& addr,
+ Logr::log_t log)
{
- string address = parts[0];
- vector<string> ipParts;
- stringtok(ipParts, address, ".");
+ DNSRecord dr;
+ dr.d_name = hostname;
- SyncRes::AuthDomain ad;
- ad.d_rdForward = false;
+ SyncRes::AuthDomain ad = makeSOAAndNSNodes(dr, "localhost.");
+
+ auto recType = addr.isIPv6() ? QType::AAAA : QType::A;
+ dr.d_type = recType;
+ dr.d_content = DNSRecordContent::mastermake(recType, 1, addr.toStringNoInterface());
+ ad.d_records.insert(dr);
+ addToDomainMap(newMap, ad, dr.d_name, log);
+}
+
+static void makeIPToNamesZone(SyncRes::domainmap_t& newMap,
+ const ComboAddress& addr,
+ const std::vector<std::string>& parts,
+ Logr::log_t log)
+{
DNSRecord dr;
- for (auto part = ipParts.rbegin(); part != ipParts.rend(); ++part) {
- dr.d_name.appendRawLabel(*part);
- }
- dr.d_name.appendRawLabel("in-addr");
+ dr.d_name = DNSName(addr.toStringReversed());
+ dr.d_name.appendRawLabel(addr.isIPv4() ? "in-addr" : "ip6");
dr.d_name.appendRawLabel("arpa");
- dr.d_class = 1;
- dr.d_place = DNSResourceRecord::ANSWER;
- dr.d_ttl = 86400;
- dr.d_type = QType::SOA;
- dr.d_content = DNSRecordContent::mastermake(QType::SOA, 1, "localhost. root 1 604800 86400 2419200 604800");
-
- ad.d_records.insert(dr);
- dr.d_type = QType::NS;
- dr.d_content = std::make_shared<NSRecordContent>(DNSName("localhost."));
+ SyncRes::AuthDomain ad = makeSOAAndNSNodes(dr, DNSName("localhost."));
- ad.d_records.insert(dr);
+ // Go over the hostname and aliases (parts[1], parts[2], etc...) and add PTR entries for
+ // reverse lookups.
dr.d_type = QType::PTR;
-
- if (ipParts.size() == 4) { // otherwise this is a partial zone
- for (unsigned int n = 1; n < parts.size(); ++n) {
- dr.d_content = DNSRecordContent::mastermake(QType::PTR, 1, DNSName(parts[n]).toString()); // XXX FIXME DNSNAME PAIN CAN THIS BE RIGHT?
- ad.d_records.insert(dr);
- }
+ for (auto name = parts.cbegin() + 1; name != parts.cend(); ++name) {
+ dr.d_content = DNSRecordContent::mastermake(QType::PTR, 1, DNSName(*name).toString());
+ ad.d_records.insert(dr);
}
- if (newMap->count(dr.d_name) != 0) {
- SLOG(g_log << Logger::Warning << "Will not overwrite zone '" << dr.d_name << "' already loaded" << endl,
- log->info(Logr::Warning, "Will not overwrite already loaded zone", "zone", Logging::Loggable(dr.d_name)));
- }
- else {
- if (ipParts.size() == 4) {
- SLOG(g_log << Logger::Warning << "Inserting reverse zone '" << dr.d_name << "' based on hosts file" << endl,
- log->info(Logr::Notice, "Inserting reverse zone based on hosts file", "zone", Logging::Loggable(dr.d_name)));
- }
- ad.d_name = dr.d_name;
- (*newMap)[ad.d_name] = ad;
+ addToDomainMap(newMap, ad, dr.d_name, log, false, true);
+}
+
+void makePartialIPZone(SyncRes::domainmap_t& newMap,
+ std::initializer_list<const char*> labels,
+ Logr::log_t log)
+{
+ DNSRecord dr;
+ for (auto label = std::rbegin(labels); label != std::rend(labels); ++label) {
+ dr.d_name.appendRawLabel(*label);
}
+ dr.d_name.appendRawLabel("in-addr");
+ dr.d_name.appendRawLabel("arpa");
+
+ SyncRes::AuthDomain ad = makeSOAAndNSNodes(dr, DNSName("localhost."));
+
+ addToDomainMap(newMap, ad, dr.d_name, log, true, true);
}
-void addForwardAndReverseLookupEntries(const std::shared_ptr<SyncRes::domainmap_t>& newMap,
+void addForwardAndReverseLookupEntries(SyncRes::domainmap_t& newMap,
const std::string& searchSuffix,
const std::vector<std::string>& parts,
Logr::log_t log)
{
- for (unsigned int n = 1; n < parts.size(); ++n) {
- if (searchSuffix.empty() || parts[n].find('.') != string::npos) {
- makeNameToIPZone(newMap, DNSName(parts[n]), parts[0], log);
+ const ComboAddress address{parts[0]};
+
+ // Go over the hostname and aliases (parts[1], parts[2], etc...) and add entries
+ // for forward lookups.
+ for (auto name = parts.cbegin() + 1; name != parts.cend(); ++name) {
+ if (searchSuffix.empty() || name->find('.') != string::npos) {
+ makeNameToIPZone(newMap, DNSName(*name), address, log);
}
else {
- DNSName canonic = toCanonic(DNSName(searchSuffix), parts[n]); /// XXXX DNSName pain
- if (canonic != DNSName(parts[n])) { // XXX further DNSName pain
- makeNameToIPZone(newMap, canonic, parts[0], log);
+ DNSName canonical = toCanonic(DNSName(searchSuffix), *name);
+ if (canonical != DNSName(*name)) {
+ makeNameToIPZone(newMap, canonical, address, log);
}
}
}
- makeIPToNamesZone(newMap, parts, log);
+
+ // Add entries for reverse lookups.
+ makeIPToNamesZone(newMap, address, parts, log);
}
bool parseEtcHostsLine(std::vector<std::string>& parts, std::string& line)
}
parts.clear();
stringtok(parts, line, "\t\r\n ");
- if (parts[0].find(':') != string::npos) {
- return false;
- }
return parts.size() >= 2;
}
}
if (::arg().mustDo("export-etc-hosts")) {
- string line;
string fname = ::arg()["etc-hosts-file"];
-
ifstream ifs(fname.c_str());
if (!ifs) {
SLOG(g_log << Logger::Warning << "Could not open " << fname << " for reading" << endl,
log->error(Logr::Warning, "Could not open file for reading", "file", Logging::Loggable(fname)));
}
else {
+ std::string line{};
while (getline(ifs, line)) {
if (!parseEtcHostsLine(parts, line)) {
continue;
}
- string searchSuffix = ::arg()["export-etc-hosts-search-suffix"];
- addForwardAndReverseLookupEntries(newMap, searchSuffix, parts, log);
+ try {
+ string searchSuffix = ::arg()["export-etc-hosts-search-suffix"];
+ addForwardAndReverseLookupEntries(*newMap, searchSuffix, parts, log);
+ }
+ catch (const PDNSException& ex) {
+ SLOG(g_log << Logger::Warning
+ << "The line `" << line << "` "
+ << "in the provided etc-hosts file `" << fname << "` "
+ << "could not be added: " << ex.reason << ". Going to skip it."
+ << endl,
+ log->info(Logr::Notice, "Skipping line in etc-hosts file",
+ "line", Logging::Loggable(line),
+ "hosts-file", Logging::Loggable(fname),
+ "reason", Logging::Loggable(ex.reason)));
+ }
}
}
}
if (::arg().mustDo("serve-rfc1918")) {
SLOG(g_log << Logger::Warning << "Inserting rfc 1918 private space zones" << endl,
log->info(Logr::Notice, "Inserting rfc 1918 private space zones"));
- parts.clear();
- parts.push_back("127");
- makeIPToNamesZone(newMap, parts, log);
- parts[0] = "10";
- makeIPToNamesZone(newMap, parts, log);
- parts[0] = "192.168";
- makeIPToNamesZone(newMap, parts, log);
+ makePartialIPZone(*newMap, {"127"}, log);
+ makePartialIPZone(*newMap, {"10"}, log);
+ makePartialIPZone(*newMap, {"192", "168"}, log);
+
for (int n = 16; n < 32; n++) {
- parts[0] = "172." + std::to_string(n);
- makeIPToNamesZone(newMap, parts, log);
+ makePartialIPZone(*newMap, {"172", std::to_string(n).c_str()}, log);
}
}