diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2016-06-03 22:07:38 +0200 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2016-06-07 10:52:50 +0200 |
commit | 4d1e7dc23c3cad10aacee1f585f33ca159e5724a (patch) | |
tree | 99aed84b38723a5090cf4f7ab73501af1c144ef5 | |
parent | 24430e4b07b4c8c902adbbbf190ead43b1e92115 (diff) | |
download | NetworkManager-4d1e7dc23c3cad10aacee1f585f33ca159e5724a.tar.gz |
dns: add CIDR reverse DNS IPv4 entries to dnsmasq
When a reverse DNS entry must be added to dnsmasq, instead of
considering IP addresses as classful use the prefix to compute one or
more "in-addr.arpa" according to CIDR rules.
https://bugzilla.gnome.org/show_bug.cgi?id=767174
-rw-r--r-- | src/dns-manager/nm-dns-utils.c | 60 | ||||
-rw-r--r-- | src/nm-core-utils.c | 48 | ||||
-rw-r--r-- | src/nm-core-utils.h | 2 | ||||
-rw-r--r-- | src/tests/test-general.c | 68 |
4 files changed, 126 insertions, 52 deletions
diff --git a/src/dns-manager/nm-dns-utils.c b/src/dns-manager/nm-dns-utils.c index e920611acc..d864aa9619 100644 --- a/src/dns-manager/nm-dns-utils.c +++ b/src/dns-manager/nm-dns-utils.c @@ -23,52 +23,14 @@ #include <string.h> #include "nm-dns-utils.h" +#include "nm-core-internal.h" #include "nm-platform.h" #include "nm-utils.h" -static void -add_ip4_to_rdns_array (guint32 ip, GPtrArray *domains) /* network byte order */ -{ - guint32 defprefix; - guchar *p; - char *str = NULL; - int i; - - defprefix = nm_utils_ip4_get_default_prefix (ip); - - /* Convert to host byte order, mask the host bits, and convert back */ - ip = ntohl (ip); - ip &= 0xFFFFFFFF << (32 - defprefix); - ip = htonl (ip); - p = (guchar *) &ip; - - if (defprefix == 8) - str = g_strdup_printf ("%u.in-addr.arpa", p[0] & 0xFF); - else if (defprefix == 16) - str = g_strdup_printf ("%u.%u.in-addr.arpa", p[1] & 0xFF, p[0] & 0xFF); - else if (defprefix == 24) - str = g_strdup_printf ("%u.%u.%u.in-addr.arpa", p[2] & 0xFF, p[1] & 0xFF, p[0] & 0xFF); - - if (!str) { - g_return_if_fail (str != NULL); - return; - } - - /* Suppress duplicates */ - for (i = 0; i < domains->len; i++) { - if (strcmp (str, g_ptr_array_index (domains, i)) == 0) - break; - } - - if (i == domains->len) - g_ptr_array_add (domains, str); - else - g_free (str); -} - char ** nm_dns_utils_get_ip4_rdns_domains (NMIP4Config *ip4) { + char **strv; GPtrArray *domains = NULL; int i; @@ -76,30 +38,24 @@ nm_dns_utils_get_ip4_rdns_domains (NMIP4Config *ip4) domains = g_ptr_array_sized_new (5); - /* To calculate the reverse DNS domains for this IP4 config, we take - * all the IP addresses and routes in the config, calculate the network - * portion, and convert that to classful, and use the network bits for - * the final domain. FIXME: better handle classless routing, which might - * require us to add multiple domains for each actual network prefix to - * cover all the separate networks in that block. - */ - for (i = 0; i < nm_ip4_config_get_num_addresses (ip4); i++) { const NMPlatformIP4Address *address = nm_ip4_config_get_address (ip4, i); - add_ip4_to_rdns_array (address->address, domains); + nm_utils_get_reverse_dns_domains_ip4 (address->address, address->plen, domains); } for (i = 0; i < nm_ip4_config_get_num_routes (ip4); i++) { const NMPlatformIP4Route *route = nm_ip4_config_get_route (ip4, i); - add_ip4_to_rdns_array (route->network, domains); + nm_utils_get_reverse_dns_domains_ip4 (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 */ - return (char **) g_ptr_array_free (domains, (domains->len == 1)); -} + strv = (char **) g_ptr_array_free (domains, (domains->len == 1)); + return _nm_utils_strv_cleanup (strv, FALSE, FALSE, TRUE); + +} diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index 12b537713e..1258a75f1e 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -3270,3 +3270,51 @@ nm_utils_dnsmasq_status_to_string (int status, char *dest, gsize size) g_snprintf (dest, size, "%s (%d)", msg, status); return dest; } + +/** + * nm_utils_get_reverse_dns_domains_ip4: + * @addr: IP address in network order + * @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_ip4 (guint32 addr, guint8 plen, GPtrArray *domains) +{ + guint32 ip, ip2, mask; + guchar *p; + guint octets; + guint i; + gsize len0, len; + char *str, *s; + + g_return_if_fail (domains); + g_return_if_fail (plen <= 32); + + if (!plen) + return; + + octets = (plen - 1) / 8 + 1; + ip = ntohl (addr); + mask = 0xFFFFFFFF << (32 - plen); + ip &= mask; + ip2 = ip; + + len0 = NM_STRLEN ("in-addr.arpa") + (4 * octets) + 1; + while ((ip2 & mask) == ip) { + addr = htonl (ip2); + p = (guchar *) &addr; + + len = len0; + str = s = g_malloc (len); + for (i = octets; i > 0; i--) + nm_utils_strbuf_append (&s, &len, "%u.", p[i - 1] & 0xff); + nm_utils_strbuf_append_str (&s, &len, "in-addr.arpa"); + + g_ptr_array_add (domains, str); + + ip2 += 1 << ((32 - plen) & ~7); + } +} diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h index db7794f615..8b278f725b 100644 --- a/src/nm-core-utils.h +++ b/src/nm-core-utils.h @@ -406,4 +406,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); + #endif /* __NM_CORE_UTILS_H__ */ diff --git a/src/tests/test-general.c b/src/tests/test-general.c index d29cdc0eed..34e928811d 100644 --- a/src/tests/test-general.c +++ b/src/tests/test-general.c @@ -1363,6 +1363,72 @@ test_duplicate_decl_specifier (void) /*****************************************************************************/ +static void +test_reverse_dns_ip4 (void) +{ + guint32 addr; + GPtrArray *domains = g_ptr_array_new_full (8, g_free); + + inet_pton (AF_INET, "7.2.3.0", &addr); + nm_utils_get_reverse_dns_domains_ip4 (addr, 27, domains); + g_assert_cmpuint (domains->len, ==, 32); + g_assert_cmpstr (domains->pdata[0], ==, "0.3.2.7.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[31], ==, "31.3.2.7.in-addr.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET, "10.155.16.0", &addr); + nm_utils_get_reverse_dns_domains_ip4 (addr, 22, domains); + g_assert_cmpuint (domains->len, ==, 4); + g_assert_cmpstr (domains->pdata[0], ==, "16.155.10.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[1], ==, "17.155.10.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[2], ==, "18.155.10.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[3], ==, "19.155.10.in-addr.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET, "4.5.6.7", &addr); + nm_utils_get_reverse_dns_domains_ip4 (addr, 32, domains); + g_assert_cmpuint (domains->len, ==, 1); + g_assert_cmpstr (domains->pdata[0], ==, "7.6.5.4.in-addr.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET, "4.5.6.7", &addr); + nm_utils_get_reverse_dns_domains_ip4 (addr, 8, domains); + g_assert_cmpuint (domains->len, ==, 1); + g_assert_cmpstr (domains->pdata[0], ==, "4.in-addr.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET, "4.180.6.7", &addr); + nm_utils_get_reverse_dns_domains_ip4 (addr, 9, domains); + g_assert_cmpuint (domains->len, ==, 128); + g_assert_cmpstr (domains->pdata[0], ==, "128.4.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[1], ==, "129.4.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[127], ==, "255.4.in-addr.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET, "172.16.0.0", &addr); + nm_utils_get_reverse_dns_domains_ip4 (addr, 12, domains); + g_assert_cmpuint (domains->len, ==, 16); + g_assert_cmpstr (domains->pdata[0], ==, "16.172.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[1], ==, "17.172.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[14], ==, "30.172.in-addr.arpa"); + g_assert_cmpstr (domains->pdata[15], ==, "31.172.in-addr.arpa"); + + g_ptr_array_set_size (domains, 0); + + inet_pton (AF_INET, "1.2.3.4", &addr); + nm_utils_get_reverse_dns_domains_ip4 (addr, 0, domains); + g_assert_cmpuint (domains->len, ==, 0); + + g_ptr_array_unref (domains); +} + +/*****************************************************************************/ + NMTST_DEFINE (); int @@ -1397,6 +1463,8 @@ main (int argc, char **argv) g_test_add_func ("/general/nm_match_spec_match_config", test_nm_match_spec_match_config); g_test_add_func ("/general/duplicate_decl_specifier", test_duplicate_decl_specifier); + g_test_add_func ("/general/reverse_dns/ip4", test_reverse_dns_ip4); + return g_test_run (); } |