diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2016-06-03 22:07:42 +0200 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2016-06-07 11:20:09 +0200 |
commit | ae763642d885dc8d8edc3890a2087bfddbaae635 (patch) | |
tree | 5a47b71a40850020db724d1a481190dc63888106 | |
parent | 4d1e7dc23c3cad10aacee1f585f33ca159e5724a (diff) | |
download | NetworkManager-ae763642d885dc8d8edc3890a2087bfddbaae635.tar.gz |
dns: add reverse DNS IPv6 entries to dnsmasq
https://bugzilla.gnome.org/show_bug.cgi?id=767174
-rw-r--r-- | src/dns-manager/nm-dns-dnsmasq.c | 12 | ||||
-rw-r--r-- | src/dns-manager/nm-dns-utils.c | 31 | ||||
-rw-r--r-- | src/dns-manager/nm-dns-utils.h | 2 | ||||
-rw-r--r-- | src/nm-core-utils.c | 57 | ||||
-rw-r--r-- | src/nm-core-utils.h | 1 | ||||
-rw-r--r-- | src/tests/test-general.c | 57 |
6 files changed, 158 insertions, 2 deletions
diff --git a/src/dns-manager/nm-dns-dnsmasq.c b/src/dns-manager/nm-dns-dnsmasq.c index 79fc7d6cb8..bde3427355 100644 --- a/src/dns-manager/nm-dns-dnsmasq.c +++ b/src/dns-manager/nm-dns-dnsmasq.c @@ -219,6 +219,8 @@ add_ip6_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP6Config *ip6, nnameservers = nm_ip6_config_get_num_nameservers (ip6); if (split) { + char **domains, **iter; + if (nnameservers == 0) return FALSE; @@ -248,6 +250,16 @@ add_ip6_config (NMDnsDnsmasq *self, GVariantBuilder *servers, NMIP6Config *ip6, } } + /* Ensure reverse-DNS works by directing queries for ip6.arpa + * domains to the split domain's nameserver. + */ + domains = nm_dns_utils_get_ip6_rdns_domains (ip6); + if (domains) { + for (iter = domains; iter && *iter; iter++) + add_dnsmasq_nameserver (self, servers, buf, *iter); + g_strfreev (domains); + } + g_free (buf); } } diff --git a/src/dns-manager/nm-dns-utils.c b/src/dns-manager/nm-dns-utils.c index d864aa9619..f9bb79b65f 100644 --- a/src/dns-manager/nm-dns-utils.c +++ b/src/dns-manager/nm-dns-utils.c @@ -57,5 +57,36 @@ nm_dns_utils_get_ip4_rdns_domains (NMIP4Config *ip4) strv = (char **) g_ptr_array_free (domains, (domains->len == 1)); return _nm_utils_strv_cleanup (strv, FALSE, FALSE, TRUE); +} + +char ** +nm_dns_utils_get_ip6_rdns_domains (NMIP6Config *ip6) +{ + char **strv; + GPtrArray *domains = NULL; + int i; + + g_return_val_if_fail (ip6 != NULL, NULL); + + domains = g_ptr_array_sized_new (5); + + for (i = 0; i < nm_ip6_config_get_num_addresses (ip6); i++) { + const NMPlatformIP6Address *address = nm_ip6_config_get_address (ip6, i); + nm_utils_get_reverse_dns_domains_ip6 (&address->address, address->plen, domains); + } + + for (i = 0; i < nm_ip6_config_get_num_routes (ip6); i++) { + const NMPlatformIP6Route *route = nm_ip6_config_get_route (ip6, i); + + nm_utils_get_reverse_dns_domains_ip6 (&route->network, route->plen, domains); + } + + /* Terminating NULL so we can use g_strfreev() to free it */ + g_ptr_array_add (domains, NULL); + + /* Free the array and return NULL if the only element was the ending NULL */ + strv = (char **) g_ptr_array_free (domains, (domains->len == 1)); + + return _nm_utils_strv_cleanup (strv, FALSE, FALSE, TRUE); } diff --git a/src/dns-manager/nm-dns-utils.h b/src/dns-manager/nm-dns-utils.h index 75c6b0608f..2c484ac341 100644 --- a/src/dns-manager/nm-dns-utils.h +++ b/src/dns-manager/nm-dns-utils.h @@ -21,8 +21,10 @@ #define __NETWORKMANAGER_DNS_UTILS_H__ #include "nm-ip4-config.h" +#include "nm-ip6-config.h" char **nm_dns_utils_get_ip4_rdns_domains (NMIP4Config *ip4); +char **nm_dns_utils_get_ip6_rdns_domains (NMIP6Config *ip6); #endif /* NM_DNS_UTILS_H */ diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index 1258a75f1e..b20653838d 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -3318,3 +3318,60 @@ nm_utils_get_reverse_dns_domains_ip4 (guint32 addr, guint8 plen, GPtrArray *doma ip2 += 1 << ((32 - plen) & ~7); } } + +/** + * nm_utils_get_reverse_dns_domains_ip6: + * @addr: IPv6 address + * @plen: prefix length + * @domains: array for results + * + * Creates reverse DNS domains for the given address and prefix length, and + * append them to @domains. + */ +void +nm_utils_get_reverse_dns_domains_ip6 (const struct in6_addr *ip, guint8 plen, GPtrArray *domains) +{ + struct in6_addr addr; + guint nibbles, bits, entries; + int i, j; + gsize len0, len; + char *str, *s; + + g_return_if_fail (domains); + g_return_if_fail (plen <= 128); + + if (!plen) + return; + + memcpy (&addr, ip, sizeof (struct in6_addr)); + nm_utils_ip6_address_clear_host_address (&addr, &addr, plen); + + /* Number of nibbles to include in domains */ + nibbles = (plen - 1) / 4 + 1; + /* Prefix length in nibble */ + bits = plen - ((plen - 1) / 4 * 4); + /* Number of domains */ + entries = 1 << (4 - bits); + + len0 = NM_STRLEN ("ip6.arpa") + (2 * nibbles) + 1; + +#define N_SHIFT(x) ((x) % 2 ? 0 : 4) + + for (i = 0; i < entries; i++) { + len = len0; + str = s = g_malloc (len); + + for (j = nibbles - 1; j >= 0; j--) + nm_utils_strbuf_append (&s, + &len, + "%x.", + (addr.s6_addr[j / 2] >> N_SHIFT (j)) & 0xf); + nm_utils_strbuf_append_str (&s, &len, "ip6.arpa"); + + g_ptr_array_add (domains, str); + + addr.s6_addr[(nibbles - 1) / 2] += 1 << N_SHIFT (nibbles - 1); + } + +#undef N_SHIFT +} diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h index 8b278f725b..ce22439b1b 100644 --- a/src/nm-core-utils.h +++ b/src/nm-core-utils.h @@ -407,5 +407,6 @@ gboolean nm_utils_ip4_address_is_link_local (in_addr_t addr); const char *nm_utils_dnsmasq_status_to_string (int status, char *dest, gsize size); void nm_utils_get_reverse_dns_domains_ip4 (guint32 ip, guint8 plen, GPtrArray *domains); +void nm_utils_get_reverse_dns_domains_ip6 (const struct in6_addr *ip, guint8 plen, GPtrArray *domains); #endif /* __NM_CORE_UTILS_H__ */ diff --git a/src/tests/test-general.c b/src/tests/test-general.c index 34e928811d..9769ead11b 100644 --- a/src/tests/test-general.c +++ b/src/tests/test-general.c @@ -1361,8 +1361,6 @@ test_duplicate_decl_specifier (void) v_result[0] = TEST_MAX (v_const[0], nmtst_get_rand_int () % 5) + v2; } -/*****************************************************************************/ - static void test_reverse_dns_ip4 (void) { @@ -1427,6 +1425,60 @@ test_reverse_dns_ip4 (void) g_ptr_array_unref (domains); } +static void +test_reverse_dns_ip6 (void) +{ + struct in6_addr addr; + GPtrArray *domains = g_ptr_array_new_full (8, g_free); + + inet_pton (AF_INET6, "1234::56", &addr); + nm_utils_get_reverse_dns_domains_ip6 (&addr, 16, domains); + g_assert_cmpuint (domains->len, ==, 1); + g_assert_cmpstr (domains->pdata[0], ==, "4.3.2.1.ip6.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET6, "1234::56", &addr); + nm_utils_get_reverse_dns_domains_ip6 (&addr, 17, domains); + g_assert_cmpuint (domains->len, ==, 8); + g_assert_cmpstr (domains->pdata[0], ==, "0.4.3.2.1.ip6.arpa"); + g_assert_cmpstr (domains->pdata[1], ==, "1.4.3.2.1.ip6.arpa"); + g_assert_cmpstr (domains->pdata[7], ==, "7.4.3.2.1.ip6.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET6, "2001:db8::", &addr); + nm_utils_get_reverse_dns_domains_ip6 (&addr, 29, domains); + g_assert_cmpuint (domains->len, ==, 8); + g_assert_cmpstr (domains->pdata[0], ==, "8.b.d.0.1.0.0.2.ip6.arpa"); + g_assert_cmpstr (domains->pdata[1], ==, "9.b.d.0.1.0.0.2.ip6.arpa"); + g_assert_cmpstr (domains->pdata[7], ==, "f.b.d.0.1.0.0.2.ip6.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET6, "0123:4567:89ab:cdef::", &addr); + nm_utils_get_reverse_dns_domains_ip6 (&addr, 63, domains); + g_assert_cmpuint (domains->len, ==, 2); + g_assert_cmpstr (domains->pdata[0], ==, "e.e.d.c.b.a.9.8.7.6.5.4.3.2.1.0.ip6.arpa"); + g_assert_cmpstr (domains->pdata[1], ==, "f.e.d.c.b.a.9.8.7.6.5.4.3.2.1.0.ip6.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET6, "fec0:1234:5678:9ab0::", &addr); + nm_utils_get_reverse_dns_domains_ip6 (&addr, 61, domains); + g_assert_cmpuint (domains->len, ==, 8); + g_assert_cmpstr (domains->pdata[0], ==, "0.b.a.9.8.7.6.5.4.3.2.1.0.c.e.f.ip6.arpa"); + g_assert_cmpstr (domains->pdata[7], ==, "7.b.a.9.8.7.6.5.4.3.2.1.0.c.e.f.ip6.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET6, "0123:4567:89ab:cdee::", &addr); + nm_utils_get_reverse_dns_domains_ip6 (&addr, 0, domains); + g_assert_cmpuint (domains->len, ==, 0); + + g_ptr_array_unref (domains); +} + /*****************************************************************************/ NMTST_DEFINE (); @@ -1464,6 +1516,7 @@ main (int argc, char **argv) g_test_add_func ("/general/duplicate_decl_specifier", test_duplicate_decl_specifier); g_test_add_func ("/general/reverse_dns/ip4", test_reverse_dns_ip4); + g_test_add_func ("/general/reverse_dns/ip6", test_reverse_dns_ip6); return g_test_run (); } |