Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/virsocketaddr.c | 63 ++++++++++++++++++++++++++++++++++++++++
src/util/virsocketaddr.h | 4 +++
3 files changed, 68 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 6b4fe17e20..0be273511d 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -3368,6 +3368,7 @@ virSocketSendFD;
# util/virsocketaddr.h
virSocketAddrBroadcast;
virSocketAddrBroadcastByPrefix;
+virSocketAddrBytes;
virSocketAddrCheckNetmask;
virSocketAddrEqual;
virSocketAddrFormat;
diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c
index fbda858cfe..0a1ae1ac5f 100644
--- a/src/util/virsocketaddr.c
+++ b/src/util/virsocketaddr.c
@@ -30,6 +30,7 @@
*/
typedef unsigned char virSocketAddrIPv4[4];
typedef unsigned short virSocketAddrIPv6[8];
+typedef unsigned char virSocketAddrIPv6Bytes[16];
typedef unsigned char virSocketAddrIPv6Nibbles[32];
static int
@@ -68,6 +69,23 @@ virSocketAddrGetIPv6Addr(const virSocketAddr *addr, virSocketAddrIPv6
*tab)
return 0;
}
+
+static int
+virSocketAddrGetIPv6Bytes(const virSocketAddr *addr,
+ virSocketAddrIPv6Bytes *tab)
+{
+ size_t i;
+
+ if (!addr || !tab || addr->data.stor.ss_family != AF_INET6)
+ return -1;
+
+ for (i = 0; i < 16; i++)
+ (*tab)[i] = addr->data.inet6.sin6_addr.s6_addr[i];
+
+ return 0;
+}
+
+
static int
virSocketAddrGetIPv6Nibbles(const virSocketAddr *addr,
virSocketAddrIPv6Nibbles *tab)
@@ -1331,6 +1349,51 @@ virSocketAddrPTRDomain(const virSocketAddr *addr,
return 0;
}
+
+/**
+ * virSocketAddrBytes:
+ * @addr: address to convert to byte array
+ * @bytes: a preallocated array to store the address bytes to
+ * @maxBytes: the size of @bytes
+ *
+ * Extracts individual bytes of an IPv4 or IPv6 address in the provided @bytes
+ * array, which should be large enough to store 16 bytes (the size of an IPv6
+ * address). Bytes are stored in network order.
+ *
+ * Returns the number of bytes stored in @bytes on success or 0 when @bytes
+ * array is not big enough or @addr is not IPv4 or IPv6.
+ */
+int
+virSocketAddrBytes(const virSocketAddr *addr,
+ unsigned char *bytes,
+ int maxBytes)
+{
+ if (VIR_SOCKET_ADDR_IS_FAMILY(addr, AF_INET6)) {
+ virSocketAddrIPv6Bytes ip;
+
+ if (maxBytes < sizeof(ip))
+ return 0;
+
+ virSocketAddrGetIPv6Bytes(addr, &ip);
+ memcpy(bytes, ip, sizeof(ip));
+ return sizeof(ip);
+ }
+
+ if (VIR_SOCKET_ADDR_IS_FAMILY(addr, AF_INET)) {
+ virSocketAddrIPv4 ip;
+
+ if (maxBytes < sizeof(ip))
+ return 0;
+
+ virSocketAddrGetIPv4Addr(addr, &ip);
+ memcpy(bytes, ip, sizeof(ip));
+ return sizeof(ip);
+ }
+
+ return 0;
+}
+
+
void
virSocketAddrFree(virSocketAddr *addr)
{
diff --git a/src/util/virsocketaddr.h b/src/util/virsocketaddr.h
index ec265d6e44..47b8effa85 100644
--- a/src/util/virsocketaddr.h
+++ b/src/util/virsocketaddr.h
@@ -143,6 +143,10 @@ int virSocketAddrPTRDomain(const virSocketAddr *addr,
char **ptr)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3);
+int virSocketAddrBytes(const virSocketAddr *addr,
+ unsigned char *bytes,
+ int maxBytes);
+
void virSocketAddrFree(virSocketAddr *addr);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virSocketAddr, virSocketAddrFree);
--
2.43.0