|
|
f96e0b |
From 590290e07fe45f5fee7cd15e507fe90e54046732 Mon Sep 17 00:00:00 2001
|
|
|
f96e0b |
From: Gustavo Luiz Duarte <gustavold@linux.vnet.ibm.com>
|
|
|
f96e0b |
Date: Fri, 28 Sep 2012 19:42:07 -0400
|
|
|
f96e0b |
Subject: [PATCH 452/482] Issue separate DNS queries for ipv4 and ipv6
|
|
|
f96e0b |
|
|
|
f96e0b |
Adding multiple questions on a single DNS query is not supportted by
|
|
|
f96e0b |
most DNS servers. This patch issues two separate DNS queries
|
|
|
f96e0b |
sequentially for ipv4 and then for ipv6.
|
|
|
f96e0b |
|
|
|
f96e0b |
There are 4 possible config options:
|
|
|
f96e0b |
DNS_OPTION_IPV4: issue only one ipv4 query
|
|
|
f96e0b |
DNS_OPTION_IPV6: issue only one ipv6 query
|
|
|
f96e0b |
DNS_OPTION_PREFER_IPV4: issue the ipv4 query first and fallback to ipv6
|
|
|
f96e0b |
DNS_OPTION_PREFER_IPV6: issue the ipv6 query first and fallback to ipv4
|
|
|
f96e0b |
However, there is no code yet to set such config option. The default is
|
|
|
f96e0b |
DNS_OPTION_PREFER_IPV4.
|
|
|
f96e0b |
|
|
|
f96e0b |
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=860829
|
|
|
f96e0b |
---
|
|
|
f96e0b |
grub-core/net/dns.c | 99 ++++++++++++++++++++++++++++++++++++-----------------
|
|
|
f96e0b |
include/grub/net.h | 9 +++++
|
|
|
f96e0b |
2 files changed, 76 insertions(+), 32 deletions(-)
|
|
|
f96e0b |
|
|
|
f96e0b |
diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
|
|
|
f96e0b |
index 3381ea7..fac97b0 100644
|
|
|
f96e0b |
--- a/grub-core/net/dns.c
|
|
|
f96e0b |
+++ b/grub-core/net/dns.c
|
|
|
f96e0b |
@@ -34,6 +34,14 @@ struct dns_cache_element
|
|
|
f96e0b |
#define DNS_CACHE_SIZE 1021
|
|
|
f96e0b |
#define DNS_HASH_BASE 423
|
|
|
f96e0b |
|
|
|
f96e0b |
+typedef enum grub_dns_qtype_id
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ GRUB_DNS_QTYPE_A = 1,
|
|
|
f96e0b |
+ GRUB_DNS_QTYPE_AAAA = 28
|
|
|
f96e0b |
+ } grub_dns_qtype_id_t;
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+static grub_dns_option_t dns_type_option = DNS_OPTION_PREFER_IPV4;
|
|
|
f96e0b |
+
|
|
|
f96e0b |
static struct dns_cache_element dns_cache[DNS_CACHE_SIZE];
|
|
|
f96e0b |
static struct grub_net_network_level_address *dns_servers;
|
|
|
f96e0b |
static grub_size_t dns_nservers, dns_servers_alloc;
|
|
|
f96e0b |
@@ -410,13 +418,13 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)),
|
|
|
f96e0b |
return GRUB_ERR_NONE;
|
|
|
f96e0b |
}
|
|
|
f96e0b |
|
|
|
f96e0b |
-grub_err_t
|
|
|
f96e0b |
-grub_net_dns_lookup (const char *name,
|
|
|
f96e0b |
+static grub_err_t
|
|
|
f96e0b |
+grub_net_dns_lookup_qtype (const char *name,
|
|
|
f96e0b |
const struct grub_net_network_level_address *servers,
|
|
|
f96e0b |
grub_size_t n_servers,
|
|
|
f96e0b |
grub_size_t *naddresses,
|
|
|
f96e0b |
struct grub_net_network_level_address **addresses,
|
|
|
f96e0b |
- int cache)
|
|
|
f96e0b |
+ int cache, grub_dns_qtype_id_t qtype)
|
|
|
f96e0b |
{
|
|
|
f96e0b |
grub_size_t send_servers = 0;
|
|
|
f96e0b |
grub_size_t i, j;
|
|
|
f96e0b |
@@ -471,8 +479,7 @@ grub_net_dns_lookup (const char *name,
|
|
|
f96e0b |
+ GRUB_NET_MAX_LINK_HEADER_SIZE
|
|
|
f96e0b |
+ GRUB_NET_UDP_HEADER_SIZE
|
|
|
f96e0b |
+ sizeof (struct dns_header)
|
|
|
f96e0b |
- + grub_strlen (name) + 2 + 4
|
|
|
f96e0b |
- + 2 + 4);
|
|
|
f96e0b |
+ + grub_strlen (name) + 2 + 4);
|
|
|
f96e0b |
if (!nb)
|
|
|
f96e0b |
{
|
|
|
f96e0b |
grub_free (data.name);
|
|
|
f96e0b |
@@ -482,7 +489,7 @@ grub_net_dns_lookup (const char *name,
|
|
|
f96e0b |
+ GRUB_NET_MAX_LINK_HEADER_SIZE
|
|
|
f96e0b |
+ GRUB_NET_UDP_HEADER_SIZE);
|
|
|
f96e0b |
grub_netbuff_put (nb, sizeof (struct dns_header)
|
|
|
f96e0b |
- + grub_strlen (name) + 2 + 4 + 2 + 4);
|
|
|
f96e0b |
+ + grub_strlen (name) + 2 + 4);
|
|
|
f96e0b |
head = (struct dns_header *) nb->data;
|
|
|
f96e0b |
optr = (grub_uint8_t *) (head + 1);
|
|
|
f96e0b |
for (iptr = name; *iptr; )
|
|
|
f96e0b |
@@ -509,18 +516,7 @@ grub_net_dns_lookup (const char *name,
|
|
|
f96e0b |
|
|
|
f96e0b |
/* Type: A. */
|
|
|
f96e0b |
*optr++ = 0;
|
|
|
f96e0b |
- *optr++ = 1;
|
|
|
f96e0b |
-
|
|
|
f96e0b |
- /* Class. */
|
|
|
f96e0b |
- *optr++ = 0;
|
|
|
f96e0b |
- *optr++ = 1;
|
|
|
f96e0b |
-
|
|
|
f96e0b |
- /* Compressed name. */
|
|
|
f96e0b |
- *optr++ = 0xc0;
|
|
|
f96e0b |
- *optr++ = 0x0c;
|
|
|
f96e0b |
- /* Type: AAAA. */
|
|
|
f96e0b |
- *optr++ = 0;
|
|
|
f96e0b |
- *optr++ = 28;
|
|
|
f96e0b |
+ *optr++ = qtype;
|
|
|
f96e0b |
|
|
|
f96e0b |
/* Class. */
|
|
|
f96e0b |
*optr++ = 0;
|
|
|
f96e0b |
@@ -529,7 +525,7 @@ grub_net_dns_lookup (const char *name,
|
|
|
f96e0b |
head->id = data.id;
|
|
|
f96e0b |
head->flags = FLAGS_RD;
|
|
|
f96e0b |
head->ra_z_r_code = 0;
|
|
|
f96e0b |
- head->qdcount = grub_cpu_to_be16_compile_time (2);
|
|
|
f96e0b |
+ head->qdcount = grub_cpu_to_be16_compile_time (1);
|
|
|
f96e0b |
head->ancount = grub_cpu_to_be16_compile_time (0);
|
|
|
f96e0b |
head->nscount = grub_cpu_to_be16_compile_time (0);
|
|
|
f96e0b |
head->arcount = grub_cpu_to_be16_compile_time (0);
|
|
|
f96e0b |
@@ -587,16 +583,47 @@ grub_net_dns_lookup (const char *name,
|
|
|
f96e0b |
if (*data.naddresses)
|
|
|
f96e0b |
return GRUB_ERR_NONE;
|
|
|
f96e0b |
if (data.dns_err)
|
|
|
f96e0b |
- return grub_error (GRUB_ERR_NET_NO_DOMAIN,
|
|
|
f96e0b |
- N_("no DNS record found"));
|
|
|
f96e0b |
-
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ grub_dprintf ("dns", "%s. QTYPE: %u QNAME: %s\n",
|
|
|
f96e0b |
+ N_("no DNS record found"), qtype, name);
|
|
|
f96e0b |
+ return GRUB_ERR_NET_NO_DOMAIN;
|
|
|
f96e0b |
+ }
|
|
|
f96e0b |
if (err)
|
|
|
f96e0b |
{
|
|
|
f96e0b |
grub_errno = err;
|
|
|
f96e0b |
return err;
|
|
|
f96e0b |
}
|
|
|
f96e0b |
- return grub_error (GRUB_ERR_TIMEOUT,
|
|
|
f96e0b |
- N_("no DNS reply received"));
|
|
|
f96e0b |
+ grub_dprintf ("dns", "%s. QTYPE: %u QNAME: %s\n",
|
|
|
f96e0b |
+ N_("no DNS reply received"), qtype, name);
|
|
|
f96e0b |
+ return GRUB_ERR_TIMEOUT;
|
|
|
f96e0b |
+}
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+grub_err_t
|
|
|
f96e0b |
+grub_net_dns_lookup (const char *name,
|
|
|
f96e0b |
+ const struct grub_net_network_level_address *servers,
|
|
|
f96e0b |
+ grub_size_t n_servers,
|
|
|
f96e0b |
+ grub_size_t *naddresses,
|
|
|
f96e0b |
+ struct grub_net_network_level_address **addresses,
|
|
|
f96e0b |
+ int cache)
|
|
|
f96e0b |
+{
|
|
|
f96e0b |
+ if (dns_type_option == DNS_OPTION_IPV6 || dns_type_option == DNS_OPTION_PREFER_IPV6)
|
|
|
f96e0b |
+ grub_net_dns_lookup_qtype (name, servers, n_servers, naddresses,
|
|
|
f96e0b |
+ addresses, cache, GRUB_DNS_QTYPE_AAAA);
|
|
|
f96e0b |
+ else
|
|
|
f96e0b |
+ grub_net_dns_lookup_qtype (name, servers, n_servers, naddresses,
|
|
|
f96e0b |
+ addresses, cache, GRUB_DNS_QTYPE_A);
|
|
|
f96e0b |
+ if (!*naddresses)
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ if (dns_type_option == DNS_OPTION_PREFER_IPV4)
|
|
|
f96e0b |
+ grub_net_dns_lookup_qtype (name, servers, n_servers, naddresses,
|
|
|
f96e0b |
+ addresses, cache, GRUB_DNS_QTYPE_AAAA);
|
|
|
f96e0b |
+ else if (dns_type_option == DNS_OPTION_PREFER_IPV6)
|
|
|
f96e0b |
+ grub_net_dns_lookup_qtype (name, servers, n_servers, naddresses,
|
|
|
f96e0b |
+ addresses, cache, GRUB_DNS_QTYPE_A);
|
|
|
f96e0b |
+ }
|
|
|
f96e0b |
+ if (!*naddresses)
|
|
|
f96e0b |
+ return GRUB_ERR_NET_NO_DOMAIN;
|
|
|
f96e0b |
+ return GRUB_ERR_NONE;
|
|
|
f96e0b |
}
|
|
|
f96e0b |
|
|
|
f96e0b |
static grub_err_t
|
|
|
f96e0b |
@@ -604,22 +631,28 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)),
|
|
|
f96e0b |
int argc, char **args)
|
|
|
f96e0b |
{
|
|
|
f96e0b |
grub_err_t err;
|
|
|
f96e0b |
- grub_size_t naddresses, i;
|
|
|
f96e0b |
+ struct grub_net_network_level_address cmd_server;
|
|
|
f96e0b |
+ struct grub_net_network_level_address *servers;
|
|
|
f96e0b |
+ grub_size_t nservers, i, naddresses = 0;
|
|
|
f96e0b |
struct grub_net_network_level_address *addresses = 0;
|
|
|
f96e0b |
if (argc != 2 && argc != 1)
|
|
|
f96e0b |
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
|
|
|
f96e0b |
if (argc == 2)
|
|
|
f96e0b |
{
|
|
|
f96e0b |
- struct grub_net_network_level_address server;
|
|
|
f96e0b |
- err = grub_net_resolve_address (args[1], &server);
|
|
|
f96e0b |
+ err = grub_net_resolve_address (args[1], &cmd_server);
|
|
|
f96e0b |
if (err)
|
|
|
f96e0b |
return err;
|
|
|
f96e0b |
- err = grub_net_dns_lookup (args[0], &server, 1, &naddresses,
|
|
|
f96e0b |
- &addresses, 0);
|
|
|
f96e0b |
+ servers = &cmd_server;
|
|
|
f96e0b |
+ nservers = 1;
|
|
|
f96e0b |
}
|
|
|
f96e0b |
else
|
|
|
f96e0b |
- err = grub_net_dns_lookup (args[0], dns_servers, dns_nservers, &naddresses,
|
|
|
f96e0b |
- &addresses, 0);
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ servers = dns_servers;
|
|
|
f96e0b |
+ nservers = dns_nservers;
|
|
|
f96e0b |
+ }
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ grub_net_dns_lookup (args[0], servers, nservers, &naddresses,
|
|
|
f96e0b |
+ &addresses, 0);
|
|
|
f96e0b |
|
|
|
f96e0b |
for (i = 0; i < naddresses; i++)
|
|
|
f96e0b |
{
|
|
|
f96e0b |
@@ -628,7 +661,9 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)),
|
|
|
f96e0b |
grub_printf ("%s\n", buf);
|
|
|
f96e0b |
}
|
|
|
f96e0b |
grub_free (addresses);
|
|
|
f96e0b |
- return GRUB_ERR_NONE;
|
|
|
f96e0b |
+ if (naddresses)
|
|
|
f96e0b |
+ return GRUB_ERR_NONE;
|
|
|
f96e0b |
+ return grub_error (GRUB_ERR_NET_NO_DOMAIN, N_("no DNS record found"));
|
|
|
f96e0b |
}
|
|
|
f96e0b |
|
|
|
f96e0b |
static grub_err_t
|
|
|
f96e0b |
diff --git a/include/grub/net.h b/include/grub/net.h
|
|
|
f96e0b |
index 1bd7af2..e677246 100644
|
|
|
f96e0b |
--- a/include/grub/net.h
|
|
|
f96e0b |
+++ b/include/grub/net.h
|
|
|
f96e0b |
@@ -506,6 +506,15 @@ grub_err_t
|
|
|
f96e0b |
grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf,
|
|
|
f96e0b |
const grub_net_network_level_address_t *proto_addr,
|
|
|
f96e0b |
grub_net_link_level_address_t *hw_addr);
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+typedef enum
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ DNS_OPTION_IPV4,
|
|
|
f96e0b |
+ DNS_OPTION_IPV6,
|
|
|
f96e0b |
+ DNS_OPTION_PREFER_IPV4,
|
|
|
f96e0b |
+ DNS_OPTION_PREFER_IPV6
|
|
|
f96e0b |
+ } grub_dns_option_t;
|
|
|
f96e0b |
+
|
|
|
f96e0b |
grub_err_t
|
|
|
f96e0b |
grub_net_dns_lookup (const char *name,
|
|
|
f96e0b |
const struct grub_net_network_level_address *servers,
|
|
|
f96e0b |
--
|
|
|
f96e0b |
1.8.2.1
|
|
|
f96e0b |
|