From: Remi Gacogne Date: Mon, 22 Nov 2021 10:28:02 +0000 (+0100) Subject: iputils: Add functions to retrieve the list of network interfaces, addresses X-Git-Tag: auth-4.7.0-alpha1~118^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6ec09d51c4412da3edd2def5d9bce8ae4062d2e8;p=thirdparty%2Fpdns.git iputils: Add functions to retrieve the list of network interfaces, addresses Only tested on Linux but should work at least on FreeBSD and OpenBSD as well. --- diff --git a/m4/pdns_check_network_libs.m4 b/m4/pdns_check_network_libs.m4 index d8b020c875..f74311473c 100644 --- a/m4/pdns_check_network_libs.m4 +++ b/m4/pdns_check_network_libs.m4 @@ -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 ]) ]) diff --git a/pdns/iputils.cc b/pdns/iputils.cc index 1c042289a9..67375ffb2e 100644 --- a/pdns/iputils.cc +++ b/pdns/iputils.cc @@ -25,6 +25,10 @@ #include "iputils.hh" #include +#if HAVE_GETIFADDRS +#include +#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 getListOfNetworkInterfaces() +{ + std::set 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 getListOfAddressesOfNetworkInterface(const std::string& itf) +{ + std::vector 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; +} diff --git a/pdns/iputils.hh b/pdns/iputils.hh index 23b200b1a5..191e33d9fc 100644 --- a/pdns/iputils.hh +++ b/pdns/iputils.hh @@ -1650,6 +1650,9 @@ bool isTCPSocketUsable(int sock); extern template class NetmaskTree; ComboAddress parseIPAndPort(const std::string& input, uint16_t port); +std::set getListOfNetworkInterfaces(); +std::vector 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);