1 From 3e00d82827f80461f9fe6da37acd84235c08e5a5 Mon Sep 17 00:00:00 2001
2 From: Gustavo Luiz Duarte <gustavold@linux.vnet.ibm.com>
3 Date: Fri, 28 Sep 2012 19:42:07 -0400
4 Subject: [PATCH] Issue separate DNS queries for ipv4 and ipv6
6 Adding multiple questions on a single DNS query is not supportted by
7 most DNS servers. This patch issues two separate DNS queries
8 sequentially for ipv4 and then for ipv6.
10 There are 4 possible config options:
11 DNS_OPTION_IPV4: issue only one ipv4 query
12 DNS_OPTION_IPV6: issue only one ipv6 query
13 DNS_OPTION_PREFER_IPV4: issue the ipv4 query first and fallback to ipv6
14 DNS_OPTION_PREFER_IPV6: issue the ipv6 query first and fallback to ipv4
15 However, there is no code yet to set such config option. The default is
16 DNS_OPTION_PREFER_IPV4.
18 Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=860829
20 grub-core/net/dns.c | 99 ++++++++++++++++++++++++++++++++++++-----------------
21 include/grub/net.h | 9 +++++
22 2 files changed, 76 insertions(+), 32 deletions(-)
24 diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
25 index 3381ea7..725725c 100644
26 --- a/grub-core/net/dns.c
27 +++ b/grub-core/net/dns.c
28 @@ -34,6 +34,14 @@ struct dns_cache_element
29 #define DNS_CACHE_SIZE 1021
30 #define DNS_HASH_BASE 423
32 +typedef enum grub_dns_qtype_id
34 + GRUB_DNS_QTYPE_A = 1,
35 + GRUB_DNS_QTYPE_AAAA = 28
36 + } grub_dns_qtype_id_t;
38 +static grub_dns_option_t dns_type_option = DNS_OPTION_PREFER_IPV4;
40 static struct dns_cache_element dns_cache[DNS_CACHE_SIZE];
41 static struct grub_net_network_level_address *dns_servers;
42 static grub_size_t dns_nservers, dns_servers_alloc;
43 @@ -410,13 +418,13 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)),
48 -grub_net_dns_lookup (const char *name,
50 +grub_net_dns_lookup_qtype (const char *name,
51 const struct grub_net_network_level_address *servers,
52 grub_size_t n_servers,
53 grub_size_t *naddresses,
54 struct grub_net_network_level_address **addresses,
56 + int cache, grub_dns_qtype_id_t qtype)
58 grub_size_t send_servers = 0;
60 @@ -471,8 +479,7 @@ grub_net_dns_lookup (const char *name,
61 + GRUB_NET_MAX_LINK_HEADER_SIZE
62 + GRUB_NET_UDP_HEADER_SIZE
63 + sizeof (struct dns_header)
64 - + grub_strlen (name) + 2 + 4
66 + + grub_strlen (name) + 2 + 4);
69 grub_free (data.name);
70 @@ -482,7 +489,7 @@ grub_net_dns_lookup (const char *name,
71 + GRUB_NET_MAX_LINK_HEADER_SIZE
72 + GRUB_NET_UDP_HEADER_SIZE);
73 grub_netbuff_put (nb, sizeof (struct dns_header)
74 - + grub_strlen (name) + 2 + 4 + 2 + 4);
75 + + grub_strlen (name) + 2 + 4);
76 head = (struct dns_header *) nb->data;
77 optr = (grub_uint8_t *) (head + 1);
78 for (iptr = name; *iptr; )
79 @@ -509,18 +516,7 @@ grub_net_dns_lookup (const char *name,
89 - /* Compressed name. */
99 @@ -529,7 +525,7 @@ grub_net_dns_lookup (const char *name,
101 head->flags = FLAGS_RD;
102 head->ra_z_r_code = 0;
103 - head->qdcount = grub_cpu_to_be16_compile_time (2);
104 + head->qdcount = grub_cpu_to_be16_compile_time (1);
105 head->ancount = grub_cpu_to_be16_compile_time (0);
106 head->nscount = grub_cpu_to_be16_compile_time (0);
107 head->arcount = grub_cpu_to_be16_compile_time (0);
108 @@ -587,16 +583,47 @@ grub_net_dns_lookup (const char *name,
109 if (*data.naddresses)
110 return GRUB_ERR_NONE;
112 - return grub_error (GRUB_ERR_NET_NO_DOMAIN,
113 - N_("no DNS record found"));
116 + grub_dprintf ("dns", "%s. QTYPE: %u QNAME: %s\n",
117 + N_("no DNS record found"), qtype, name);
118 + return GRUB_ERR_NET_NO_DOMAIN;
125 - return grub_error (GRUB_ERR_TIMEOUT,
126 - N_("no DNS reply received"));
127 + grub_dprintf ("dns", "%s. QTYPE: %u QNAME: %s\n",
128 + N_("no DNS reply received"), qtype, name);
129 + return GRUB_ERR_TIMEOUT;
133 +grub_net_dns_lookup (const char *name,
134 + const struct grub_net_network_level_address *servers,
135 + grub_size_t n_servers,
136 + grub_size_t *naddresses,
137 + struct grub_net_network_level_address **addresses,
140 + if (dns_type_option == DNS_OPTION_IPV6 || dns_type_option == DNS_OPTION_PREFER_IPV6)
141 + grub_net_dns_lookup_qtype (name, servers, n_servers, naddresses,
142 + addresses, cache, GRUB_DNS_QTYPE_AAAA);
144 + grub_net_dns_lookup_qtype (name, servers, n_servers, naddresses,
145 + addresses, cache, GRUB_DNS_QTYPE_A);
148 + if (dns_type_option == DNS_OPTION_PREFER_IPV4)
149 + grub_net_dns_lookup_qtype (name, servers, n_servers, naddresses,
150 + addresses, cache, GRUB_DNS_QTYPE_AAAA);
151 + else if (dns_type_option == DNS_OPTION_PREFER_IPV6)
152 + grub_net_dns_lookup_qtype (name, servers, n_servers, naddresses,
153 + addresses, cache, GRUB_DNS_QTYPE_A);
156 + return GRUB_ERR_NET_NO_DOMAIN;
157 + return GRUB_ERR_NONE;
161 @@ -604,22 +631,28 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)),
162 int argc, char **args)
165 - grub_size_t naddresses, i;
166 + struct grub_net_network_level_address cmd_server;
167 + struct grub_net_network_level_address *servers;
168 + grub_size_t nservers, i, naddresses = 0;
169 struct grub_net_network_level_address *addresses = 0;
170 if (argc != 2 && argc != 1)
171 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
174 - struct grub_net_network_level_address server;
175 - err = grub_net_resolve_address (args[1], &server);
176 + err = grub_net_resolve_address (args[1], &cmd_server);
179 - err = grub_net_dns_lookup (args[0], &server, 1, &naddresses,
181 + servers = &cmd_server;
185 - err = grub_net_dns_lookup (args[0], dns_servers, dns_nservers, &naddresses,
188 + servers = dns_servers;
189 + nservers = dns_nservers;
192 + grub_net_dns_lookup (args[0], servers, nservers, &naddresses,
195 for (i = 0; i < naddresses; i++)
197 @@ -628,7 +661,9 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)),
198 grub_printf ("%s\n", buf);
200 grub_free (addresses);
201 - return GRUB_ERR_NONE;
203 + return GRUB_ERR_NONE;
204 + return grub_error (GRUB_ERR_NET_NO_DOMAIN, N_("no DNS record found"));
208 diff --git a/include/grub/net.h b/include/grub/net.h
209 index 3877451..a7e5b2c 100644
210 --- a/include/grub/net.h
211 +++ b/include/grub/net.h
212 @@ -505,6 +505,15 @@ grub_err_t
213 grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf,
214 const grub_net_network_level_address_t *proto_addr,
215 grub_net_link_level_address_t *hw_addr);
221 + DNS_OPTION_PREFER_IPV4,
222 + DNS_OPTION_PREFER_IPV6
223 + } grub_dns_option_t;
226 grub_net_dns_lookup (const char *name,
227 const struct grub_net_network_level_address *servers,