From: Pieter Lexis Date: Wed, 13 May 2020 15:05:03 +0000 (+0200) Subject: LUA records: two improvements to createForward X-Git-Tag: rec-4.4.0-beta1~24^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=448e7a2dd7092561846ced41b6b45f7d56a34330;p=thirdparty%2Fpdns.git LUA records: two improvements to createForward * Allow the createForward record to lay deeper than directly underneath the zone's apex. * Add dashed IP address support to createForward --- diff --git a/pdns/lua-record.cc b/pdns/lua-record.cc index 50bbf48e74..b06b8c0fb3 100644 --- a/pdns/lua-record.cc +++ b/pdns/lua-record.cc @@ -606,21 +606,47 @@ static void setupLuaRecords() return std::string("error"); }); lua.writeFunction("createForward", []() { + static string allZerosIP("0.0.0.0"); DNSName rel=s_lua_record_ctx->qname.makeRelative(s_lua_record_ctx->zone); + // parts is something like ["1", "2", "3", "4", "static"] or + // ["1", "2", "3", "4"] or ["ip40414243", "ip-addresses", ...] auto parts = rel.getRawLabels(); - if(parts.size()==4) - return parts[0]+"."+parts[1]+"."+parts[2]+"."+parts[3]; - if(parts.size()==1) { + // Yes, this still breaks if an 1-2-3-4.XXXX is nested too deeply... + if(parts.size()>=4) { + try { + ComboAddress ca(parts[0]+"."+parts[1]+"."+parts[2]+"."+parts[3]); + return ca.toString(); + } catch (const PDNSException &e) { + return allZerosIP; + } + } else if (parts.size() >= 1) { // either hex string, or 12-13-14-15 - // cout< ip_parts; + stringtok(ip_parts, parts[0], "-"); unsigned int x1, x2, x3, x4; - if(sscanf(parts[0].c_str()+2, "%02x%02x%02x%02x", &x1, &x2, &x3, &x4)==4) { + if (ip_parts.size() >= 4) { + // 1-2-3-4 with any prefix (e.g. ip-foo-bar-1-2-3-4) + string ret; + for (size_t n=4; n > 0; n--) { + auto octet = ip_parts[ip_parts.size() - n]; + try { + auto octetVal = std::stol(octet); + if (octetVal >= 0 && octetVal <= 255) { + ret += ip_parts.at(ip_parts.size() - n) + "."; + } else { + return allZerosIP; + } + } catch (const std::exception &e) { + return allZerosIP; + } + } + ret.resize(ret.size() - 1); // remove trailing dot after last octet + return ret; + } else if(parts[0].length() == 10 && sscanf(parts[0].c_str()+2, "%02x%02x%02x%02x", &x1, &x2, &x3, &x4)==4) { return std::to_string(x1)+"."+std::to_string(x2)+"."+std::to_string(x3)+"."+std::to_string(x4); } - - } - return std::string("0.0.0.0"); + return allZerosIP; }); lua.writeFunction("createForward6", []() { diff --git a/regression-tests.auth-py/test_LuaRecords.py b/regression-tests.auth-py/test_LuaRecords.py index 39ab51acf9..d0ba5ed039 100644 --- a/regression-tests.auth-py/test_LuaRecords.py +++ b/regression-tests.auth-py/test_LuaRecords.py @@ -117,6 +117,8 @@ any IN TXT "hello there" resolve IN LUA A ";local r=resolve('localhost', 1) local t={{}} for _,v in ipairs(r) do table.insert(t, v:toString()) end return t" +*.createforward IN LUA A "createForward()" + """, } _web_rrsets = [] @@ -611,6 +613,41 @@ resolve IN LUA A ";local r=resolve('localhost', 1) local t={{}} self.assertRcodeEqual(res, dns.rcode.NOERROR) self.assertEqual(res.answer, response.answer) + def testCreateForward(self): + name_suffix = '.createforward.example.org.' + + name_expected = { + "1.2.3.4": "1.2.3.4", + "1.2.3.4.static": "1.2.3.4", + "1.2.3.4.5.6": "1.2.3.4", + "invalid.1.2.3.4": "0.0.0.0", + "invalid": "0.0.0.0", + "1-2-3-4": "1.2.3.4", + "1-2-3-4.foo": "1.2.3.4", + "1-2-3-4.foo.bar": "0.0.0.0", + "1-2-3-4.foo.bar.baz": "0.0.0.0", + "1-2-3-4.foo.bar.baz.quux": "0.0.0.0", + "ip-1-2-3-4": "1.2.3.4", + "ip-is-here-for-you-1-2-3-4": "1.2.3.4", + "ip40414243": "64.65.66.67", + "ipp40414243": "0.0.0.0", + "ip4041424": "0.0.0.0", + } + + for k, v in name_expected.items(): + name = k + name_suffix + + query = dns.message.make_query(name, 'A') + response = dns.message.make_response(query) + response.answer.append(dns.rrset.from_text( + name, 0, dns.rdataclass.IN, dns.rdatatype.A, v)) + + res = self.sendUDPQuery(query) + print(res) + self.assertRcodeEqual(res, dns.rcode.NOERROR) + self.assertEqual(res.answer, response.answer) + + if __name__ == '__main__': unittest.main() exit(0)