In order to assist with existing pool source hostname validation against
an incoming pool source definition, we need a way to validate that the
resolved hostname provided for the pool doesn't match some existing
pool; otherwise, we'd have a scenario where two storage pools could be
looking at the same data.
Search through all the existing pools resolved names against the proposed
definitions resolved hostnames - if any match, we return true; otherwise,
false is returned
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/virutil.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++
src/util/virutil.h | 2 +
3 files changed, 109 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 5ba9635..a5f4d7f 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2323,6 +2323,7 @@ virIndexToDiskName;
virIsCapableFCHost;
virIsCapableVport;
virIsDevMapperDevice;
+virIsSameHostnameInfo;
virIsSUID;
virIsValidHostname;
virManageVport;
diff --git a/src/util/virutil.c b/src/util/virutil.c
index f6cc9af..c152b8c 100644
--- a/src/util/virutil.c
+++ b/src/util/virutil.c
@@ -739,6 +739,112 @@ virIsValidHostname(const char *hostname)
}
+/*
+ * virIsSameHostnameInfo:
+ *
+ * Take two hostname representations and compare their 'getnameinfo' results
+ * to ensure that they differ. This will be used by the network storage pool
+ * validation to ensure an incoming definition doesn't match some existing
+ * pool definition just because someone tried to change the hostname string
+ * representation. For example, "localhost" and "127.0.0.1" would
fail the
+ * plain STREQ check, but they essentially are the same host, so the incoming
+ * definition should be rejected since a pool for the host already exists.
+ *
+ * @poolhostname: String stored as the pool's hostname
+ * @defhostname: String to be used by the def's hostname
+ *
+ * Returns true if they are the same, false if not
+ */
+bool
+virIsSameHostnameInfo(const char *poolhostname,
+ const char *defhostname)
+{
+ int r;
+ struct addrinfo poolhints, *poolinfo = NULL, *poolcur;
+ struct addrinfo defhints, *definfo = NULL, *defcur;
+ char poolhost[NI_MAXHOST];
+ char defhost[NI_MAXHOST];
+
+ memset(&poolhints, 0, sizeof(poolhints));
+ poolhints.ai_family = AF_UNSPEC;
+ poolhints.ai_protocol = IPPROTO_TCP;
+
+ if ((r = getaddrinfo(poolhostname, NULL, &poolhints, &poolinfo)) != 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("IP address lookup for poolhostname '%s' failed:
%s"),
+ poolhostname, gai_strerror(r));
+ return false;
+ }
+
+ if (!poolinfo) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("No IP address for poolhostname '%s' found"),
+ poolhostname);
+ return false;
+ }
+
+ memset(&defhints, 0, sizeof(defhints));
+ defhints.ai_family = AF_UNSPEC;
+ defhints.ai_protocol = IPPROTO_TCP;
+
+ if ((r = getaddrinfo(defhostname, NULL, &defhints, &definfo)) != 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("IP address lookup for defhostname '%s' failed:
%s"),
+ defhostname, gai_strerror(r));
+ goto cleanup;
+ }
+
+ if (!definfo) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("No IP address for defhostname '%s' found"),
+ defhostname);
+ goto cleanup;
+ }
+
+ for (poolcur = poolinfo; poolcur; poolcur = poolcur->ai_next) {
+
+ if ((r = getnameinfo(poolcur->ai_addr, poolcur->ai_addrlen,
+ poolhost, sizeof(poolhost), NULL, 0,
+ NI_NUMERICHOST)) != 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Formatting IP address for poolhost '%s'
"
+ "failed: %s"),
+ poolhostname, gai_strerror(r));
+ goto cleanup;
+ }
+
+
+ for (defcur = definfo; defcur; defcur = defcur->ai_next) {
+ if ((r = getnameinfo(defcur->ai_addr, defcur->ai_addrlen,
+ defhost, sizeof(defhost), NULL, 0,
+ NI_NUMERICHOST)) != 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Formatting IP address for defhost '%s'
"
+ "failed: %s"),
+ defhostname, gai_strerror(r));
+ goto cleanup;
+ }
+
+ if (poolcur->ai_family != defcur->ai_family)
+ continue;
+
+ if (STREQ(poolhost, defhost)) {
+ freeaddrinfo(poolinfo);
+ freeaddrinfo(definfo);
+ return true;
+ }
+ }
+ }
+
+ cleanup:
+ if (poolinfo)
+ freeaddrinfo(poolinfo);
+ if (definfo)
+ freeaddrinfo(definfo);
+ return false;
+}
+
+
char *
virGetUserDirectory(void)
{
diff --git a/src/util/virutil.h b/src/util/virutil.h
index 73ad147..5a84411 100644
--- a/src/util/virutil.h
+++ b/src/util/virutil.h
@@ -132,6 +132,8 @@ static inline int pthread_sigmask(int how,
char *virGetHostname(void);
bool virIsValidHostname(const char *hostname) ATTRIBUTE_NONNULL(1);
+bool virIsSameHostnameInfo(const char *poolhostname, const char *defhostname)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
char *virGetUserDirectory(void);
char *virGetUserDirectoryByUID(uid_t uid);
--
2.1.0