]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
auth: refactor if{url,port}up functions
authorCharles-Henri Bruyand <charles-henri.bruyand@open-xchange.com>
Tue, 21 Mar 2023 13:58:19 +0000 (14:58 +0100)
committerCharles-Henri Bruyand <charles-henri.bruyand@open-xchange.com>
Tue, 21 Mar 2023 13:58:19 +0000 (14:58 +0100)
pdns/lua-record.cc

index b4810b4cf5f6abd9e09f1a846cdeaee634977e3d..639653fede220b89d8f15361cb7a6ec25aacc10f 100644 (file)
@@ -301,7 +301,6 @@ bool doCompare(const T& var, const std::string& res, const C& cmp)
 }
 }
 
-
 static std::string getGeo(const std::string& ip, GeoIPInterface::GeoIPQueryAttribute qa)
 {
   static bool initialized;
@@ -560,6 +559,29 @@ static vector<ComboAddress> convComboAddressList(const iplist_t& items, uint16_t
   return result;
 }
 
+/**
+ * Reads and unify single or multiple sets of ips :
+ * - {'192.0.2.1', '192.0.2.2'}
+ * - {{'192.0.2.1', '192.0.2.2'}, {'198.51.100.1'}}
+ */
+
+static vector<vector<ComboAddress>> convMultiComboAddressList(const boost::variant<iplist_t, ipunitlist_t>& items, uint16_t port = 0)
+{
+  vector<vector<ComboAddress>> candidates;
+
+  if(auto simple = boost::get<iplist_t>(&items)) {
+    vector<ComboAddress> unit = convComboAddressList(*simple, port);
+    candidates.push_back(unit);
+  } else {
+    auto units = boost::get<ipunitlist_t>(items);
+    for(const auto& u : units) {
+      vector<ComboAddress> unit = convComboAddressList(u.second, port);
+      candidates.push_back(unit);
+    }
+  }
+  return candidates;
+}
+
 static vector<string> convStringList(const iplist_t& items)
 {
   vector<string> result;
@@ -596,6 +618,37 @@ typedef struct AuthLuaRecordContext
 
 static thread_local unique_ptr<lua_record_ctx_t> s_lua_record_ctx;
 
+static vector<string> genericIfUp(const boost::variant<iplist_t, ipunitlist_t>& ips, boost::optional<opts_t> options, std::function<bool(const ComboAddress&, const opts_t&)> upcheckf, uint16_t port = 0) {
+  vector<vector<ComboAddress> > candidates;
+  opts_t opts;
+  if(options)
+    opts = *options;
+
+  candidates = convMultiComboAddressList(ips, port);
+
+  for(const auto& unit : candidates) {
+    vector<ComboAddress> available;
+    for(const auto& c : unit) {
+      if (upcheckf(c, opts)) {
+        available.push_back(c);
+      }
+    }
+    if(!available.empty()) {
+      vector<ComboAddress> res = useSelector(getOptionValue(options, "selector", "random"), s_lua_record_ctx->bestwho, available);
+      return convComboAddressListToString(res);
+    }
+  }
+
+  // All units down, apply backupSelector on all candidates
+  vector<ComboAddress> ret{};
+  for(const auto& unit : candidates) {
+    ret.insert(ret.end(), unit.begin(), unit.end());
+  }
+
+  vector<ComboAddress> res = useSelector(getOptionValue(options, "backupSelector", "random"), s_lua_record_ctx->bestwho, ret);
+  return convComboAddressListToString(res);
+}
+
 static void setupLuaRecords(LuaContext& lua)
 {
   lua.writeFunction("latlon", []() {
@@ -833,51 +886,17 @@ static void setupLuaRecords(LuaContext& lua)
    * @example ifportup(443, { '1.2.3.4', '5.4.3.2' })"
    */
   lua.writeFunction("ifportup", [](int port, const boost::variant<iplist_t, ipunitlist_t>& ips, const boost::optional<std::unordered_map<string,string>> options) {
-      vector<vector<ComboAddress>> candidates;
-      opts_t opts;
-      std::string selector;
-
       if (port < 0) {
         port = 0;
       }
       if (port > std::numeric_limits<uint16_t>::max()) {
         port = std::numeric_limits<uint16_t>::max();
       }
-      if(options)
-        opts = *options;
-
-      if(auto simple = boost::get<iplist_t>(&ips)) {
-        vector<ComboAddress> unit = convComboAddressList(*simple, port);
-        candidates.push_back(unit);
-      } else {
-        auto units = boost::get<ipunitlist_t>(ips);
-        for(const auto& u : units) {
-          vector<ComboAddress> unit = convComboAddressList(u.second, port);
-          candidates.push_back(unit);
-        }
-      }
-
-      for(const auto& unit : candidates) {
-        vector<ComboAddress> available;
-        for(const auto& c : unit) {
-          if(g_up.isUp(c, opts)) {
-            available.push_back(c);
-          }
-        }
-        if(!available.empty()) {
-          vector<ComboAddress> res = useSelector(getOptionValue(options, "selector", "random"), s_lua_record_ctx->bestwho, available);
-          return convComboAddressListToString(res);
-        }
-      }
 
-      // All units down, apply backupSelector on all candidates
-      vector<ComboAddress> unavailable{};
-      for(const auto& unit : candidates) {
-        unavailable.insert(unavailable.end(), unit.begin(), unit.end());
-      }
-
-      vector<ComboAddress> res = useSelector(getOptionValue(options, "backupSelector", "random"), s_lua_record_ctx->bestwho, unavailable);
-      return convComboAddressListToString(res);
+      auto checker = [](const ComboAddress& addr, const opts_t& opts) {
+        return g_up.isUp(addr, opts);
+      };
+      return genericIfUp(ips, options, checker, port);
     });
 
   lua.writeFunction("ifurlextup", [](const vector<pair<int, opts_t> >& ipurls, boost::optional<opts_t> options) {
@@ -916,42 +935,11 @@ static void setupLuaRecords(LuaContext& lua)
   lua.writeFunction("ifurlup", [](const std::string& url,
                                           const boost::variant<iplist_t, ipunitlist_t>& ips,
                                           boost::optional<opts_t> options) {
-      vector<vector<ComboAddress> > candidates;
-      opts_t opts;
-      if(options)
-        opts = *options;
-      if(auto simple = boost::get<iplist_t>(&ips)) {
-        vector<ComboAddress> unit = convComboAddressList(*simple);
-        candidates.push_back(unit);
-      } else {
-        auto units = boost::get<ipunitlist_t>(ips);
-        for(const auto& u : units) {
-          vector<ComboAddress> unit = convComboAddressList(u.second);
-          candidates.push_back(unit);
-        }
-      }
 
-      for(const auto& unit : candidates) {
-        vector<ComboAddress> available;
-        for(const auto& c : unit) {
-          if(g_up.isUp(c, url, opts)) {
-            available.push_back(c);
-          }
-        }
-        if(!available.empty()) {
-          vector<ComboAddress> res = useSelector(getOptionValue(options, "selector", "random"), s_lua_record_ctx->bestwho, available);
-          return convComboAddressListToString(res);
-        }
-      }
-
-      // All units down, apply backupSelector on all candidates
-      vector<ComboAddress> ret{};
-      for(const auto& unit : candidates) {
-        ret.insert(ret.end(), unit.begin(), unit.end());
-      }
-
-      vector<ComboAddress> res = useSelector(getOptionValue(options, "backupSelector", "random"), s_lua_record_ctx->bestwho, ret);
-      return convComboAddressListToString(res);
+    auto checker = [&url](const ComboAddress& addr, const opts_t& opts) {
+        return g_up.isUp(addr, url, opts);
+      };
+      return genericIfUp(ips, options, checker);
     });
   /*
    * Returns a random IP address from the supplied list