[libvirt] [PATCH v2 4/5] util: Introduce virSocketAddrPTRDomain
Laine Stump
laine at laine.org
Wed Dec 14 20:25:49 UTC 2016
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 at redhat.com>
> ---
> 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.
More information about the libvir-list
mailing list