[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