This function takes exactly one argument: an address to check.
It returns true, iff the address is an IPv4 or IPv6 address in numeric
format, false if otherwise (e.g. for "examplehost").
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/virsocketaddr.c | 71 +++++++++++++++++++++++++++++++++++++-----------
src/util/virsocketaddr.h | 2 ++
tests/sockettest.c | 29 ++++++++++++++++++++
4 files changed, 87 insertions(+), 16 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index fe40834..54ef9a7 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1682,6 +1682,7 @@ virSocketAddrGetIpPrefix;
virSocketAddrGetPort;
virSocketAddrGetRange;
virSocketAddrIsNetmask;
+virSocketAddrIsNumeric;
virSocketAddrIsPrivate;
virSocketAddrIsWildcard;
virSocketAddrMask;
diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c
index 3e01baf..ddb3058 100644
--- a/src/util/virsocketaddr.c
+++ b/src/util/virsocketaddr.c
@@ -71,6 +71,35 @@ static int virSocketAddrGetIPv6Addr(virSocketAddrPtr addr,
virSocketAddrIPv6Ptr
return 0;
}
+static int
+virSocketAddrParseInternal(struct addrinfo **res,
+ const char *val,
+ int family,
+ bool reportError)
+{
+ struct addrinfo hints;
+ int err;
+
+ if (val == NULL) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s", _("Missing
address"));
+ return -1;
+ }
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_flags = AI_NUMERICHOST;
+ if ((err = getaddrinfo(val, NULL, &hints, res)) != 0) {
+ if (reportError)
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("Cannot parse socket address '%s': %s"),
+ val, gai_strerror(err));
+
+ return -1;
+ }
+
+ return 0;
+}
+
/**
* virSocketAddrParse:
* @val: a numeric network address IPv4 or IPv6
@@ -84,24 +113,10 @@ static int virSocketAddrGetIPv6Addr(virSocketAddrPtr addr,
virSocketAddrIPv6Ptr
*/
int virSocketAddrParse(virSocketAddrPtr addr, const char *val, int family) {
int len;
- struct addrinfo hints;
- struct addrinfo *res = NULL;
- int err;
+ struct addrinfo *res;
- if (val == NULL) {
- virReportError(VIR_ERR_INVALID_ARG, "%s", _("Missing
address"));
+ if (virSocketAddrParseInternal(&res, val, family, true) < 0)
return -1;
- }
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = family;
- hints.ai_flags = AI_NUMERICHOST;
- if ((err = getaddrinfo(val, NULL, &hints, &res)) != 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("Cannot parse socket address '%s': %s"),
- val, gai_strerror(err));
- return -1;
- }
if (res == NULL) {
virReportError(VIR_ERR_SYSTEM_ERROR,
@@ -824,3 +839,27 @@ virSocketAddrGetIpPrefix(const virSocketAddrPtr address,
*/
return 0;
}
+/**
+ * virSocketAddrIsNumeric:
+ * @address: address to check
+ *
+ * Check if passed address is an IP address in numeric format. For
+ * instance, for 0.0.0.0 true is returned, for 'examplehost"
+ * false is returned.
+ *
+ * Returns: true iff @address is an IP address,
+ * false otherwise
+ */
+bool
+virSocketAddrIsNumeric(const char *address)
+{
+ struct addrinfo *res;
+ unsigned short family;
+
+ if (virSocketAddrParseInternal(&res, address, AF_UNSPEC, false) < 0)
+ return false;
+
+ family = res->ai_addr->sa_family;
+ freeaddrinfo(res);
+ return family == AF_INET || family == AF_INET6;
+}
diff --git a/src/util/virsocketaddr.h b/src/util/virsocketaddr.h
index b28fe6c..d844914 100644
--- a/src/util/virsocketaddr.h
+++ b/src/util/virsocketaddr.h
@@ -124,4 +124,6 @@ bool virSocketAddrEqual(const virSocketAddrPtr s1,
bool virSocketAddrIsPrivate(const virSocketAddrPtr addr);
bool virSocketAddrIsWildcard(const virSocketAddrPtr addr);
+
+bool virSocketAddrIsNumeric(const char *address);
#endif /* __VIR_SOCKETADDR_H__ */
diff --git a/tests/sockettest.c b/tests/sockettest.c
index 4b38cdf..f98955d 100644
--- a/tests/sockettest.c
+++ b/tests/sockettest.c
@@ -174,6 +174,21 @@ static int testWildcardHelper(const void *opaque)
return testWildcard(data->addr, data->pass);
}
+struct testIsNumericData {
+ const char *addr;
+ bool pass;
+};
+
+static int
+testIsNumericHelper(const void *opaque)
+{
+ const struct testIsNumericData *data = opaque;
+
+ if (virSocketAddrIsNumeric(data->addr))
+ return data->pass ? 0 : -1;
+ return data->pass ? -1 : 0;
+}
+
static int
mymain(void)
{
@@ -246,6 +261,14 @@ mymain(void)
ret = -1; \
} while (0)
+#define DO_TEST_IS_NUMERIC(addr, pass) \
+ do { \
+ struct testIsNumericData data = { addr, pass}; \
+ if (virtTestRun("Test isNumeric " addr, \
+ testIsNumericHelper, &data) < 0) \
+ ret = -1; \
+ } while (0)
+
DO_TEST_PARSE_AND_FORMAT("127.0.0.1", AF_UNSPEC, true);
DO_TEST_PARSE_AND_FORMAT("127.0.0.1", AF_INET, true);
@@ -307,6 +330,12 @@ mymain(void)
DO_TEST_WILDCARD("1", false);
DO_TEST_WILDCARD("0.1", false);
+ DO_TEST_IS_NUMERIC("0.0.0.0", true);
+ DO_TEST_IS_NUMERIC("::", true);
+ DO_TEST_IS_NUMERIC("1", true);
+ DO_TEST_IS_NUMERIC("::ffff", true);
+ DO_TEST_IS_NUMERIC("examplehost", false);
+
return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
--
1.8.1.5