]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
LUA records: two improvements to createForward 9101/head
authorPieter Lexis <pieter.lexis@powerdns.com>
Wed, 13 May 2020 15:05:03 +0000 (17:05 +0200)
committerPieter Lexis <pieter.lexis@powerdns.com>
Tue, 4 Aug 2020 11:37:33 +0000 (13:37 +0200)
* Allow the createForward record to lay deeper than directly underneath
  the zone's apex.

* Add dashed IP address support to createForward

pdns/lua-record.cc
regression-tests.auth-py/test_LuaRecords.py

index 50bbf48e7422c2fb9a5c2bdf5a185c7005d7e175..b06b8c0fb370602040feac878ae2720c35a9fe4c 100644 (file)
@@ -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<<parts[0]<<endl;
+        vector<string> 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", []() {
index 39ab51acf90d1afaa1cb366b46d469cdc2425577..d0ba5ed039117b2a348ceac8d1284e4d308b2ccc 100644 (file)
@@ -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)