From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1TOHvE-0004E5-Kv for mharc-grub-devel@gnu.org; Tue, 16 Oct 2012 20:55:44 -0400 Received: from eggs.gnu.org ([208.118.235.92]:44678) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TOHvC-0004CV-5b for grub-devel@gnu.org; Tue, 16 Oct 2012 20:55:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TOHvA-0002Tm-32 for grub-devel@gnu.org; Tue, 16 Oct 2012 20:55:42 -0400 Received: from e24smtp02.br.ibm.com ([32.104.18.86]:45625) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TOHv9-0002Rg-JJ for grub-devel@gnu.org; Tue, 16 Oct 2012 20:55:40 -0400 Received: from /spool/local by e24smtp02.br.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 16 Oct 2012 21:55:28 -0300 Received: from d24dlp02.br.ibm.com (9.18.248.206) by e24smtp02.br.ibm.com (10.172.0.142) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 16 Oct 2012 21:55:26 -0300 Received: from d24relay03.br.ibm.com (d24relay03.br.ibm.com [9.13.184.25]) by d24dlp02.br.ibm.com (Postfix) with ESMTP id 585BD1DC0054 for ; Tue, 16 Oct 2012 20:55:25 -0400 (EDT) Received: from d24av03.br.ibm.com (d24av03.br.ibm.com [9.8.31.95]) by d24relay03.br.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q9H0sChW45023388 for ; Tue, 16 Oct 2012 21:54:12 -0300 Received: from d24av03.br.ibm.com (loopback [127.0.0.1]) by d24av03.br.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q9GMtj13015541 for ; Tue, 16 Oct 2012 19:55:45 -0300 Received: from [9.8.7.129] ([9.8.7.129]) by d24av03.br.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id q9GMtjYu015531 for ; Tue, 16 Oct 2012 19:55:45 -0300 Message-ID: <507E01FB.4050303@linux.vnet.ibm.com> Date: Tue, 16 Oct 2012 21:55:23 -0300 From: Gustavo Luiz Duarte User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:16.0) Gecko/20121009 Thunderbird/16.0 MIME-Version: 1.0 To: grub-devel@gnu.org Subject: [PATCH] Issue separate DNS queries for ipv4 and ipv6 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-Content-Scanned: Fidelis XPS MAILER x-cbid: 12101700-2194-0000-0000-00000362967E X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 32.104.18.86 X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 17 Oct 2012 00:55:43 -0000 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