]> www.infradead.org Git - users/sagi/libnvme.git/commitdiff
util: Add functions to parse the system's interfaces
authorMartin Belanger <martin.belanger@dell.com>
Fri, 18 Aug 2023 01:28:57 +0000 (21:28 -0400)
committerDaniel Wagner <wagi@monom.org>
Wed, 30 Aug 2023 15:21:59 +0000 (17:21 +0200)
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 <martin.belanger@dell.com>
src/nvme/util.c
src/nvme/util.h

index 77584538bfb26072b06f2c323288d4347e513eca..8fe094d55ef8556b1e88d36148565c5ba952377e 100644 (file)
@@ -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 */
index 9d6faf366a6ecd9462c7b51a789bb93cd43e21b6..0739cf2fb9629a0ac883aee6556dedfab36eccdd 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef _LIBNVME_UTIL_H
 #define _LIBNVME_UTIL_H
 
+#include <ifaddrs.h>
+
 #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 */