]> TLD Linux GIT Repositories - packages/grub2.git/blob - Issue-separate-DNS-queries-for-ipv4-and-ipv6.patch
- grub2 from PLD
[packages/grub2.git] / Issue-separate-DNS-queries-for-ipv4-and-ipv6.patch
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
5
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.
9
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.
17
18 Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=860829
19 ---
20  grub-core/net/dns.c | 99 ++++++++++++++++++++++++++++++++++++-----------------
21  include/grub/net.h  |  9 +++++
22  2 files changed, 76 insertions(+), 32 deletions(-)
23
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
31  
32 +typedef enum grub_dns_qtype_id
33 +  {
34 +    GRUB_DNS_QTYPE_A = 1,
35 +    GRUB_DNS_QTYPE_AAAA = 28
36 +  } grub_dns_qtype_id_t;
37 +
38 +static grub_dns_option_t dns_type_option = DNS_OPTION_PREFER_IPV4;
39 +
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)),
44    return GRUB_ERR_NONE;
45  }
46  
47 -grub_err_t
48 -grub_net_dns_lookup (const char *name,
49 +static grub_err_t
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,
55 -                    int cache)
56 +                    int cache, grub_dns_qtype_id_t qtype)
57  {
58    grub_size_t send_servers = 0;
59    grub_size_t i, j;
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
65 -                          + 2 + 4);
66 +                          + grub_strlen (name) + 2 + 4);
67    if (!nb)
68      {
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,
80  
81    /* Type: A.  */
82    *optr++ = 0;
83 -  *optr++ = 1;
84 -
85 -  /* Class.  */
86 -  *optr++ = 0;
87 -  *optr++ = 1;
88 -
89 -  /* Compressed name.  */
90 -  *optr++ = 0xc0;
91 -  *optr++ = 0x0c;
92 -  /* Type: AAAA.  */
93 -  *optr++ = 0;
94 -  *optr++ = 28;
95 +  *optr++ = qtype;
96  
97    /* Class.  */
98    *optr++ = 0;
99 @@ -529,7 +525,7 @@ grub_net_dns_lookup (const char *name,
100    head->id = data.id;
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;
111    if (data.dns_err)
112 -    return grub_error (GRUB_ERR_NET_NO_DOMAIN,
113 -                      N_("no DNS record found"));
114 -    
115 +    {
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;
119 +    }
120    if (err)
121      {
122        grub_errno = err;
123        return err;
124      }
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;
130 +}
131 +
132 +grub_err_t
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,
138 +                    int cache)
139 +{
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);
143 +  else
144 +      grub_net_dns_lookup_qtype (name, servers, n_servers, naddresses,
145 +                                 addresses, cache, GRUB_DNS_QTYPE_A);
146 +  if (!*naddresses)
147 +    {
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);
154 +    }
155 +  if (!*naddresses)
156 +      return GRUB_ERR_NET_NO_DOMAIN;
157 +  return GRUB_ERR_NONE;
158  }
159  
160  static grub_err_t
161 @@ -604,22 +631,28 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)),
162                    int argc, char **args)
163  {
164    grub_err_t err;
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"));
172    if (argc == 2)
173      {
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);
177        if (err)
178         return err;
179 -      err = grub_net_dns_lookup (args[0], &server, 1, &naddresses,
180 -                                &addresses, 0);
181 +      servers = &cmd_server;
182 +      nservers = 1;
183      }
184    else
185 -    err = grub_net_dns_lookup (args[0], dns_servers, dns_nservers, &naddresses,
186 -                              &addresses, 0);
187 +    {
188 +      servers = dns_servers;
189 +      nservers = dns_nservers;
190 +    }
191 +
192 +  grub_net_dns_lookup (args[0], servers, nservers, &naddresses,
193 +                       &addresses, 0);
194  
195    for (i = 0; i < naddresses; i++)
196      {
197 @@ -628,7 +661,9 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)),
198        grub_printf ("%s\n", buf);
199      }
200    grub_free (addresses);
201 -  return GRUB_ERR_NONE;
202 +  if (naddresses)
203 +    return GRUB_ERR_NONE;
204 +  return grub_error (GRUB_ERR_NET_NO_DOMAIN, N_("no DNS record found"));
205  }
206  
207  static grub_err_t
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);
216 +
217 +typedef enum
218 +  {
219 +    DNS_OPTION_IPV4,
220 +    DNS_OPTION_IPV6,
221 +    DNS_OPTION_PREFER_IPV4,
222 +    DNS_OPTION_PREFER_IPV6
223 +  } grub_dns_option_t;
224 +
225  grub_err_t
226  grub_net_dns_lookup (const char *name,
227                      const struct grub_net_network_level_address *servers,
228 -- 
229 1.7.11.4
230