]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Add getListOfRangesOfNetworkInterface() Lua binding
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 9 May 2022 10:27:33 +0000 (12:27 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 7 Oct 2022 15:48:02 +0000 (17:48 +0200)
pdns/dnsdist-console.cc
pdns/dnsdist-lua-bindings.cc
pdns/dnsdistdist/docs/reference/config.rst
pdns/iputils.cc
pdns/iputils.hh

index bf802fc85668c78b9b34f4e43116c372ce6f1613..a559258b1b673ff2a04bf4a7fadcdbc1a949016e 100644 (file)
@@ -522,6 +522,7 @@ const std::vector<ConsoleKeyword> g_consoleKeywords{
   { "getDOHFrontendCount", true, "", "returns the number of DoH listeners" },
   { "getListOfAddressesOfNetworkInterface", true, "itf", "returns the list of addresses configured on a given network interface, as strings" },
   { "getListOfNetworkInterfaces", true, "", "returns the list of network interfaces present on the system, as strings" },
+  { "getListOfRangesOfNetworkInterface", true, "itf", "returns the list of network ranges configured on a given network interface, as strings" },
   { "getMACAddress", true, "IP addr", "return the link-level address (MAC) corresponding to the supplied neighbour  IP address, if known by the kernel" },
   { "getOutgoingTLSSessionCacheSize", true, "", "returns the number of TLS sessions (for outgoing connections) currently cached" },
   { "getPool", true, "name", "return the pool named `name`, or \"\" for the default pool" },
index e0337d3fa31bf18c3f3ea509401579903a0a3d20..dd00c0485e90ace7159a9050efc5adc13979ab4f 100644 (file)
@@ -746,6 +746,16 @@ void setupLuaBindings(LuaContext& luaCtx, bool client)
     return result;
   });
 
+  luaCtx.writeFunction("getListOfRangesOfNetworkInterface", [](const std::string& itf) {
+    LuaArray<std::string> result;
+    auto addrs = getListOfRangesOfNetworkInterface(itf);
+    int counter = 1;
+    for (const auto& addr : addrs) {
+      result.push_back({counter++, addr.toString()});
+    }
+    return result;
+  });
+
   luaCtx.writeFunction("getMACAddress", [](const std::string& ip) {
     return getMACAddress(ComboAddress(ip));
   });
index 512a15eb56c5258e16bc81cf9c05e1a1b0cedc1d..99c4e1459303e4c499e8a48de1a7c408b255f4af 100644 (file)
@@ -1029,6 +1029,15 @@ Status, Statistics and More
   Return the list of network interfaces configured on the system, as strings.
   This function requires support for ``getifaddrs``, which is known to be present on FreeBSD, Linux, and OpenBSD at least.
 
+.. function:: getListOfRangesOfNetworkInterface(itf)
+
+  .. versionadded:: 1.8.0
+
+  Return the list of network ranges configured on a given network interface, as strings.
+  This function requires support for ``getifaddrs``, which is known to be present on FreeBSD, Linux, and OpenBSD at least.
+
+  :param str itf: The name of the network interface
+
 .. function:: getMACAddress(ip) -> str
 
   .. versionadded:: 1.8.0
index 528ae9014972c8c585b7d1c14975e7506f281b28..e28927d1e4640a150c52cda954f39202e2361bdc 100644 (file)
@@ -587,3 +587,54 @@ std::vector<ComboAddress> getListOfAddressesOfNetworkInterface(const std::string
 #endif
   return result;
 }
+
+#if HAVE_GETIFADDRS
+static uint8_t convertNetmaskToBits(const struct in_addr* mask, socklen_t len)
+{
+  uint8_t result = 0;
+  // for all bytes in the address (4 for IPv4, 16 for IPv6)
+  for (size_t idx = 0; idx < len; idx++) {
+    uint8_t byte = *(reinterpret_cast<const uint8_t*>(&mask->s_addr) + idx);
+    // count the number of bits set
+    while (byte > 0) {
+      result += (byte & 1);
+      byte >>= 1;
+    }
+  }
+  return result;
+}
+#endif /* HAVE_GETIFADDRS */
+
+std::vector<Netmask> getListOfRangesOfNetworkInterface(const std::string& itf)
+{
+  std::vector<Netmask> result;
+#if HAVE_GETIFADDRS
+  struct ifaddrs *ifaddr;
+  if (getifaddrs(&ifaddr) == -1) {
+    return result;
+  }
+
+  for (struct ifaddrs *ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
+    if (ifa->ifa_name == nullptr || strcmp(ifa->ifa_name, itf.c_str()) != 0) {
+      continue;
+    }
+    if (ifa->ifa_addr == nullptr || (ifa->ifa_addr->sa_family != AF_INET && ifa->ifa_addr->sa_family != AF_INET6)) {
+      continue;
+    }
+    ComboAddress addr;
+    try {
+      addr.setSockaddr(ifa->ifa_addr, ifa->ifa_addr->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6));
+    }
+    catch (...) {
+      continue;
+    }
+
+    auto netmask = reinterpret_cast<const struct sockaddr_in*>(ifa->ifa_netmask);
+    uint8_t maskBits = convertNetmaskToBits(&netmask->sin_addr, addr.getSocklen());
+    result.emplace_back(addr, maskBits);
+  }
+
+  freeifaddrs(ifaddr);
+#endif
+  return result;
+}
index af3c2cc74ab9e28bd066b6914a767f6510dc6211..459167e97babe0e8a424331be07880a93a5b7e59 100644 (file)
@@ -1707,6 +1707,7 @@ ComboAddress parseIPAndPort(const std::string& input, uint16_t port);
 
 std::set<std::string> getListOfNetworkInterfaces();
 std::vector<ComboAddress> getListOfAddressesOfNetworkInterface(const std::string& itf);
+std::vector<Netmask> getListOfRangesOfNetworkInterface(const std::string& itf);
 
 /* These functions throw if the value was already set to a higher value,
    or on error */