]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
iputils: Add functions to retrieve the list of network interfaces, addresses
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 22 Nov 2021 10:28:02 +0000 (11:28 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 3 Dec 2021 15:24:07 +0000 (16:24 +0100)
Only tested on Linux but should work at least on FreeBSD and OpenBSD
as well.

m4/pdns_check_network_libs.m4
pdns/iputils.cc
pdns/iputils.hh

index d8b020c875ff882efa154692a8bdee41f9a585f6..f74311473cf09d89497c326508b3d7f4154b70e6 100644 (file)
@@ -4,4 +4,5 @@ AC_DEFUN([PDNS_CHECK_NETWORK_LIBS],[
   AC_SEARCH_LIBS([socket], [socket])
   AC_SEARCH_LIBS([gethostent], [nsl])
   AC_CHECK_FUNCS([recvmmsg sendmmsg accept4])
+  AC_CHECK_DECL(getifaddrs, [AC_DEFINE([HAVE_GETIFADDRS], [1], [Define to 1 if you have getifaddrs])], [], [#include <ifaddrs.h>])
 ])
index 1c042289a9e909c4ed7e95ef752ff33e015b1769..67375ffb2ef75db98e3d365f6c77b1cbacce8ba5 100644 (file)
 #include "iputils.hh"
 #include <sys/socket.h> 
 
+#if HAVE_GETIFADDRS
+#include <ifaddrs.h>
+#endif
+
 /** these functions provide a very lightweight wrapper to the Berkeley sockets API. Errors -> exceptions! */
 
 static void RuntimeError(const boost::format& fmt)
@@ -543,3 +547,56 @@ void setSocketSendBuffer(int fd, uint32_t size)
 {
   setSocketBuffer(fd, SO_SNDBUF, size);
 }
+
+std::set<std::string> getListOfNetworkInterfaces()
+{
+  std::set<std::string> 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) {
+      continue;
+    }
+    result.insert(ifa->ifa_name);
+  }
+
+  freeifaddrs(ifaddr);
+#endif
+  return result;
+}
+
+std::vector<ComboAddress> getListOfAddressesOfNetworkInterface(const std::string& itf)
+{
+  std::vector<ComboAddress> 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;
+    }
+
+    result.push_back(addr);
+  }
+
+  freeifaddrs(ifaddr);
+#endif
+  return result;
+}
index 23b200b1a5375fa69f6f7f609d2614f155176190..191e33d9fc02f3c8af587a6c47f7a81810408f31 100644 (file)
@@ -1650,6 +1650,9 @@ bool isTCPSocketUsable(int sock);
 extern template class NetmaskTree<bool>;
 ComboAddress parseIPAndPort(const std::string& input, uint16_t port);
 
+std::set<std::string> getListOfNetworkInterfaces();
+std::vector<ComboAddress> getListOfAddressesOfNetworkInterface(const std::string& itf);
+
 /* These functions throw if the value was already set to a higher value,
    or on error */
 void setSocketBuffer(int fd, int optname, uint32_t size);