Re: [PATCH v2 4/5] util: Introduce virSocketAddrPTRDomain

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 12/13/2016 08:52 AM, Jiri Denemark wrote:
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@xxxxxxxxxx>
---
  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 ffbf46c1a..27c1edaef 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2391,6 +2391,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;
+}

It *could* have been done without this extra type and function, but it does make it easier to follow :-)

+
+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;

Okay, so you're not calling it "error" because it's only for a special kind of error. Unconventional, but okay.

+    }
+
+    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__ */


ACK.

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list



[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]
  Powered by Linux