From: Gustavo Luiz Duarte <gustavold@linux.vnet.ibm.com>
To: grub-devel@gnu.org
Subject: [PATCH] Issue separate DNS queries for ipv4 and ipv6
Date: Tue, 16 Oct 2012 21:55:23 -0300 [thread overview]
Message-ID: <507E01FB.4050303@linux.vnet.ibm.com> (raw)
Adding multiple questions on a single DNS query is not supportted by
most DNS servers. This patch issues two separate DNS queries
sequentially for ipv4 and then for ipv6.
There are 4 possible config options:
DNS_OPTION_IPV4: issue only one ipv4 query
DNS_OPTION_IPV6: issue only one ipv6 query
DNS_OPTION_PREFER_IPV4: issue the ipv4 query first and fallback to ipv6
DNS_OPTION_PREFER_IPV6: issue the ipv6 query first and fallback to ipv4
However, there is no code yet to set such config option. The default is
DNS_OPTION_PREFER_IPV4.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=860829
---
grub-core/net/dns.c | 99 ++++++++++++++++++++++++++++++++++++-----------------
include/grub/net.h | 9 +++++
2 files changed, 76 insertions(+), 32 deletions(-)
diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
index 3381ea7..725725c 100644
--- a/grub-core/net/dns.c
+++ b/grub-core/net/dns.c
@@ -34,6 +34,14 @@ struct dns_cache_element
#define DNS_CACHE_SIZE 1021
#define DNS_HASH_BASE 423
+typedef enum grub_dns_qtype_id
+ {
+ GRUB_DNS_QTYPE_A = 1,
+ GRUB_DNS_QTYPE_AAAA = 28
+ } grub_dns_qtype_id_t;
+
+static grub_dns_option_t dns_type_option = DNS_OPTION_PREFER_IPV4;
+
static struct dns_cache_element dns_cache[DNS_CACHE_SIZE];
static struct grub_net_network_level_address *dns_servers;
static grub_size_t dns_nservers, dns_servers_alloc;
@@ -410,13 +418,13 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)),
return GRUB_ERR_NONE;
}
-grub_err_t
-grub_net_dns_lookup (const char *name,
+static grub_err_t
+grub_net_dns_lookup_qtype (const char *name,
const struct grub_net_network_level_address *servers,
grub_size_t n_servers,
grub_size_t *naddresses,
struct grub_net_network_level_address **addresses,
- int cache)
+ int cache, grub_dns_qtype_id_t qtype)
{
grub_size_t send_servers = 0;
grub_size_t i, j;
@@ -471,8 +479,7 @@ grub_net_dns_lookup (const char *name,
+ GRUB_NET_MAX_LINK_HEADER_SIZE
+ GRUB_NET_UDP_HEADER_SIZE
+ sizeof (struct dns_header)
- + grub_strlen (name) + 2 + 4
- + 2 + 4);
+ + grub_strlen (name) + 2 + 4);
if (!nb)
{
grub_free (data.name);
@@ -482,7 +489,7 @@ grub_net_dns_lookup (const char *name,
+ GRUB_NET_MAX_LINK_HEADER_SIZE
+ GRUB_NET_UDP_HEADER_SIZE);
grub_netbuff_put (nb, sizeof (struct dns_header)
- + grub_strlen (name) + 2 + 4 + 2 + 4);
+ + grub_strlen (name) + 2 + 4);
head = (struct dns_header *) nb->data;
optr = (grub_uint8_t *) (head + 1);
for (iptr = name; *iptr; )
@@ -509,18 +516,7 @@ grub_net_dns_lookup (const char *name,
/* Type: A. */
*optr++ = 0;
- *optr++ = 1;
-
- /* Class. */
- *optr++ = 0;
- *optr++ = 1;
-
- /* Compressed name. */
- *optr++ = 0xc0;
- *optr++ = 0x0c;
- /* Type: AAAA. */
- *optr++ = 0;
- *optr++ = 28;
+ *optr++ = qtype;
/* Class. */
*optr++ = 0;
@@ -529,7 +525,7 @@ grub_net_dns_lookup (const char *name,
head->id = data.id;
head->flags = FLAGS_RD;
head->ra_z_r_code = 0;
- head->qdcount = grub_cpu_to_be16_compile_time (2);
+ head->qdcount = grub_cpu_to_be16_compile_time (1);
head->ancount = grub_cpu_to_be16_compile_time (0);
head->nscount = grub_cpu_to_be16_compile_time (0);
head->arcount = grub_cpu_to_be16_compile_time (0);
@@ -587,16 +583,47 @@ grub_net_dns_lookup (const char *name,
if (*data.naddresses)
return GRUB_ERR_NONE;
if (data.dns_err)
- return grub_error (GRUB_ERR_NET_NO_DOMAIN,
- N_("no DNS record found"));
-
+ {
+ grub_dprintf ("dns", "%s. QTYPE: %u QNAME: %s\n",
+ N_("no DNS record found"), qtype, name);
+ return GRUB_ERR_NET_NO_DOMAIN;
+ }
if (err)
{
grub_errno = err;
return err;
}
- return grub_error (GRUB_ERR_TIMEOUT,
- N_("no DNS reply received"));
+ grub_dprintf ("dns", "%s. QTYPE: %u QNAME: %s\n",
+ N_("no DNS reply received"), qtype, name);
+ return GRUB_ERR_TIMEOUT;
+}
+
+grub_err_t
+grub_net_dns_lookup (const char *name,
+ const struct grub_net_network_level_address *servers,
+ grub_size_t n_servers,
+ grub_size_t *naddresses,
+ struct grub_net_network_level_address **addresses,
+ int cache)
+{
+ if (dns_type_option == DNS_OPTION_IPV6 || dns_type_option == DNS_OPTION_PREFER_IPV6)
+ grub_net_dns_lookup_qtype (name, servers, n_servers, naddresses,
+ addresses, cache, GRUB_DNS_QTYPE_AAAA);
+ else
+ grub_net_dns_lookup_qtype (name, servers, n_servers, naddresses,
+ addresses, cache, GRUB_DNS_QTYPE_A);
+ if (!*naddresses)
+ {
+ if (dns_type_option == DNS_OPTION_PREFER_IPV4)
+ grub_net_dns_lookup_qtype (name, servers, n_servers, naddresses,
+ addresses, cache, GRUB_DNS_QTYPE_AAAA);
+ else if (dns_type_option == DNS_OPTION_PREFER_IPV6)
+ grub_net_dns_lookup_qtype (name, servers, n_servers, naddresses,
+ addresses, cache, GRUB_DNS_QTYPE_A);
+ }
+ if (!*naddresses)
+ return GRUB_ERR_NET_NO_DOMAIN;
+ return GRUB_ERR_NONE;
}
static grub_err_t
@@ -604,22 +631,28 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)),
int argc, char **args)
{
grub_err_t err;
- grub_size_t naddresses, i;
+ struct grub_net_network_level_address cmd_server;
+ struct grub_net_network_level_address *servers;
+ grub_size_t nservers, i, naddresses = 0;
struct grub_net_network_level_address *addresses = 0;
if (argc != 2 && argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
if (argc == 2)
{
- struct grub_net_network_level_address server;
- err = grub_net_resolve_address (args[1], &server);
+ err = grub_net_resolve_address (args[1], &cmd_server);
if (err)
return err;
- err = grub_net_dns_lookup (args[0], &server, 1, &naddresses,
- &addresses, 0);
+ servers = &cmd_server;
+ nservers = 1;
}
else
- err = grub_net_dns_lookup (args[0], dns_servers, dns_nservers, &naddresses,
- &addresses, 0);
+ {
+ servers = dns_servers;
+ nservers = dns_nservers;
+ }
+
+ grub_net_dns_lookup (args[0], servers, nservers, &naddresses,
+ &addresses, 0);
for (i = 0; i < naddresses; i++)
{
@@ -628,7 +661,9 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)),
grub_printf ("%s\n", buf);
}
grub_free (addresses);
- return GRUB_ERR_NONE;
+ if (naddresses)
+ return GRUB_ERR_NONE;
+ return grub_error (GRUB_ERR_NET_NO_DOMAIN, N_("no DNS record found"));
}
static grub_err_t
diff --git a/include/grub/net.h b/include/grub/net.h
index 3877451..a7e5b2c 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -505,6 +505,15 @@ grub_err_t
grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf,
const grub_net_network_level_address_t *proto_addr,
grub_net_link_level_address_t *hw_addr);
+
+typedef enum
+ {
+ DNS_OPTION_IPV4,
+ DNS_OPTION_IPV6,
+ DNS_OPTION_PREFER_IPV4,
+ DNS_OPTION_PREFER_IPV6
+ } grub_dns_option_t;
+
grub_err_t
grub_net_dns_lookup (const char *name,
const struct grub_net_network_level_address *servers,
--
1.7.11.4
next reply other threads:[~2012-10-17 0:55 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-10-17 0:55 Gustavo Luiz Duarte [this message]
2012-10-17 1:06 ` [PATCH] Issue separate DNS queries for ipv4 and ipv6 Richard Laager
2012-10-18 21:21 ` Gustavo Luiz Duarte
2012-10-18 21:50 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-11-02 16:34 ` Vladimir 'φ-coder/phcoder' Serbinenko
2013-11-05 19:07 ` Gustavo Luiz Duarte
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=507E01FB.4050303@linux.vnet.ibm.com \
--to=gustavold@linux.vnet.ibm.com \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.