diff --git a/docs/settings.rst b/docs/settings.rst index f12989680652..597603e87cec 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -1084,7 +1084,7 @@ guaranteed to be stable, and is in fact likely to change. .. _setting-lua-records-exec-limit: ``lua-records-exec-limit`` ------------------------------ +-------------------------- - Integer - Default: 1000 @@ -1092,6 +1092,18 @@ guaranteed to be stable, and is in fact likely to change. Limit LUA records scripts to ``lua-records-exec-limit`` instructions. Setting this to any value less than or equal to 0 will set no limit. +.. _setting-lua-records-insert-whitespace: + +``lua-records-insert-whitespace`` +--------------------------------- + +- Boolean +- Default: no in 5.0, yes before that + +.. versionadded:: 4.9.1 + +When combining the ``"`` delimited chunks of a LUA record, whether to insert whitespace between each chunk. + .. _setting-master: ``master`` diff --git a/docs/upgrading.rst b/docs/upgrading.rst index b0713eee9c5d..683ac23c9bbf 100644 --- a/docs/upgrading.rst +++ b/docs/upgrading.rst @@ -11,6 +11,11 @@ upgrade notes if your version is older than 3.4.2. 4.9.0 to 5.0.0/master -------------- +LUA records whitespace insertion +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:ref:`setting-lua-records-insert-whitespace`, introduced in 4.9.1 with the default value (``yes``) set to maintain the old behaviour of inserting whitespace, is set to ``no`` in 5.0. + ixfrdist IPv6 support ^^^^^^^^^^^^^^^^^^^^^ diff --git a/pdns/auth-main.cc b/pdns/auth-main.cc index 98ccfc03ae43..fc42d07db8f9 100644 --- a/pdns/auth-main.cc +++ b/pdns/auth-main.cc @@ -309,6 +309,7 @@ static void declareArguments() ::arg().setSwitch("8bit-dns", "Allow 8bit dns queries") = "no"; #ifdef HAVE_LUA_RECORDS ::arg().setSwitch("enable-lua-records", "Process LUA records for all zones (metadata overrides this)") = "no"; + ::arg().setSwitch("lua-records-insert-whitespace", "Insert whitespace when combining LUA chunks") = "no"; ::arg().set("lua-records-exec-limit", "LUA records scripts execution limit (instructions count). Values <= 0 mean no limit") = "1000"; ::arg().set("lua-health-checks-expire-delay", "Stops doing health checks after the record hasn't been used for that delay (in seconds)") = "3600"; ::arg().set("lua-health-checks-interval", "LUA records health checks monitoring interval in seconds") = "5"; @@ -704,6 +705,7 @@ static void mainthread() g_doLuaRecord = ::arg().mustDo("enable-lua-records"); g_LuaRecordSharedState = (::arg()["enable-lua-records"] == "shared"); g_luaRecordExecLimit = ::arg().asNum("lua-records-exec-limit"); + g_luaRecordInsertWhitespace = ::arg().mustDo("lua-records-insert-whitespace"); g_luaHealthChecksInterval = ::arg().asNum("lua-health-checks-interval"); g_luaConsistentHashesExpireDelay = ::arg().asNum("lua-consistent-hashes-expire-delay"); g_luaConsistentHashesCleanupInterval = ::arg().asNum("lua-consistent-hashes-cleanup-interval"); diff --git a/pdns/auth-main.hh b/pdns/auth-main.hh index b96a61c68187..bc3d90c0d77d 100644 --- a/pdns/auth-main.hh +++ b/pdns/auth-main.hh @@ -50,6 +50,7 @@ extern size_t g_proxyProtocolMaximumSize; #ifdef HAVE_LUA_RECORDS extern bool g_doLuaRecord; extern bool g_LuaRecordSharedState; +extern bool g_luaRecordInsertWhitespace; extern time_t g_luaHealthChecksInterval; extern time_t g_luaHealthChecksExpireDelay; extern time_t g_luaConsistentHashesExpireDelay; diff --git a/pdns/dnsrecords.cc b/pdns/dnsrecords.cc index 6b0079247ebc..a7c752be1fa9 100644 --- a/pdns/dnsrecords.cc +++ b/pdns/dnsrecords.cc @@ -167,15 +167,27 @@ boilerplate_conv(OPT, ); #ifdef HAVE_LUA_RECORDS + +bool g_luaRecordInsertWhitespace; + string LUARecordContent::getCode() const { // in d_code, series of "part1" "part2" vector parts; stringtok(parts, d_code, "\""); string ret; - for(const auto& p : parts) { - ret += p; - ret.append(1, ' '); + if (g_luaRecordInsertWhitespace) { // default before 5.0 + for(const auto& part : parts) { + ret += part; + ret.append(1, ' '); + } + } + else { // default since 5.0 + for(const auto& part : parts) { + if (part != " ") { + ret += part; + } + } } return ret; } diff --git a/regression-tests.auth-py/test_LuaRecords.py b/regression-tests.auth-py/test_LuaRecords.py index 3d6d91a4bc8f..973d98568c87 100644 --- a/regression-tests.auth-py/test_LuaRecords.py +++ b/regression-tests.auth-py/test_LuaRecords.py @@ -43,6 +43,7 @@ class TestLuaRecords(AuthTest): launch=bind geoip any-to-tcp=no enable-lua-records +lua-records-insert-whitespace=yes lua-health-checks-interval=1 """ @@ -157,6 +158,8 @@ class TestLuaRecords(AuthTest): lookmeup IN A 192.0.2.5 dblookup IN LUA A "dblookup('lookmeup.example.org', pdns.A)[1]" + +whitespace IN LUA TXT "'foo" "bar'" """, 'createforward6.example.org': """ createforward6.example.org. 3600 IN SOA {soa} @@ -1090,6 +1093,22 @@ def testDblookup(self): self.assertRcodeEqual(res, dns.rcode.NOERROR) self.assertEqual(self.sortRRsets(res.answer), self.sortRRsets(response.answer)) + def testWhitespace(self, expectws=True): + """ + Test TXT query for whitespace + """ + name = 'whitespace.example.org.' + + query = dns.message.make_query(name, 'TXT') + + response = dns.message.make_response(query) + + response.answer.append(dns.rrset.from_text(name, 0, dns.rdataclass.IN, dns.rdatatype.TXT, '"foo bar"' if expectws else '"foobar"')) + + res = self.sendUDPQuery(query) + self.assertRcodeEqual(res, dns.rcode.NOERROR) + self.assertEqual(res.answer, response.answer) + class TestLuaRecordsShared(TestLuaRecords): _config_template = """ @@ -1098,6 +1117,7 @@ class TestLuaRecordsShared(TestLuaRecords): launch=bind geoip any-to-tcp=no enable-lua-records=shared +lua-records-insert-whitespace=yes lua-health-checks-interval=1 """ @@ -1112,6 +1132,20 @@ def testCounter(self): self.assertEqual(len(resUDP), 50) self.assertEqual(len(resTCP), 50) +class TestLuaRecordsNoWhiteSpace(TestLuaRecords): + _config_template = """ +geoip-database-files=../modules/geoipbackend/regression-tests/GeoLiteCity.mmdb +edns-subnet-processing=yes +launch=bind geoip +any-to-tcp=no +enable-lua-records +lua-records-insert-whitespace=no +lua-health-checks-interval=1 +""" + + def testWhitespace(self): + return TestLuaRecords.testWhitespace(self, False) + if __name__ == '__main__': unittest.main() exit(0)