issue separate DNS queries for ipv4 and ipv6
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. Fixes: https://savannah.gnu.org/bugs/?39710 * grub-core/net/bootp.c (parse_dhcp_vendor): Add DNS option. * grub-core/net/dns.c (grub_dns_qtype_id): New enum. * (grub_net_dns_lookup): Now using separated dns packages. * (grub_cmd_nslookup): Add error condition. * (grub_cmd_list_dns): Print DNS option. * (grub_cmd_add_dns): Add four parameters: --only-ipv4, * --only-ipv6, --prefer-ipv4, and --prefer-ipv6. * include/grub/net.h (grub_dns_option_t): New enum. * (grub_net_network_level_address): option added. Also-by: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com> Signed-off-by: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
This commit is contained in:
parent
339eacce1b
commit
9e236169e9
4 changed files with 125 additions and 39 deletions
21
ChangeLog
21
ChangeLog
|
@ -1,3 +1,24 @@
|
||||||
|
2013-11-05 Gustavo Luiz Duarte <gustavold@linux.vnet.ibm.com>
|
||||||
|
2013-11-05 Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
|
||||||
|
|
||||||
|
Issue separate DNS queries for ipv4 and ipv6
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Fixes: https://savannah.gnu.org/bugs/?39710
|
||||||
|
|
||||||
|
* grub-core/net/bootp.c (parse_dhcp_vendor): Add DNS option.
|
||||||
|
* grub-core/net/dns.c (grub_dns_qtype_id): New enum.
|
||||||
|
* (grub_net_dns_lookup): Now using separated dns packages.
|
||||||
|
* (grub_cmd_nslookup): Add error condition.
|
||||||
|
* (grub_cmd_list_dns): Print DNS option.
|
||||||
|
* (grub_cmd_add_dns): Add four parameters: --only-ipv4, --only-ipv6,
|
||||||
|
--prefer-ipv4, and --prefer-ipv6.
|
||||||
|
* include/grub/net.h (grub_dns_option_t): New enum.
|
||||||
|
* (grub_net_network_level_address): option added.
|
||||||
|
|
||||||
2013-11-05 Vladimir Testov <vladimir.testov@rosalab.ru>
|
2013-11-05 Vladimir Testov <vladimir.testov@rosalab.ru>
|
||||||
|
|
||||||
* grub-core/video/fb/video_fb.c: Merge two blit functions
|
* grub-core/video/fb/video_fb.c: Merge two blit functions
|
||||||
|
|
|
@ -123,6 +123,7 @@ parse_dhcp_vendor (const char *name, void *vend, int limit, int *mask)
|
||||||
struct grub_net_network_level_address s;
|
struct grub_net_network_level_address s;
|
||||||
s.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
s.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
||||||
s.ipv4 = grub_get_unaligned32 (ptr);
|
s.ipv4 = grub_get_unaligned32 (ptr);
|
||||||
|
s.option = DNS_OPTION_PREFER_IPV4;
|
||||||
grub_net_add_dns_server (&s);
|
grub_net_add_dns_server (&s);
|
||||||
ptr += 4;
|
ptr += 4;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,12 @@ struct dns_cache_element
|
||||||
#define DNS_CACHE_SIZE 1021
|
#define DNS_CACHE_SIZE 1021
|
||||||
#define DNS_HASH_BASE 423
|
#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 struct dns_cache_element dns_cache[DNS_CACHE_SIZE];
|
static struct dns_cache_element dns_cache[DNS_CACHE_SIZE];
|
||||||
static struct grub_net_network_level_address *dns_servers;
|
static struct grub_net_network_level_address *dns_servers;
|
||||||
static grub_size_t dns_nservers, dns_servers_alloc;
|
static grub_size_t dns_nservers, dns_servers_alloc;
|
||||||
|
@ -426,6 +432,7 @@ grub_net_dns_lookup (const char *name,
|
||||||
const char *iptr;
|
const char *iptr;
|
||||||
struct dns_header *head;
|
struct dns_header *head;
|
||||||
static grub_uint16_t id = 1;
|
static grub_uint16_t id = 1;
|
||||||
|
grub_uint8_t *qtypeptr;
|
||||||
grub_err_t err = GRUB_ERR_NONE;
|
grub_err_t err = GRUB_ERR_NONE;
|
||||||
struct recv_data data = {naddresses, addresses, cache,
|
struct recv_data data = {naddresses, addresses, cache,
|
||||||
grub_cpu_to_be16 (id++), 0, 0, name, 0};
|
grub_cpu_to_be16 (id++), 0, 0, name, 0};
|
||||||
|
@ -478,8 +485,7 @@ grub_net_dns_lookup (const char *name,
|
||||||
+ GRUB_NET_MAX_LINK_HEADER_SIZE
|
+ GRUB_NET_MAX_LINK_HEADER_SIZE
|
||||||
+ GRUB_NET_UDP_HEADER_SIZE
|
+ GRUB_NET_UDP_HEADER_SIZE
|
||||||
+ sizeof (struct dns_header)
|
+ sizeof (struct dns_header)
|
||||||
+ grub_strlen (name) + 2 + 4
|
+ grub_strlen (name) + 2 + 4);
|
||||||
+ 2 + 4);
|
|
||||||
if (!nb)
|
if (!nb)
|
||||||
{
|
{
|
||||||
grub_free (sockets);
|
grub_free (sockets);
|
||||||
|
@ -490,7 +496,7 @@ grub_net_dns_lookup (const char *name,
|
||||||
+ GRUB_NET_MAX_LINK_HEADER_SIZE
|
+ GRUB_NET_MAX_LINK_HEADER_SIZE
|
||||||
+ GRUB_NET_UDP_HEADER_SIZE);
|
+ GRUB_NET_UDP_HEADER_SIZE);
|
||||||
grub_netbuff_put (nb, sizeof (struct dns_header)
|
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;
|
head = (struct dns_header *) nb->data;
|
||||||
optr = (grub_uint8_t *) (head + 1);
|
optr = (grub_uint8_t *) (head + 1);
|
||||||
for (iptr = name; *iptr; )
|
for (iptr = name; *iptr; )
|
||||||
|
@ -516,20 +522,9 @@ grub_net_dns_lookup (const char *name,
|
||||||
}
|
}
|
||||||
*optr++ = 0;
|
*optr++ = 0;
|
||||||
|
|
||||||
/* Type: A. */
|
/* Type. */
|
||||||
*optr++ = 0;
|
*optr++ = 0;
|
||||||
*optr++ = 1;
|
qtypeptr = optr++;
|
||||||
|
|
||||||
/* Class. */
|
|
||||||
*optr++ = 0;
|
|
||||||
*optr++ = 1;
|
|
||||||
|
|
||||||
/* Compressed name. */
|
|
||||||
*optr++ = 0xc0;
|
|
||||||
*optr++ = 0x0c;
|
|
||||||
/* Type: AAAA. */
|
|
||||||
*optr++ = 0;
|
|
||||||
*optr++ = 28;
|
|
||||||
|
|
||||||
/* Class. */
|
/* Class. */
|
||||||
*optr++ = 0;
|
*optr++ = 0;
|
||||||
|
@ -538,7 +533,7 @@ grub_net_dns_lookup (const char *name,
|
||||||
head->id = data.id;
|
head->id = data.id;
|
||||||
head->flags = FLAGS_RD;
|
head->flags = FLAGS_RD;
|
||||||
head->ra_z_r_code = 0;
|
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->ancount = grub_cpu_to_be16_compile_time (0);
|
||||||
head->nscount = 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);
|
head->arcount = grub_cpu_to_be16_compile_time (0);
|
||||||
|
@ -572,18 +567,33 @@ grub_net_dns_lookup (const char *name,
|
||||||
goto out;
|
goto out;
|
||||||
for (j = 0; j < send_servers; j++)
|
for (j = 0; j < send_servers; j++)
|
||||||
{
|
{
|
||||||
grub_err_t err2;
|
grub_err_t err2;
|
||||||
if (!sockets[j])
|
if (!sockets[j])
|
||||||
continue;
|
continue;
|
||||||
nb->data = nbd;
|
nb->data = nbd;
|
||||||
err2 = grub_net_send_udp_packet (sockets[j], nb);
|
|
||||||
if (err2)
|
grub_size_t t = 0;
|
||||||
{
|
do
|
||||||
grub_errno = GRUB_ERR_NONE;
|
{
|
||||||
err = err2;
|
if (servers[j].option == DNS_OPTION_IPV4 ||
|
||||||
}
|
((servers[j].option == DNS_OPTION_PREFER_IPV4) && (t++ == 0)) ||
|
||||||
if (*data.naddresses)
|
((servers[j].option == DNS_OPTION_PREFER_IPV6) && (t++ == 1)))
|
||||||
goto out;
|
*qtypeptr = GRUB_DNS_QTYPE_A;
|
||||||
|
else
|
||||||
|
*qtypeptr = GRUB_DNS_QTYPE_AAAA;
|
||||||
|
|
||||||
|
grub_dprintf ("dns", "QTYPE: %u QNAME: %s\n", *qtypeptr, name);
|
||||||
|
|
||||||
|
err2 = grub_net_send_udp_packet (sockets[j], nb);
|
||||||
|
if (err2)
|
||||||
|
{
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
err = err2;
|
||||||
|
}
|
||||||
|
if (*data.naddresses)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
while (t == 1);
|
||||||
}
|
}
|
||||||
grub_net_poll_cards (200, &data.stop);
|
grub_net_poll_cards (200, &data.stop);
|
||||||
}
|
}
|
||||||
|
@ -615,22 +625,28 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)),
|
||||||
int argc, char **args)
|
int argc, char **args)
|
||||||
{
|
{
|
||||||
grub_err_t err;
|
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;
|
struct grub_net_network_level_address *addresses = 0;
|
||||||
if (argc != 2 && argc != 1)
|
if (argc != 2 && argc != 1)
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
|
||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
{
|
{
|
||||||
struct grub_net_network_level_address server;
|
err = grub_net_resolve_address (args[1], &cmd_server);
|
||||||
err = grub_net_resolve_address (args[1], &server);
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
err = grub_net_dns_lookup (args[0], &server, 1, &naddresses,
|
servers = &cmd_server;
|
||||||
&addresses, 0);
|
nservers = 1;
|
||||||
}
|
}
|
||||||
else
|
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++)
|
for (i = 0; i < naddresses; i++)
|
||||||
{
|
{
|
||||||
|
@ -639,7 +655,9 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)),
|
||||||
grub_printf ("%s\n", buf);
|
grub_printf ("%s\n", buf);
|
||||||
}
|
}
|
||||||
grub_free (addresses);
|
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
|
static grub_err_t
|
||||||
|
@ -648,11 +666,32 @@ grub_cmd_list_dns (struct grub_command *cmd __attribute__ ((unused)),
|
||||||
char **args __attribute__ ((unused)))
|
char **args __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
grub_size_t i;
|
grub_size_t i;
|
||||||
|
const char *strtype = "";
|
||||||
|
|
||||||
for (i = 0; i < dns_nservers; i++)
|
for (i = 0; i < dns_nservers; i++)
|
||||||
{
|
{
|
||||||
|
switch (dns_servers[i].option)
|
||||||
|
{
|
||||||
|
case DNS_OPTION_IPV4:
|
||||||
|
strtype = "only ipv4";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DNS_OPTION_IPV6:
|
||||||
|
strtype = "only ipv6";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DNS_OPTION_PREFER_IPV4:
|
||||||
|
strtype = "prefer ipv4";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DNS_OPTION_PREFER_IPV6:
|
||||||
|
strtype = "prefer ipv6";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
char buf[GRUB_NET_MAX_STR_ADDR_LEN];
|
char buf[GRUB_NET_MAX_STR_ADDR_LEN];
|
||||||
grub_net_addr_to_str (&dns_servers[i], buf);
|
grub_net_addr_to_str (&dns_servers[i], buf);
|
||||||
grub_printf ("%s\n", buf);
|
grub_printf ("%s (%s)\n", buf, strtype);
|
||||||
}
|
}
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
@ -664,8 +703,24 @@ grub_cmd_add_dns (struct grub_command *cmd __attribute__ ((unused)),
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
struct grub_net_network_level_address server;
|
struct grub_net_network_level_address server;
|
||||||
|
|
||||||
if (argc != 1)
|
if ((argc < 1) || (argc > 2))
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||||
|
else if (argc == 1)
|
||||||
|
server.option = DNS_OPTION_PREFER_IPV4;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (grub_strcmp (args[1], "--only-ipv4") == 0)
|
||||||
|
server.option = DNS_OPTION_IPV4;
|
||||||
|
else if (grub_strcmp (args[1], "--only-ipv6") == 0)
|
||||||
|
server.option = DNS_OPTION_IPV6;
|
||||||
|
else if (grub_strcmp (args[1], "--prefer-ipv4") == 0)
|
||||||
|
server.option = DNS_OPTION_PREFER_IPV4;
|
||||||
|
else if (grub_strcmp (args[1], "--prefer-ipv6") == 0)
|
||||||
|
server.option = DNS_OPTION_PREFER_IPV6;
|
||||||
|
else
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
|
||||||
|
}
|
||||||
|
|
||||||
err = grub_net_resolve_address (args[0], &server);
|
err = grub_net_resolve_address (args[0], &server);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -156,6 +156,14 @@ typedef enum grub_network_level_protocol_id
|
||||||
GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
|
GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
|
||||||
} grub_network_level_protocol_id_t;
|
} grub_network_level_protocol_id_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DNS_OPTION_IPV4,
|
||||||
|
DNS_OPTION_IPV6,
|
||||||
|
DNS_OPTION_PREFER_IPV4,
|
||||||
|
DNS_OPTION_PREFER_IPV6
|
||||||
|
} grub_dns_option_t;
|
||||||
|
|
||||||
typedef struct grub_net_network_level_address
|
typedef struct grub_net_network_level_address
|
||||||
{
|
{
|
||||||
grub_network_level_protocol_id_t type;
|
grub_network_level_protocol_id_t type;
|
||||||
|
@ -164,6 +172,7 @@ typedef struct grub_net_network_level_address
|
||||||
grub_uint32_t ipv4;
|
grub_uint32_t ipv4;
|
||||||
grub_uint64_t ipv6[2];
|
grub_uint64_t ipv6[2];
|
||||||
};
|
};
|
||||||
|
grub_dns_option_t option;
|
||||||
} grub_net_network_level_address_t;
|
} grub_net_network_level_address_t;
|
||||||
|
|
||||||
typedef struct grub_net_network_level_netaddress
|
typedef struct grub_net_network_level_netaddress
|
||||||
|
|
Loading…
Reference in a new issue