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@xxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list