diff --git a/libebpfdiscovery/headers/ebpfdiscovery/Discovery.h b/libebpfdiscovery/headers/ebpfdiscovery/Discovery.h index d692aec4..cdadb696 100644 --- a/libebpfdiscovery/headers/ebpfdiscovery/Discovery.h +++ b/libebpfdiscovery/headers/ebpfdiscovery/Discovery.h @@ -22,7 +22,7 @@ #include "ebpfdiscoveryshared/Types.h" #include "httpparser/HttpRequestParser.h" #include "service/Aggregator.h" -#include "service/IpAddressNetlinkChecker.h" +#include "service/IpAddressCheckerImpl.h" #include #include @@ -73,8 +73,8 @@ class Discovery { DiscoveryBpfFds bpfFds; SavedSessionsCacheType savedSessions; - service::NetlinkCalls netlinkCalls; - service::IpAddressNetlinkChecker ipChecker{netlinkCalls}; + service::InterfacesReader interfacesReader; + service::IpAddressCheckerImpl ipChecker{interfacesReader}; service::Aggregator serviceAggregator; }; diff --git a/libservice/CMakeLists.txt b/libservice/CMakeLists.txt index 2cbcd214..2211f2dc 100644 --- a/libservice/CMakeLists.txt +++ b/libservice/CMakeLists.txt @@ -15,8 +15,8 @@ list(APPEND SOURCES src/Aggregator.cpp src/IpAddress.cpp - src/IpAddressNetlinkChecker.cpp - src/NetlinkCalls.cpp + src/IpAddressCheckerImpl.cpp + src/InterfacesReader.cpp src/NetlinkSocket.cpp) set(TARGET service) diff --git a/libservice/headers/service/NetlinkCalls.h b/libservice/headers/service/InterfacesReader.h similarity index 62% rename from libservice/headers/service/NetlinkCalls.h rename to libservice/headers/service/InterfacesReader.h index d29c5108..d7a4174f 100644 --- a/libservice/headers/service/NetlinkCalls.h +++ b/libservice/headers/service/InterfacesReader.h @@ -18,38 +18,41 @@ #include #include +#include +#include #include #include #include -#include struct sockaddr_nl; namespace service { -using IPv4int = uint32_t; +struct Ipv6Network { + in6_addr networkIpv6Addr; + in6_addr networkMask; +}; -struct IpIfce { - std::vector ip; - std::vector broadcast; - uint32_t mask; +struct Ipv4Network { + in_addr networkIpv4Addr; + in_addr networkMask; + std::optional broadcastAddr; }; -using IpInterfaces = std::unordered_map; -using BridgeIndices = std::vector; -class NetlinkCalls { +class InterfacesReader { public: - virtual ~NetlinkCalls() = default; + virtual ~InterfacesReader() = default; + void printNetworksInfo(); + [[nodiscard]] virtual std::vector getIpV4Interfaces() const; + [[nodiscard]] virtual std::vector getIpV6Interfaces() const; - struct Ipv6Network { - in6_addr networkIpv6Addr; - in6_addr networkMask; - }; + virtual void collectAllIpInterfaces(); + +private: + std::vector ipv4Networks; + std::vector ipv6Networks; - virtual IpInterfaces collectIpInterfaces() const; - virtual std::vector collectIpv6Networks() const; - virtual BridgeIndices collectBridgeIndices() const; }; } // namespace service diff --git a/libservice/headers/service/IpAddress.h b/libservice/headers/service/IpAddress.h index 1f4db78c..f535b5de 100644 --- a/libservice/headers/service/IpAddress.h +++ b/libservice/headers/service/IpAddress.h @@ -26,6 +26,7 @@ using IPv4bytes = uint8_t[4]; using IPv6bytes = uint8_t[16]; std::string ipv4ToString(const IPv4bytes addr); +std::string ipv4InAdrToString(const in_addr& addr); std::string ipv6ToString(const IPv6bytes addr); } // namespace service diff --git a/libservice/headers/service/IpAddressChecker.h b/libservice/headers/service/IpAddressChecker.h index d71953de..33aad2fc 100644 --- a/libservice/headers/service/IpAddressChecker.h +++ b/libservice/headers/service/IpAddressChecker.h @@ -17,6 +17,7 @@ #pragma once #include +#include "netinet/in.h" struct in6_addr; @@ -28,8 +29,8 @@ class IpAddressChecker { public: virtual ~IpAddressChecker() = default; - virtual bool isV4AddressExternal(IPv4int addr) const = 0; + [[nodiscard]] virtual bool isV4AddressExternal(const in_addr& addr) const = 0; - virtual bool isV6AddressExternal(const in6_addr& addr) const = 0; + [[nodiscard]] virtual bool isV6AddressExternal(const in6_addr& addr) const = 0; }; } // namespace service diff --git a/libservice/headers/service/IpAddressNetlinkChecker.h b/libservice/headers/service/IpAddressCheckerImpl.h similarity index 68% rename from libservice/headers/service/IpAddressNetlinkChecker.h rename to libservice/headers/service/IpAddressCheckerImpl.h index 7d949d48..545051a2 100644 --- a/libservice/headers/service/IpAddressNetlinkChecker.h +++ b/libservice/headers/service/IpAddressCheckerImpl.h @@ -16,21 +16,20 @@ #pragma once -#include #include -#include #include +#include #include "IpAddressChecker.h" -#include "NetlinkCalls.h" +#include "InterfacesReader.h" namespace service { -class IpAddressNetlinkChecker : public IpAddressChecker { +class IpAddressCheckerImpl : public IpAddressChecker { public: - explicit IpAddressNetlinkChecker(const NetlinkCalls& calls); + explicit IpAddressCheckerImpl(InterfacesReader& interfaceReader); - bool isV4AddressExternal(IPv4int addr) const override; + bool isV4AddressExternal(const in_addr& addr) const override; bool isV6AddressExternal(const in6_addr& addr) const override; @@ -42,24 +41,13 @@ class IpAddressNetlinkChecker : public IpAddressChecker { ipv6Range parseIpv6Range(const std::string& range) const; bool isInRange(const in6_addr& addr, const std::string& range) const; bool checkSubnet(const in6_addr& addrToCheck, const in6_addr& interfaceIpv6Addr, const in6_addr& interfaceMask) const; + bool checkSubnetIpv4(const in_addr& addrToCheck, const in_addr& interfaceIpv4Addr, const in_addr& interfaceMask) const; bool ipv6AddressContainsMappedIpv4Address(const in6_addr& addr) const; std::optional getMappedIPv4Addr(const in6_addr& addr) const; void readNetworks(); - void printNetworkInterfacesInfo(); - - bool isLocalBridge(int index) const { - if (const auto it{isLocalBridgeMap.find(index)}; it != isLocalBridgeMap.end()) { - return it->second; - } - - return false; - } - - const NetlinkCalls& netlink; - IpInterfaces ipInterfaces; - std::vector ipv6Networks; - std::unordered_map isLocalBridgeMap; + InterfacesReader& interfacesReader; + std::vector ipv6Networks; }; } // namespace service diff --git a/libservice/src/Aggregator.cpp b/libservice/src/Aggregator.cpp index fa4d92c0..1dfd7dbb 100644 --- a/libservice/src/Aggregator.cpp +++ b/libservice/src/Aggregator.cpp @@ -18,7 +18,7 @@ #include "logging/Logger.h" #include "service/IpAddress.h" -#include "service/IpAddressNetlinkChecker.h" +#include "service/IpAddressCheckerImpl.h" #include @@ -29,7 +29,7 @@ static std::string getEndpoint(const std::string& host, const std::string& url) } static bool isIpv4ClientExternal(const IpAddressChecker& ipChecker, const in_addr& clientAddrBinary) { - return ipChecker.isV4AddressExternal(clientAddrBinary.s_addr); + return ipChecker.isV4AddressExternal(clientAddrBinary); } static bool isIpv6ClientExternal(const IpAddressChecker& ipChecker, const in6_addr& clientAddrBinary) { diff --git a/libservice/src/InterfacesReader.cpp b/libservice/src/InterfacesReader.cpp new file mode 100644 index 00000000..fd41b5b5 --- /dev/null +++ b/libservice/src/InterfacesReader.cpp @@ -0,0 +1,88 @@ +/* + * Copyright 2023 Dynatrace LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "service/InterfacesReader.h" + +#include +#include +#include +#include +#include +#include + +#include "NetlinkSocket.h" +#include "logging/Logger.h" + +namespace service { + +void InterfacesReader::printNetworksInfo() { + LOG_INFO("{} IPv4 networks have been discovered:", ipv4Networks.size()); + for (const auto& ipv4Network : ipv4Networks) { + char ipv4NetworkAddrString[INET_ADDRSTRLEN]; + char ipv4NetworkMaskString[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(ipv4Network.networkIpv4Addr), ipv4NetworkAddrString, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &(ipv4Network.networkMask), ipv4NetworkMaskString, INET_ADDRSTRLEN); + LOG_INFO("Detected IPv4 network: {}, Mask: {}", ipv4NetworkAddrString, ipv4NetworkMaskString); + } + LOG_INFO("{} IPv6 networks have been discovered:", ipv6Networks.size()); + for (const auto& ipv6Network : ipv6Networks) { + char ipv6NetworkAddrString[INET6_ADDRSTRLEN]; + char ipv6NetworkMaskString[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &(ipv6Network.networkIpv6Addr), ipv6NetworkAddrString, INET6_ADDRSTRLEN); + inet_ntop(AF_INET6, &(ipv6Network.networkMask), ipv6NetworkMaskString, INET6_ADDRSTRLEN); + LOG_INFO("Detected IPv6 network: {}, Mask: {}", ipv6NetworkAddrString, ipv6NetworkMaskString); + } +} + +void InterfacesReader::collectAllIpInterfaces() { + ifaddrs* ifAddressStruct = nullptr; + if (getifaddrs(&ifAddressStruct) != 0) { + LOG_WARN("Error while collecting IP interfaces, getifaddrs returned error: {}", strerror(errno)); + return; + } + for (const ifaddrs* ifa = ifAddressStruct; ifa != nullptr; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == nullptr) { + continue; + } + if (ifa->ifa_addr->sa_family == AF_INET6) { + const in6_addr networkIpv6Addr = reinterpret_cast(ifa->ifa_addr)->sin6_addr; + const in6_addr networkMask = reinterpret_cast(ifa->ifa_netmask)->sin6_addr; + + ipv6Networks.emplace_back(Ipv6Network{networkIpv6Addr, networkMask}); + continue; + } + if (ifa->ifa_addr->sa_family == AF_INET) { + auto address = reinterpret_cast(ifa->ifa_addr)->sin_addr; + auto mask = reinterpret_cast(ifa->ifa_netmask)->sin_addr; + std::optional broadcast{}; + if (ifa->ifa_flags & IFF_BROADCAST) { + broadcast = std::optional(reinterpret_cast(ifa->ifa_ifu.ifu_broadaddr)->sin_addr); + } + ipv4Networks.emplace_back(Ipv4Network{{address}, mask, broadcast}); + } + } + freeifaddrs(ifAddressStruct); +} + +std::vector InterfacesReader::getIpV4Interfaces() const { + return ipv4Networks; +} + +std::vector InterfacesReader::getIpV6Interfaces() const { + return ipv6Networks; +} + +} // namespace service diff --git a/libservice/src/IpAddress.cpp b/libservice/src/IpAddress.cpp index d9d90f79..22520bd0 100644 --- a/libservice/src/IpAddress.cpp +++ b/libservice/src/IpAddress.cpp @@ -29,6 +29,10 @@ std::string ipv4ToString(const IPv4bytes addr) { return std::string(ipAddress); } +std::string ipv4InAdrToString(const in_addr& addr) { + return ipv4ToString(reinterpret_cast(addr)); +} + std::string ipv6ToString(const IPv6bytes addr) { char ipAddress[INET6_ADDRSTRLEN]; const auto res{inet_ntop(AF_INET6, addr, ipAddress, sizeof(ipAddress))}; diff --git a/libservice/src/IpAddressNetlinkChecker.cpp b/libservice/src/IpAddressCheckerImpl.cpp similarity index 56% rename from libservice/src/IpAddressNetlinkChecker.cpp rename to libservice/src/IpAddressCheckerImpl.cpp index 000e5a24..ac000f54 100644 --- a/libservice/src/IpAddressNetlinkChecker.cpp +++ b/libservice/src/IpAddressCheckerImpl.cpp @@ -14,60 +14,29 @@ * limitations under the License. */ -#include "service/IpAddressNetlinkChecker.h" +#include "service/IpAddressCheckerImpl.h" #include "logging/Logger.h" #include #include #include #include -#include #include +#include +#include namespace service { -IpAddressNetlinkChecker::IpAddressNetlinkChecker(const NetlinkCalls& calls) : netlink{calls} { +IpAddressCheckerImpl::IpAddressCheckerImpl(InterfacesReader& interfaceReader) : interfacesReader{interfaceReader} { readNetworks(); } -void IpAddressNetlinkChecker::readNetworks() { - ipInterfaces = netlink.collectIpInterfaces(); - - for (const auto& [index, ipIfce] : ipInterfaces) { - isLocalBridgeMap[index] = false; - } - - for (const auto& index : netlink.collectBridgeIndices()) { - isLocalBridgeMap[index] = true; - } - - ipv6Networks = netlink.collectIpv6Networks(); - - printNetworkInterfacesInfo(); -} - -void IpAddressNetlinkChecker::printNetworkInterfacesInfo() { - LOG_INFO("{} network interfaces have been discovered:", ipInterfaces.size()); - for (const auto& [index, ifce] : ipInterfaces) { - std::string ipAddresses{boost::algorithm::join( - ifce.ip | boost::adaptors::transformed([](auto ip) { - char buff[16]; - return std::string{inet_ntop(AF_INET, &ip, buff, sizeof(buff))}; - }), - ", ")}; - LOG_INFO("index: {}, IP addresses: {}{}", index, ipAddresses, isLocalBridge(index) ? " (local bridge)" : ""); - } - LOG_INFO("{} IPv6 networks have been discovered:", ipv6Networks.size()); - for (const auto& ipv6Network : ipv6Networks) { - char ipv6NetworkAddrString[INET6_ADDRSTRLEN]; - char ipv6NetworkMaskString[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &(ipv6Network.networkIpv6Addr), ipv6NetworkAddrString, INET6_ADDRSTRLEN); - inet_ntop(AF_INET6, &(ipv6Network.networkMask), ipv6NetworkMaskString, INET6_ADDRSTRLEN); - LOG_INFO("Detected IPv6 network: {}, Mask: {}", ipv6NetworkAddrString, ipv6NetworkMaskString); - } +void IpAddressCheckerImpl::readNetworks() { + interfacesReader.collectAllIpInterfaces(); + interfacesReader.printNetworksInfo(); } -bool IpAddressNetlinkChecker::isV4AddressExternal(IPv4int addr) const { +bool IpAddressCheckerImpl::isV4AddressExternal(const in_addr& addr) const { // Special-Purpose IP Address Registries (https://datatracker.ietf.org/doc/html/rfc6890) static const struct { uint32_t network; @@ -93,40 +62,29 @@ bool IpAddressNetlinkChecker::isV4AddressExternal(IPv4int addr) const { }; for (const auto& [network, mask] : reservedRanges) { - if ((htonl(addr) & mask) == network) { + if ((ntohl(addr.s_addr) & mask) == network) { + LOG_DEBUG("Address {} internal, belonging to reserved range (network, mask): {:#x}, {:#x}", + ipv4InAdrToString(addr), + network, + mask); return false; } } - const bool srcLocal{std::any_of(ipInterfaces.begin(), ipInterfaces.end(), [addr, this](const auto& ipInterfaceEntry) { - const auto& [ipInterfaceIndex, ipInterface]{ipInterfaceEntry}; - return std::any_of(ipInterface.ip.begin(), ipInterface.ip.end(), [addr, index = ipInterfaceIndex, this](const auto& ip) { - return !isLocalBridge(index) && addr == ip; - }); - })}; - - if (srcLocal) { - return false; - } - - const bool bridgeRelated{std::any_of(ipInterfaces.begin(), ipInterfaces.end(), [addr, this](const auto& ipInterfaceEntry) { - const auto& [ipInterfaceIndex, ipInterface]{ipInterfaceEntry}; - return std::any_of( - ipInterface.ip.begin(), - ipInterface.ip.end(), - [addr, index = ipInterfaceIndex, mask = ipInterface.mask, this](const auto& ip) { - return isLocalBridge(index) && (addr & mask) == (ip & mask); - }); - })}; - - if (bridgeRelated) { - return false; + for (const auto& ipv4Network : interfacesReader.getIpV4Interfaces()) { + if (checkSubnetIpv4(addr, ipv4Network.networkIpv4Addr, ipv4Network.networkMask)) { + LOG_DEBUG("Address {} internal, belonging to local interface (addr, mask): {}, {}", + ipv4InAdrToString(addr), + ipv4InAdrToString(ipv4Network.networkIpv4Addr), + ipv4InAdrToString(ipv4Network.networkMask)); + return false; + } } return true; } -bool IpAddressNetlinkChecker::ipv6AddressContainsMappedIpv4Address(const in6_addr& addr) const { +bool IpAddressCheckerImpl::ipv6AddressContainsMappedIpv4Address(const in6_addr& addr) const { for (const auto& internalRange : {"::ffff:0:0/96", "::ffff:0:0:0/96", "64:ff9b::/96"}) { if (isInRange(addr, internalRange)) { return true; @@ -136,7 +94,7 @@ bool IpAddressNetlinkChecker::ipv6AddressContainsMappedIpv4Address(const in6_add return false; } -std::optional IpAddressNetlinkChecker::getMappedIPv4Addr(const in6_addr& addr) const { +std::optional IpAddressCheckerImpl::getMappedIPv4Addr(const in6_addr& addr) const { if (!ipv6AddressContainsMappedIpv4Address(addr)) { return std::nullopt; } @@ -145,7 +103,7 @@ std::optional IpAddressNetlinkChecker::getMappedIPv4Addr(const in6_addr return ipv4Binary; } -IpAddressNetlinkChecker::ipv6Range IpAddressNetlinkChecker::parseIpv6Range(const std::string& range) const { +IpAddressCheckerImpl::ipv6Range IpAddressCheckerImpl::parseIpv6Range(const std::string& range) const { ipv6Range rangeStruct; const auto slashPos{range.find('/')}; rangeStruct.ipv6Address = range.substr(0, slashPos); @@ -153,8 +111,8 @@ IpAddressNetlinkChecker::ipv6Range IpAddressNetlinkChecker::parseIpv6Range(const return rangeStruct; } -bool IpAddressNetlinkChecker::isInRange(const in6_addr& addr, const std::string& range) const { - auto rangeStruct{IpAddressNetlinkChecker::parseIpv6Range(range)}; +bool IpAddressCheckerImpl::isInRange(const in6_addr& addr, const std::string& range) const { + auto rangeStruct{IpAddressCheckerImpl::parseIpv6Range(range)}; in6_addr rangeIpv6Address{}; inet_pton(AF_INET6, rangeStruct.ipv6Address.c_str(), &rangeIpv6Address); @@ -183,7 +141,7 @@ bool IpAddressNetlinkChecker::isInRange(const in6_addr& addr, const std::string& return memcmp(&andResult, &rangeIpv6Address, sizeof(andResult)) == 0; } -bool IpAddressNetlinkChecker::checkSubnet( +bool IpAddressCheckerImpl::checkSubnet( const in6_addr& addrToCheck, const in6_addr& interfaceIpv6Addr, const in6_addr& interfaceMask) const { const auto s6Addr32ArraySize = sizeof(addrToCheck.s6_addr32) / sizeof(addrToCheck.s6_addr32[0]); for (size_t i = 0; i < s6Addr32ArraySize; ++i) { @@ -194,19 +152,26 @@ bool IpAddressNetlinkChecker::checkSubnet( return true; } -bool IpAddressNetlinkChecker::isV6AddressExternal(const in6_addr& addr) const { +bool IpAddressCheckerImpl::checkSubnetIpv4( + const in_addr& addrToCheck, const in_addr& interfaceIpv4Addr, const in_addr& interfaceMask) const { + if ((addrToCheck.s_addr & interfaceMask.s_addr) != (interfaceIpv4Addr.s_addr & interfaceMask.s_addr)) { + return false; + } + return true; +} +bool IpAddressCheckerImpl::isV6AddressExternal(const in6_addr& addr) const { if (auto mappedV4Addr = getMappedIPv4Addr(addr); mappedV4Addr) { - return isV4AddressExternal(*mappedV4Addr); + return isV4AddressExternal(static_cast(*mappedV4Addr)); } - for (auto& ipv6Network : ipv6Networks) { + for (auto& ipv6Network : interfacesReader.getIpV6Interfaces()) { if (checkSubnet(addr, ipv6Network.networkIpv6Addr, ipv6Network.networkMask)) { return false; } } for (const auto& internalRange : {"fc00::/7", "fec0::/10", "fe80::/10", "::1/128"}) { - if (IpAddressNetlinkChecker::isInRange(addr, internalRange)) { + if (isInRange(addr, internalRange)) { return false; } } diff --git a/libservice/src/NetlinkCalls.cpp b/libservice/src/NetlinkCalls.cpp deleted file mode 100644 index 5b4e6b81..00000000 --- a/libservice/src/NetlinkCalls.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright 2023 Dynatrace LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "service/NetlinkCalls.h" - -#include -#include -#include -#include -#include - -#include "NetlinkSocket.h" -#include "logging/Logger.h" - -namespace service { - -static constexpr uint32_t BUFFLEN{4096}; - -static void addNetlinkMsg(nlmsghdr* nh, int type, const void* data, int dataLen) { - struct rtattr* rta; - int rta_length = RTA_LENGTH(dataLen); - - rta = reinterpret_cast((char*)nh + NLMSG_ALIGN(nh->nlmsg_len)); - - rta->rta_type = type; - rta->rta_len = rta_length; - nh->nlmsg_len = NLMSG_ALIGN(nh->nlmsg_len) + RTA_ALIGN(rta_length); - - memcpy(RTA_DATA(rta), data, dataLen); -} - -static int sendIpAddrRequest(const NetlinkSocket& netlinkSocket, sockaddr_nl* dst, int domain) { - std::array buf{}; - - nlmsghdr* nl; - nl = reinterpret_cast(buf.data()); - nl->nlmsg_len = NLMSG_LENGTH(sizeof(ifaddrmsg)); - nl->nlmsg_type = RTM_GETADDR; - nl->nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; - - ifaddrmsg* ifa; - ifa = reinterpret_cast(NLMSG_DATA(nl)); - ifa->ifa_family = domain; // ipv4 or ipv6 - - iovec iov = {nl, nl->nlmsg_len}; - msghdr msg = {dst, sizeof(*dst), &iov, 1, NULL, 0, 0}; - - return netlinkSocket.send(&msg, 0); -} - -static int sendBridgesRequest(const NetlinkSocket& netlinkSocket, sockaddr_nl* dst, int domain) { - struct { - struct nlmsghdr n; - struct ifinfomsg i; - char _[1024]; // space for rtattr array - } r{}; - - const char* dev_type = "bridge"; - - r.n.nlmsg_len = NLMSG_LENGTH(sizeof(ifinfomsg)); - r.n.nlmsg_type = RTM_GETLINK; - r.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; - r.i.ifi_family = AF_PACKET; - r.n.nlmsg_pid = 0; - r.n.nlmsg_seq = 0; - - rtattr* linkinfo = reinterpret_cast((char*)&r.n + NLMSG_ALIGN(r.n.nlmsg_len)); - addNetlinkMsg(&r.n, IFLA_LINKINFO, NULL, 0); - addNetlinkMsg(&r.n, IFLA_INFO_KIND, dev_type, strlen(dev_type) + 1); - linkinfo->rta_len = (int)(reinterpret_cast(&r.n) + NLMSG_ALIGN(r.n.nlmsg_len) - reinterpret_cast(linkinfo)); - - iovec iov = {&r.n, r.n.nlmsg_len}; - msghdr msg = {dst, sizeof(*dst), &iov, 1, NULL, 0, 0}; - - return netlinkSocket.send(&msg, 0); -} - -static int receive(const NetlinkSocket& netlinkSocket, sockaddr_nl* dst, void* buf, size_t len) { - iovec iov; - msghdr msg{}; - iov.iov_base = buf; - iov.iov_len = len; - - msg.msg_name = dst; - msg.msg_namelen = sizeof(*dst); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - return netlinkSocket.receive(&msg, 0); -} - -static IpInterfaces::value_type parseIfceIPv4(void* data, size_t len) { - IpIfce ifce{}; - ifaddrmsg* ifa = reinterpret_cast(data); - ifce.mask = htonl(-1 << (32 - ifa->ifa_prefixlen)); - rtattr* rta = reinterpret_cast(IFA_RTA(data)); - - for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) { - in_addr* addr = reinterpret_cast(RTA_DATA(rta)); - - if (rta->rta_type == IFA_ADDRESS) { - ifce.ip.push_back(addr->s_addr); - } - - if (rta->rta_type == IFA_BROADCAST) { - ifce.broadcast.push_back(addr->s_addr); - } - } - - return {ifa->ifa_index, ifce}; -} - -template -T parse(void* data, size_t len); - -template <> -IpInterfaces::value_type parse(void* data, size_t len) { - if (reinterpret_cast(data)->ifa_family != AF_INET) { - return {}; - } - - return parseIfceIPv4(data, len); -} - -template <> -BridgeIndices::value_type parse(void* data, size_t len) { - ifinfomsg* ifa = reinterpret_cast(data); - return ifa->ifi_index; -} - -template -struct ParseResult { - uint32_t nlMsgType; - Data data; -}; - -void insert(const IpInterfaces::value_type& data, IpInterfaces& ipInterfaces) { - ipInterfaces.emplace(data); -} - -void insert(const BridgeIndices::value_type& data, BridgeIndices& bridgeIndices) { - bridgeIndices.push_back(data); -} - -template -static ParseResult parseNlMsg(void* buf, size_t len) { - const nlmsghdr* nl = reinterpret_cast(buf); - ParseResult parseResult{.nlMsgType = nl->nlmsg_type}; - - for (; NLMSG_OK(nl, len) && nl->nlmsg_type != NLMSG_DONE; nl = NLMSG_NEXT(nl, len)) { - if (nl->nlmsg_type == NLMSG_ERROR) { - const auto err{reinterpret_cast(NLMSG_DATA(nl))}; - LOG_WARN("Error while receiving netlink message: {}", std::strerror(err->error)); - break; - } - - if (nl->nlmsg_type == RTM_NEWADDR || nl->nlmsg_type == RTM_NEWLINK) { - insert(parse(NLMSG_DATA(nl), IFA_PAYLOAD(nl)), parseResult.data); - } - } - - return parseResult; -} - -template -Data receive(const NetlinkSocket& netlinkSocket, sockaddr_nl* dst) { - Data result; - for (;;) { - std::array buf{}; - const auto len{receive(netlinkSocket, dst, buf.data(), BUFFLEN)}; - - if (len <= 0) { - LOG_WARN("Error while receiving netlink message: {}", strerror(errno)); - break; - } - - const auto [nlMsgType, data]{parseNlMsg(buf.data(), len)}; - - if (nlMsgType == NLMSG_ERROR) { - break; - } - - for (const auto& entry : data) { - insert(entry, result); - } - - if (nlMsgType == NLMSG_DONE) { - break; - } - } - - return result; -} - -IpInterfaces receiveIpAddr(const NetlinkSocket& netlinkSocket, sockaddr_nl* dst) { - return receive(netlinkSocket, dst); -} - -BridgeIndices receiveBridgeIndex(const NetlinkSocket& netlinkSocket, sockaddr_nl* dst) { - return receive(netlinkSocket, dst); -} - -template -Data handleNetlink(const Send& send, const Receive& receive, int domain) { - NetlinkSocket netlinkSocket; - if (!netlinkSocket) { - LOG_WARN("Error while opening netlink socket: {}", strerror(errno)); - return {}; - } - - sockaddr_nl sa{}; - sa.nl_family = AF_NETLINK; - - int len = send(netlinkSocket, &sa, domain); - if (len <= 0) { - LOG_WARN("Error while sending netlink request: {}", strerror(errno)); - return {}; - } - - return receive(netlinkSocket, &sa); -} - -IpInterfaces NetlinkCalls::collectIpInterfaces() const { - return handleNetlink(sendIpAddrRequest, receiveIpAddr, AF_INET); -} - -std::vector NetlinkCalls::collectIpv6Networks() const { - std::vector collectedIpv6Networks{}; - - ifaddrs* ifAddressStruct = nullptr; - if (getifaddrs(&ifAddressStruct) == 0) { - for (ifaddrs* ifa = ifAddressStruct; ifa != nullptr; ifa = ifa->ifa_next) { - if (ifa->ifa_addr != nullptr && ifa->ifa_addr->sa_family == AF_INET6) { - in6_addr networkIpv6Addr = reinterpret_cast(ifa->ifa_addr)->sin6_addr; - in6_addr networkMask = reinterpret_cast(ifa->ifa_netmask)->sin6_addr; - - collectedIpv6Networks.emplace_back(Ipv6Network{networkIpv6Addr, networkMask}); - } - } - freeifaddrs(ifAddressStruct); - } - - return collectedIpv6Networks; -} - -BridgeIndices NetlinkCalls::collectBridgeIndices() const { - return handleNetlink( - sendBridgesRequest, receiveBridgeIndex, AF_INET); -} - -} // namespace service diff --git a/libservice/test/AggregatorTest.cpp b/libservice/test/AggregatorTest.cpp index 9d39f672..ed8167f8 100644 --- a/libservice/test/AggregatorTest.cpp +++ b/libservice/test/AggregatorTest.cpp @@ -16,7 +16,7 @@ #include "service/Aggregator.h" -#include "service/IpAddressNetlinkChecker.h" +#include "service/IpAddressCheckerImpl.h" #include #include @@ -33,7 +33,7 @@ void PrintTo(const Service& service, std::ostream* os) { class IpAddressCheckerMock : public IpAddressChecker { public: - MOCK_METHOD(bool, isV4AddressExternal, (IPv4int), (const)); + MOCK_METHOD(bool, isV4AddressExternal, (const in_addr&), (const)); MOCK_METHOD(bool, isV6AddressExternal, (const in6_addr&), (const)); }; @@ -61,7 +61,7 @@ struct ServiceAggregatorTest : public testing::Test { return {request, meta}; } - const NetlinkCalls netlink; + const InterfacesReader netlink; IpAddressCheckerMock ipCheckerMock; }; diff --git a/libservice/test/NetlinkCallsMock.h b/libservice/test/InterfacesReaderMock.h similarity index 72% rename from libservice/test/NetlinkCallsMock.h rename to libservice/test/InterfacesReaderMock.h index 4f9b3d14..3c9e5d87 100644 --- a/libservice/test/NetlinkCallsMock.h +++ b/libservice/test/InterfacesReaderMock.h @@ -18,15 +18,16 @@ #include -#include "service/NetlinkCalls.h" +#include "service/InterfacesReader.h" namespace service { -class NetlinkCallsMock : public NetlinkCalls { +class InterfacesReaderMock : public InterfacesReader { public: - MOCK_CONST_METHOD0(collectIpInterfaces, IpInterfaces()); - MOCK_CONST_METHOD0(collectBridgeIndices, BridgeIndices()); MOCK_CONST_METHOD0(collectIpv6Networks, std::vector()); + MOCK_CONST_METHOD0(getIpV4Interfaces, std::vector()); + MOCK_CONST_METHOD0(getIpV6Interfaces, std::vector()); + MOCK_METHOD(void, collectAllIpInterfaces, (), (override)); }; } // namespace service diff --git a/libservice/test/IpAddressCheckerTest.cpp b/libservice/test/IpAddressCheckerTest.cpp index dd7b80fa..4de0b122 100644 --- a/libservice/test/IpAddressCheckerTest.cpp +++ b/libservice/test/IpAddressCheckerTest.cpp @@ -14,8 +14,8 @@ * limitations under the License. */ -#include "NetlinkCallsMock.h" -#include "service/IpAddressNetlinkChecker.h" +#include "InterfacesReaderMock.h" +#include "service/IpAddressCheckerImpl.h" #include #include @@ -26,243 +26,240 @@ using namespace ::testing; class IpAddressCheckerTest : public Test { public: - NiceMock netlinkMock; + NiceMock netlinkMock; }; +static in_addr getV4AddrBinary(const std::string& addr) { + in_addr clientAddrBinary{}; + inet_pton(AF_INET, addr.c_str(), &clientAddrBinary); + return clientAddrBinary; +} + // 0.0.0.0/8 TEST_F(IpAddressCheckerTest, Test0_0_0_0_8) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; // Range boundaries - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("0.0.0.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("0.255.255.255"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("0.0.0.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("0.255.255.255"))); // Middle of the range - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("0.54.189.245"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("0.128.0.1"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("0.54.189.245"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("0.128.0.1"))); } // 10.0.0.0/8 TEST_F(IpAddressCheckerTest, Test10_0_0_0_8) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; // Range boundaries - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("10.0.0.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("10.255.255.255"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("10.0.0.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("10.255.255.255"))); // Middle of the range - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("10.54.189.245"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("10.128.0.1"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("10.54.189.245"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("10.128.0.1"))); } // 100.64.0.0/10 TEST_F(IpAddressCheckerTest, Test100_64_0_0_10) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; // Range boundaries - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("100.64.0.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("100.127.255.255"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("100.64.0.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("100.127.255.255"))); // Middle of the range - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("100.64.128.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("100.66.0.1"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("100.64.128.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("100.66.0.1"))); } // 127.0.0.0/8 TEST_F(IpAddressCheckerTest, Test127_0_0_0_8) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; // Range boundaries - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("127.0.0.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("127.255.255.255"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("127.0.0.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("127.255.255.255"))); // Middle of the range - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("127.0.0.1"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("127.128.0.1"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("127.0.0.1"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("127.128.0.1"))); } // 169.254.0.0/16 TEST_F(IpAddressCheckerTest, Test169_254_0_0_16) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; // Range boundaries - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("169.254.0.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("169.254.255.255"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("169.254.0.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("169.254.255.255"))); // Middle of the range - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("169.254.128.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("169.254.192.1"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("169.254.128.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("169.254.192.1"))); } // 172.16.0.0/12 TEST_F(IpAddressCheckerTest, Test172_16_0_0_12) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; // Range boundaries - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("172.16.0.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("172.31.255.255"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("172.16.0.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("172.31.255.255"))); // Middle of the range - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("172.20.0.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("172.24.0.1"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("172.20.0.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("172.24.0.1"))); } // 192.0.0.0/24 TEST_F(IpAddressCheckerTest, Test192_0_0_0_24) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; // Range boundaries - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("192.0.0.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("192.0.0.255"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("192.0.0.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("192.0.0.255"))); // Middle of the range - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("192.0.0.128"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("192.0.0.1"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("192.0.0.128"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("192.0.0.1"))); } // 192.0.2.0/24 TEST_F(IpAddressCheckerTest, Test192_0_2_0_24) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; // Range boundaries - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("192.0.2.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("192.0.2.255"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("192.0.2.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("192.0.2.255"))); // Middle of the range - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("192.0.2.128"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("192.0.2.1"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("192.0.2.128"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("192.0.2.1"))); } // 192.88.99.0/24 TEST_F(IpAddressCheckerTest, Test192_88_99_0_24) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; // Range boundaries - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("192.88.99.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("192.88.99.255"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("192.88.99.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("192.88.99.255"))); // Middle of the range - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("192.88.99.128"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("192.88.99.1"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("192.88.99.128"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("192.88.99.1"))); } // 192.168.0.0/ TEST_F(IpAddressCheckerTest, Test192_168_0_0_16) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; // Range boundaries - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("192.168.0.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("192.168.255.255"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("192.168.0.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("192.168.255.255"))); // Middle of the range - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("192.168.128.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("192.168.192.1"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("192.168.128.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("192.168.192.1"))); } // 198.18.0.0/15 TEST_F(IpAddressCheckerTest, Test198_18_0_0_15) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; // Range boundaries - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("198.18.0.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("198.19.255.255"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("198.18.0.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("198.19.255.255"))); // Middle of the range - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("198.18.128.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("198.18.192.1"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("198.18.128.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("198.18.192.1"))); } // 198.51.100.0/24 TEST_F(IpAddressCheckerTest, Test198_51_100_0_24) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; // Range boundaries - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("198.51.100.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("198.51.100.255"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("198.51.100.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("198.51.100.255"))); // Middle of the range - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("198.51.100.128"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("198.51.100.1"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("198.51.100.128"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("198.51.100.1"))); } // 203.0.113.0/24 TEST_F(IpAddressCheckerTest, Test203_0_113_0_24) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; // Range boundaries - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("203.0.113.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("203.0.113.255"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("203.0.113.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("203.0.113.255"))); // Middle of the range - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("203.0.113.128"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("203.0.113.1"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("203.0.113.128"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("203.0.113.1"))); } // 224.0.0.0/4 TEST_F(IpAddressCheckerTest, Test224_0_0_0_4) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; // Range boundaries - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("224.0.0.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("239.255.255.255"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("224.0.0.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("239.255.255.255"))); // Middle of the range - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("225.128.0.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("230.0.0.1"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("225.128.0.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("230.0.0.1"))); } // 233.252.0.0/24 TEST_F(IpAddressCheckerTest, Test233_252_0_0_24) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; // Range boundaries - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("233.252.0.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("233.252.0.255"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("233.252.0.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("233.252.0.255"))); // Middle of the range - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("233.252.0.128"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("233.252.0.1"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("233.252.0.128"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("233.252.0.1"))); } // 240.0.0.0/4 TEST_F(IpAddressCheckerTest, Test240_0_0_0_4) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; // Range boundaries - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("240.0.0.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("255.255.255.254"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("240.0.0.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("255.255.255.254"))); // Middle of the range - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("241.128.0.0"))); - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("248.0.0.1"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("241.128.0.0"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("248.0.0.1"))); } // 255.255.255.255/32 TEST_F(IpAddressCheckerTest, Test255_255_255_255_32) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; - - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("255.255.255.255"))); -} - -TEST_F(IpAddressCheckerTest, LocalBridgeIp) { - EXPECT_CALL(netlinkMock, collectIpInterfaces).WillOnce(Return(IpInterfaces{{0, IpIfce{{inet_addr("142.15.4.0")}, {}, 0x0000ffff}}})); - EXPECT_CALL(netlinkMock, collectBridgeIndices).WillOnce(Return(BridgeIndices{0})); - - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("142.15.6.5"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("255.255.255.255"))); } TEST_F(IpAddressCheckerTest, LocalIfceIpSrc) { - EXPECT_CALL(netlinkMock, collectIpInterfaces) - .WillOnce(Return(IpInterfaces{ - {0, IpIfce{{inet_addr("115.89.3.7")}, {}, 0x0000ffff}}, - })); - EXPECT_CALL(netlinkMock, collectBridgeIndices).WillOnce(Return(BridgeIndices{})); + EXPECT_CALL(netlinkMock, collectAllIpInterfaces); + EXPECT_CALL(netlinkMock,getIpV4Interfaces ) + .WillOnce(Return(std::vector{ + {{getV4AddrBinary("115.89.3.7")},{0x0000ffff}, {}} + })); - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; - EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(inet_addr("115.89.3.7"))); + EXPECT_FALSE(ipAddressNetlinkChecker.isV4AddressExternal(getV4AddrBinary("115.89.3.7"))); } static in6_addr getV6AddrBinary(const std::string& addr) { @@ -273,7 +270,7 @@ static in6_addr getV6AddrBinary(const std::string& addr) { // IPv4 mapped to IPv6 TEST_F(IpAddressCheckerTest, TestMapped) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; // mapped IPv4 EXPECT_FALSE(ipAddressNetlinkChecker.isV6AddressExternal(getV6AddrBinary("::FFFF:192.168.0.5"))); @@ -295,7 +292,7 @@ TEST_F(IpAddressCheckerTest, TestMapped) { // unique local address (prefix fc00::/7) TEST_F(IpAddressCheckerTest, UniqueLocalAddress) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; EXPECT_FALSE(ipAddressNetlinkChecker.isV6AddressExternal(getV6AddrBinary("fc00::1"))); EXPECT_FALSE(ipAddressNetlinkChecker.isV6AddressExternal(getV6AddrBinary("fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"))); @@ -305,7 +302,7 @@ TEST_F(IpAddressCheckerTest, UniqueLocalAddress) { // site local addresses (fec0::/10 - deprecated) TEST_F(IpAddressCheckerTest, SiteLocalAddress) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; EXPECT_FALSE(ipAddressNetlinkChecker.isV6AddressExternal(getV6AddrBinary("fec0::"))); EXPECT_FALSE(ipAddressNetlinkChecker.isV6AddressExternal(getV6AddrBinary("feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"))); @@ -314,7 +311,7 @@ TEST_F(IpAddressCheckerTest, SiteLocalAddress) { // link local addresses (fe80::/10) TEST_F(IpAddressCheckerTest, LinkLocalAddress) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; EXPECT_FALSE(ipAddressNetlinkChecker.isV6AddressExternal(getV6AddrBinary("fe80::"))); EXPECT_FALSE(ipAddressNetlinkChecker.isV6AddressExternal(getV6AddrBinary("febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff"))); @@ -323,7 +320,7 @@ TEST_F(IpAddressCheckerTest, LinkLocalAddress) { // loopback addresses (::1/128) TEST_F(IpAddressCheckerTest, LoopbackAddress) { - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; EXPECT_FALSE(ipAddressNetlinkChecker.isV6AddressExternal(getV6AddrBinary("::1"))); EXPECT_TRUE(ipAddressNetlinkChecker.isV6AddressExternal(getV6AddrBinary("::"))); @@ -338,11 +335,9 @@ TEST_F(IpAddressCheckerTest, Ipv6NetworkSubnet) { inet_pton(AF_INET6, "2001:db8:85a3::8a2e:370:7336", &ipv6NetworkAddr); inet_pton(AF_INET6, "ffff:ffff:ffff:ffff::", &ipv6NetworkMask); - EXPECT_CALL(netlinkMock, collectIpv6Networks).WillOnce(Return(std::vector{{service::NetlinkCalls::Ipv6Network{ipv6NetworkAddr, ipv6NetworkMask}}})); - EXPECT_CALL(netlinkMock, collectIpInterfaces).WillOnce(Return(IpInterfaces{0})); - EXPECT_CALL(netlinkMock, collectBridgeIndices).WillOnce(Return(BridgeIndices{0})); + EXPECT_CALL(netlinkMock, getIpV6Interfaces).WillRepeatedly(Return(std::vector{{Ipv6Network{ipv6NetworkAddr, ipv6NetworkMask}}})); - IpAddressNetlinkChecker ipAddressNetlinkChecker{netlinkMock}; + IpAddressCheckerImpl ipAddressNetlinkChecker{netlinkMock}; EXPECT_FALSE(ipAddressNetlinkChecker.isV6AddressExternal(getV6AddrBinary("2001:0db8:85a3:0000:0000:0000:0000:0000"))); EXPECT_TRUE(ipAddressNetlinkChecker.isV6AddressExternal(getV6AddrBinary("2001:0db8:85a3:0001:0000:0000:0000:0000"))); diff --git a/test/component/test_discovery.py b/test/component/test_discovery.py index 7644edc4..0c8b66c3 100644 --- a/test/component/test_discovery.py +++ b/test/component/test_discovery.py @@ -102,8 +102,8 @@ def test_request_forwarded_to_local_interface_with_public_ip(network_interfaces, expected_external_ipv4_24_networks=0, expected_external_ipv6_networks=0) -@pytest.mark.parametrize('network_interfaces', [[('dummy', 'eth16', '113.56.3.22', 16)]], indirect=True) -def test_request_forwarded_to_public_ip_matching_local_interface_mask(network_interfaces, run_ebpf_discovery, run_http_service): +@pytest.mark.parametrize('network_interfaces', [[('dummy', 'eth16', '113.56.3.22', 24)]], indirect=True) +def test_request_forwarded_to_public_ip_not_matching_local_interface_mask(network_interfaces, run_ebpf_discovery, run_http_service): url = run_http_service + "/forwarded" send_http_requests(url, 1, "113.56.1.57:8080") assert discovered_service_has_expected_clients(run_ebpf_discovery, url, @@ -231,10 +231,10 @@ def test_request_forwarded_to_public_ip_matching_local_interface_mask(network_in url = run_http_service + "/forwarded" send_http_requests(url, 1, "113.56.1.57:8080") assert discovered_service_has_expected_clients(run_ebpf_discovery_with_network_counters, url, - expected_internal_clients=0, - expected_external_clients=1, - expected_external_ipv4_16_networks=1, - expected_external_ipv4_24_networks=1, + expected_internal_clients=1, + expected_external_clients=0, + expected_external_ipv4_16_networks=0, + expected_external_ipv4_24_networks=0, expected_external_ipv6_networks=0) @pytest.mark.parametrize('network_interfaces', [[('dummy', 'eth19', '2001:db8:85a3::8a2e:370:7336', 64)]], indirect=True)