[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v1] dns: fixed lookup error when no IPv6 is returned
From: |
Renaud Métrich |
Subject: |
[PATCH v1] dns: fixed lookup error when no IPv6 is returned |
Date: |
Fri, 28 Apr 2023 13:17:44 +0200 |
When trying to resolve DNS names into IP addresses, the DNS code fails
from time to time with the following error:
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
error: ../../grub-core/net/dns.c:688:no DNS record found.
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
This happens when both IPv4 and IPv6 queries are performed against the
DNS server (e.g. 8.8.8.8) but there is no IP returned for IPv6 query, as
shown below:
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
grub> net_del_dns 192.168.122.1
grub> net_add_dns 8.8.8.8
grub> net_nslookup ipv4.test-ipv6.com
error: ../../grub-core/net/dns.c:688:no DNS record found.
grub> net_nslookup ipv4.test-ipv6.com
216.218.228.115
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
The root cause is the code exiting prematurely when the data->addresses
buffer has been allocated in recv_hook(), even if there was no address
returned last time recv_hook() executed.
This patch additionally simplifies the error handling.
Signed-off-by: Renaud Métrich <rmetrich@redhat.com>
---
grub-core/net/dns.c | 69 +++++++++++++++------------------------------
1 file changed, 23 insertions(+), 46 deletions(-)
diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
index afa389494..2dfb98d98 100644
--- a/grub-core/net/dns.c
+++ b/grub-core/net/dns.c
@@ -261,43 +261,27 @@ recv_hook (grub_net_udp_socket_t sock __attribute__
((unused)),
/* Code apparently assumed that only one packet is received as response.
We may get multiple responses due to network condition, so check here
and quit early. */
- if (*data->addresses)
- {
- grub_netbuff_free (nb);
- return GRUB_ERR_NONE;
- }
+ if (*data->naddresses)
+ goto out;
head = (struct dns_header *) nb->data;
ptr = (grub_uint8_t *) (head + 1);
if (ptr >= nb->tail)
- {
- grub_netbuff_free (nb);
- return GRUB_ERR_NONE;
- }
+ goto out;
if (head->id != data->id)
- {
- grub_netbuff_free (nb);
- return GRUB_ERR_NONE;
- }
+ goto out;
if (!(head->flags & FLAGS_RESPONSE) || (head->flags & FLAGS_OPCODE))
- {
- grub_netbuff_free (nb);
- return GRUB_ERR_NONE;
- }
+ goto out;
if (head->ra_z_r_code & ERRCODE_MASK)
{
data->dns_err = 1;
- grub_netbuff_free (nb);
- return GRUB_ERR_NONE;
+ goto out;
}
for (i = 0; i < grub_be_to_cpu16 (head->qdcount); i++)
{
if (ptr >= nb->tail)
- {
- grub_netbuff_free (nb);
- return GRUB_ERR_NONE;
- }
+ goto out;
while (ptr < nb->tail && !((*ptr & 0xc0) || *ptr == 0))
ptr += *ptr + 1;
if (ptr < nb->tail && (*ptr & 0xc0))
@@ -310,8 +294,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__
((unused)),
if (!*data->addresses)
{
grub_errno = GRUB_ERR_NONE;
- grub_netbuff_free (nb);
- return GRUB_ERR_NONE;
+ goto out;
}
reparse_ptr = ptr;
reparse:
@@ -322,11 +305,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__
((unused)),
grub_uint32_t ttl = 0;
grub_uint16_t length;
if (ptr >= nb->tail)
- {
- if (!*data->naddresses)
- grub_free (*data->addresses);
- return GRUB_ERR_NONE;
- }
+ goto out;
ignored = !check_name (ptr, nb->data, nb->tail, data->name);
while (ptr < nb->tail && !((*ptr & 0xc0) || *ptr == 0))
ptr += *ptr + 1;
@@ -334,12 +313,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__
((unused)),
ptr++;
ptr++;
if (ptr + 10 >= nb->tail)
- {
- if (!*data->naddresses)
- grub_free (*data->addresses);
- grub_netbuff_free (nb);
- return GRUB_ERR_NONE;
- }
+ goto out;
if (*ptr++ != 0)
ignored = 1;
class = *ptr++;
@@ -355,12 +329,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__
((unused)),
length = *ptr++ << 8;
length |= *ptr++;
if (ptr + length > nb->tail)
- {
- if (!*data->naddresses)
- grub_free (*data->addresses);
- grub_netbuff_free (nb);
- return GRUB_ERR_NONE;
- }
+ goto out;
if (!ignored)
{
if (ttl_all > ttl)
@@ -374,6 +343,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__
((unused)),
= GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
grub_memcpy (&(*data->addresses)[*data->naddresses].ipv4,
ptr, 4);
+ grub_dprintf ("dns", "got A 0x%x\n",
(*data->addresses)[*data->naddresses].ipv4);
(*data->naddresses)++;
data->stop = 1;
break;
@@ -384,6 +354,10 @@ recv_hook (grub_net_udp_socket_t sock __attribute__
((unused)),
= GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
grub_memcpy (&(*data->addresses)[*data->naddresses].ipv6,
ptr, 16);
+ grub_dprintf ("dns", "got AAAA 0x%lx%lx\n",
+ (*data->addresses)[*data->naddresses].ipv6[0],
+ (*data->addresses)[*data->naddresses].ipv6[1]
+ );
(*data->naddresses)++;
data->stop = 1;
break;
@@ -400,15 +374,14 @@ recv_hook (grub_net_udp_socket_t sock __attribute__
((unused)),
if (!data->name)
{
data->dns_err = 1;
- grub_errno = 0;
- return GRUB_ERR_NONE;
+ grub_errno = GRUB_ERR_NONE;
+ goto out;
}
grub_dprintf ("dns", "CNAME %s\n", data->name);
if (grub_strcmp (redirect_save, data->name) == 0)
{
data->dns_err = 1;
- grub_free (redirect_save);
- return GRUB_ERR_NONE;
+ goto out;
}
goto reparse;
}
@@ -440,8 +413,12 @@ recv_hook (grub_net_udp_socket_t sock __attribute__
((unused)),
*data->naddresses
* sizeof (dns_cache[h].addresses[0]));
}
+
+ out:
grub_netbuff_free (nb);
grub_free (redirect_save);
+ if (!*data->naddresses)
+ grub_free (*data->addresses);
return GRUB_ERR_NONE;
}
--
2.40.0
- [PATCH v1] dns: fixed lookup error when no IPv6 is returned,
Renaud Métrich <=