[libvirt] [PATCH v3 2/3] util: Introduce virSocketAddrPTRDomain

Jiri Denemark jdenemar at redhat.com
Fri Dec 16 18:09:23 UTC 2016


The API creates PTR domain which corresponds to a given addr/prefix.
Both IPv4 and IPv6 addresses are supported, but the prefix must be
divisible by 8 for IPv4 and divisible by 4 for IPv6.

The generated PTR domain has the following format

IPv4: 1.2.3.4.in-addr.arpa
IPv6: 0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.ip6.arpa

Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
---

Notes:
    ACKed in v2

 src/libvirt_private.syms |  1 +
 src/util/virsocketaddr.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/util/virsocketaddr.h |  9 +++++
 3 files changed, 95 insertions(+)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 7beebbf27..1391a4282 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2403,6 +2403,7 @@ virSocketAddrParse;
 virSocketAddrParseIPv4;
 virSocketAddrParseIPv6;
 virSocketAddrPrefixToNetmask;
+virSocketAddrPTRDomain;
 virSocketAddrSetIPv4Addr;
 virSocketAddrSetIPv4AddrNetOrder;
 virSocketAddrSetIPv6Addr;
diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c
index 33b1e9e1f..41f75d5c2 100644
--- a/src/util/virsocketaddr.c
+++ b/src/util/virsocketaddr.c
@@ -27,6 +27,7 @@
 #include "virerror.h"
 #include "virstring.h"
 #include "viralloc.h"
+#include "virbuffer.h"
 
 #include <netdb.h>
 
@@ -40,6 +41,8 @@ typedef unsigned char virSocketAddrIPv4[4];
 typedef virSocketAddrIPv4 *virSocketAddrIPv4Ptr;
 typedef unsigned short virSocketAddrIPv6[8];
 typedef virSocketAddrIPv6 *virSocketAddrIPv6Ptr;
+typedef unsigned char virSocketAddrIPv6Nibbles[32];
+typedef virSocketAddrIPv6Nibbles *virSocketAddrIPv6NibblesPtr;
 
 static int
 virSocketAddrGetIPv4Addr(const virSocketAddr *addr,
@@ -78,6 +81,23 @@ virSocketAddrGetIPv6Addr(const virSocketAddr *addr, virSocketAddrIPv6Ptr tab)
 }
 
 static int
+virSocketAddrGetIPv6Nibbles(const virSocketAddr *addr,
+                            virSocketAddrIPv6NibblesPtr tab)
+{
+    size_t i;
+
+    if (!addr || !tab || addr->data.stor.ss_family != AF_INET6)
+        return -1;
+
+    for (i = 0; i < 16; i++) {
+        (*tab)[2 * i] = addr->data.inet6.sin6_addr.s6_addr[i] >> 4;
+        (*tab)[2 * i + 1] = addr->data.inet6.sin6_addr.s6_addr[i] & 0xF;
+    }
+
+    return 0;
+}
+
+static int
 virSocketAddrParseInternal(struct addrinfo **res,
                            const char *val,
                            int family,
@@ -1118,3 +1138,68 @@ virSocketAddrIsNumericLocalhost(const char *addr)
 
     return false;
 }
+
+
+/**
+ * virSocketAddrPTRDomain:
+ *
+ * Create PTR domain which corresponds to @addr/@prefix. Both IPv4 and IPv6
+ * addresses are supported, but @prefix must be divisible by 8 for IPv4 and
+ * divisible by 4 for IPv6, otherwise -2 will be returned.
+ *
+ * Returns -2 if the PTR record cannot be automatically created,
+ *         -1 on error,
+  *         0 on success.
+ */
+int
+virSocketAddrPTRDomain(const virSocketAddr *addr,
+                       unsigned int prefix,
+                       char **ptr)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    size_t i;
+    int ret = -1;
+
+    if (VIR_SOCKET_ADDR_IS_FAMILY(addr, AF_INET)) {
+        virSocketAddrIPv4 ip;
+
+        if (prefix == 0 || prefix >= 32 || prefix % 8 != 0)
+            goto unsupported;
+
+        if (virSocketAddrGetIPv4Addr(addr, &ip) < 0)
+            goto cleanup;
+
+        for (i = prefix / 8; i > 0; i--)
+            virBufferAsprintf(&buf, "%u.", ip[i - 1]);
+
+        virBufferAddLit(&buf, VIR_SOCKET_ADDR_IPV4_ARPA);
+    } else if (VIR_SOCKET_ADDR_IS_FAMILY(addr, AF_INET6)) {
+        virSocketAddrIPv6Nibbles ip;
+
+        if (prefix == 0 || prefix >= 128 || prefix % 4 != 0)
+            goto unsupported;
+
+        if (virSocketAddrGetIPv6Nibbles(addr, &ip) < 0)
+            goto cleanup;
+
+        for (i = prefix / 4; i > 0; i--)
+            virBufferAsprintf(&buf, "%x.", ip[i - 1]);
+
+        virBufferAddLit(&buf, VIR_SOCKET_ADDR_IPV6_ARPA);
+    } else {
+        goto unsupported;
+    }
+
+    if (!(*ptr = virBufferContentAndReset(&buf)))
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    virBufferFreeAndReset(&buf);
+    return ret;
+
+ unsupported:
+    ret = -2;
+    goto cleanup;
+}
diff --git a/src/util/virsocketaddr.h b/src/util/virsocketaddr.h
index 7ee993b1a..43a370620 100644
--- a/src/util/virsocketaddr.h
+++ b/src/util/virsocketaddr.h
@@ -57,6 +57,9 @@ typedef struct {
 # define VIR_SOCKET_ADDR_IPV4_ALL "0.0.0.0"
 # define VIR_SOCKET_ADDR_IPV6_ALL "::"
 
+# define VIR_SOCKET_ADDR_IPV4_ARPA "in-addr.arpa"
+# define VIR_SOCKET_ADDR_IPV6_ARPA "ip6.arpa"
+
 typedef virSocketAddr *virSocketAddrPtr;
 
 typedef struct _virSocketAddrRange virSocketAddrRange;
@@ -136,4 +139,10 @@ bool virSocketAddrIsWildcard(const virSocketAddr *addr);
 int virSocketAddrNumericFamily(const char *address);
 
 bool virSocketAddrIsNumericLocalhost(const char *addr);
+
+int virSocketAddrPTRDomain(const virSocketAddr *addr,
+                           unsigned int prefix,
+                           char **ptr)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3);
+
 #endif /* __VIR_SOCKETADDR_H__ */
-- 
2.11.0




More information about the libvir-list mailing list