From: Martin Belanger Date: Fri, 18 Aug 2023 01:28:57 +0000 (-0400) Subject: util: Add functions to parse the system's interfaces X-Git-Tag: v1.6~43 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=ead417d45b3e7409e217224227f5c2015a272a63;p=users%2Fsagi%2Flibnvme.git util: Add functions to parse the system's interfaces 1) nvme_iface_matching_addr() identifies which interface owns a specific IP address. 2) nvme_iface_primary_addr_matches() checks that the primary IP address of a given interface matches a specific IP address. Signed-off-by: Martin Belanger --- diff --git a/src/nvme/util.c b/src/nvme/util.c index 77584538..8fe094d5 100644 --- a/src/nvme/util.c +++ b/src/nvme/util.c @@ -982,3 +982,79 @@ bool nvme_ipaddrs_eq(const char *addr1, const char *addr2) return false; } #endif /* HAVE_NETDB */ + +#ifdef HAVE_NETDB +const char *nvme_iface_matching_addr(const struct ifaddrs *iface_list, const char *addr) +{ + const struct ifaddrs *iface_it; + struct addrinfo *info = NULL, hint = { .ai_flags = AI_NUMERICHOST, .ai_family = AF_UNSPEC }; + const char *iface_name = NULL; + + if (!iface_list || !addr || getaddrinfo(addr, 0, &hint, &info) || !info) + return NULL; + + /* Walk through the linked list */ + for (iface_it = iface_list; iface_it != NULL; iface_it = iface_it->ifa_next) { + struct sockaddr *ifaddr = iface_it->ifa_addr; + + if (ifaddr && (ifaddr->sa_family == AF_INET || ifaddr->sa_family == AF_INET6) && + _nvme_ipaddrs_eq(info->ai_addr, ifaddr)) { + iface_name = iface_it->ifa_name; + break; + } + } + + freeaddrinfo(info); + + return iface_name; +} + +bool nvme_iface_primary_addr_matches(const struct ifaddrs *iface_list, const char *iface, const char *addr) +{ + const struct ifaddrs *iface_it; + struct addrinfo *info = NULL, hint = { .ai_flags = AI_NUMERICHOST, .ai_family = AF_UNSPEC }; + bool match_found = false; + + if (!iface_list || !addr || getaddrinfo(addr, 0, &hint, &info) || !info) + return false; + + /* Walk through the linked list */ + for (iface_it = iface_list; iface_it != NULL; iface_it = iface_it->ifa_next) { + if (strcmp(iface, iface_it->ifa_name)) + continue; /* Not the interface we're looking for*/ + + /* The interface list is ordered in a way that the primary + * address is listed first. As soon as the parsed address + * matches the family of the address we're looking for, we + * have found the primary address for that family. + */ + if (iface_it->ifa_addr && (iface_it->ifa_addr->sa_family == info->ai_addr->sa_family)) { + match_found = _nvme_ipaddrs_eq(info->ai_addr, iface_it->ifa_addr); + break; + } + } + + freeaddrinfo(info); + + return match_found; +} + +#else /* HAVE_NETDB */ + +const char *nvme_iface_matching_addr(const struct ifaddrs *iface_list, const char *addr) +{ + nvme_msg(NULL, LOG_ERR, "no support for interface lookup; " + "recompile with libnss support.\n"); + + return NULL; +} + +bool nvme_iface_primary_addr_matches(const struct ifaddrs *iface_list, const char *iface, const char *addr) +{ + nvme_msg(NULL, LOG_ERR, "no support for interface lookup; " + "recompile with libnss support.\n"); + + return false; +} + +#endif /* HAVE_NETDB */ diff --git a/src/nvme/util.h b/src/nvme/util.h index 9d6faf36..0739cf2f 100644 --- a/src/nvme/util.h +++ b/src/nvme/util.h @@ -9,6 +9,8 @@ #ifndef _LIBNVME_UTIL_H #define _LIBNVME_UTIL_H +#include + #include "types.h" /** @@ -639,4 +641,31 @@ int nvme_uuid_random(unsigned char uuid[NVME_UUID_LEN]); */ bool nvme_ipaddrs_eq(const char *addr1, const char *addr2); +/** + * nvme_iface_matching_addr - Get interface matching @addr + * @iface_list: Interface list returned by getifaddrs() + * @addr: Address to match + * + * Parse the interface list pointed to by @iface_list looking + * for the interface that has @addr as one of its assigned + * addresses. + * + * Return: The name of the interface that owns @addr or NULL. + */ +const char *nvme_iface_matching_addr(const struct ifaddrs *iface_list, const char *addr); + +/** + * nvme_iface_primary_addr_matches - Check that interface's primary address matches + * @iface_list: Interface list returned by getifaddrs() + * @iface: Interface to match + * @addr: Address to match + * + * Parse the interface list pointed to by @iface_list and looking for + * interface @iface. The get its primary address and check if it matches + * @addr. + * + * Return: true if a match is found, false otherwise. + */ +bool nvme_iface_primary_addr_matches(const struct ifaddrs *iface_list, const char *iface, const char *addr); + #endif /* _LIBNVME_UTIL_H */