DNS cache support
This commit is contained in:
parent
3729fcfc1a
commit
8d4e4fc0e5
1 changed files with 119 additions and 50 deletions
|
@ -21,16 +21,21 @@
|
||||||
#include <grub/command.h>
|
#include <grub/command.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
#include <grub/err.h>
|
#include <grub/err.h>
|
||||||
|
#include <grub/time.h>
|
||||||
|
|
||||||
struct dns_cache_element
|
struct dns_cache_element
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
grub_size_t naddresses;
|
grub_size_t naddresses;
|
||||||
struct grub_net_network_level_address *addresses;
|
struct grub_net_network_level_address *addresses;
|
||||||
struct grub_net_network_level_address *source;
|
|
||||||
grub_uint64_t limit_time;
|
grub_uint64_t limit_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define DNS_CACHE_SIZE 1021
|
||||||
|
#define DNS_HASH_BASE 423
|
||||||
|
|
||||||
|
static struct dns_cache_element dns_cache[DNS_CACHE_SIZE];
|
||||||
|
|
||||||
struct dns_header
|
struct dns_header
|
||||||
{
|
{
|
||||||
grub_uint16_t id;
|
grub_uint16_t id;
|
||||||
|
@ -67,8 +72,25 @@ struct recv_data
|
||||||
grub_uint16_t id;
|
grub_uint16_t id;
|
||||||
int dns_err;
|
int dns_err;
|
||||||
char *name;
|
char *name;
|
||||||
|
const char *oname;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
hash (const char *str)
|
||||||
|
{
|
||||||
|
int v = 0, xn = 1;
|
||||||
|
const char *ptr;
|
||||||
|
for (ptr = str; *ptr; )
|
||||||
|
{
|
||||||
|
v = (v + xn * *ptr);
|
||||||
|
xn = (DNS_HASH_BASE * xn) % DNS_CACHE_SIZE;
|
||||||
|
ptr++;
|
||||||
|
if (((ptr - str) & 0x3ff) == 0)
|
||||||
|
v %= DNS_CACHE_SIZE;
|
||||||
|
}
|
||||||
|
return v % DNS_CACHE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head,
|
check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head,
|
||||||
const grub_uint8_t *tail, const char *check_with,
|
const grub_uint8_t *tail, const char *check_with,
|
||||||
|
@ -172,6 +194,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)),
|
||||||
grub_uint8_t *ptr, *reparse_ptr;
|
grub_uint8_t *ptr, *reparse_ptr;
|
||||||
int redirect_cnt = 0;
|
int redirect_cnt = 0;
|
||||||
char *redirect_save = NULL;
|
char *redirect_save = NULL;
|
||||||
|
grub_uint32_t ttl_all = ~0U;
|
||||||
|
|
||||||
head = (struct dns_header *) nb->data;
|
head = (struct dns_header *) nb->data;
|
||||||
ptr = (grub_uint8_t *) (head + 1);
|
ptr = (grub_uint8_t *) (head + 1);
|
||||||
|
@ -255,8 +278,8 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)),
|
||||||
ignored = 1;
|
ignored = 1;
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
{
|
{
|
||||||
ttl >>= 8;
|
ttl <<= 8;
|
||||||
ttl = *ptr++ << 28;
|
ttl |= *ptr++;
|
||||||
}
|
}
|
||||||
length = *ptr++ << 8;
|
length = *ptr++ << 8;
|
||||||
length |= *ptr++;
|
length |= *ptr++;
|
||||||
|
@ -268,6 +291,9 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)),
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
if (!ignored)
|
if (!ignored)
|
||||||
|
{
|
||||||
|
if (ttl_all > ttl)
|
||||||
|
ttl_all = ttl;
|
||||||
switch (class)
|
switch (class)
|
||||||
{
|
{
|
||||||
case DNS_CLASS_A:
|
case DNS_CLASS_A:
|
||||||
|
@ -313,8 +339,34 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)),
|
||||||
}
|
}
|
||||||
goto reparse;
|
goto reparse;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ptr += length;
|
ptr += length;
|
||||||
}
|
}
|
||||||
|
if (ttl_all && *data->naddresses && data->cache)
|
||||||
|
{
|
||||||
|
int h;
|
||||||
|
grub_dprintf ("dns", "caching for %d seconds\n", ttl_all);
|
||||||
|
h = hash (data->oname);
|
||||||
|
grub_free (dns_cache[h].name);
|
||||||
|
dns_cache[h].name = 0;
|
||||||
|
grub_free (dns_cache[h].addresses);
|
||||||
|
dns_cache[h].addresses = 0;
|
||||||
|
dns_cache[h].name = grub_strdup (data->oname);
|
||||||
|
dns_cache[h].naddresses = *data->naddresses;
|
||||||
|
dns_cache[h].addresses = grub_malloc (*data->naddresses
|
||||||
|
* sizeof (dns_cache[h].addresses[0]));
|
||||||
|
dns_cache[h].limit_time = grub_get_time_ms () + 1000 * ttl_all;
|
||||||
|
if (!dns_cache[h].addresses || !dns_cache[h].name)
|
||||||
|
{
|
||||||
|
grub_free (dns_cache[h].name);
|
||||||
|
dns_cache[h].name = 0;
|
||||||
|
grub_free (dns_cache[h].addresses);
|
||||||
|
dns_cache[h].addresses = 0;
|
||||||
|
}
|
||||||
|
grub_memcpy (dns_cache[h].addresses, *data->addresses,
|
||||||
|
*data->naddresses
|
||||||
|
* sizeof (dns_cache[h].addresses[0]));
|
||||||
|
}
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
grub_free (redirect_save);
|
grub_free (redirect_save);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
@ -338,18 +390,35 @@ grub_net_dns_lookup (const char *name,
|
||||||
static grub_uint16_t id = 1;
|
static grub_uint16_t id = 1;
|
||||||
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};
|
grub_cpu_to_be16 (id++), 0, 0, name};
|
||||||
grub_uint8_t *nbd;
|
grub_uint8_t *nbd;
|
||||||
int have_server = 0;
|
int have_server = 0;
|
||||||
|
|
||||||
|
*naddresses = 0;
|
||||||
|
if (cache)
|
||||||
|
{
|
||||||
|
int h;
|
||||||
|
h = hash (name);
|
||||||
|
if (dns_cache[h].name && grub_strcmp (dns_cache[h].name, name) == 0
|
||||||
|
&& grub_get_time_ms () < dns_cache[h].limit_time)
|
||||||
|
{
|
||||||
|
grub_dprintf ("dns", "retrieved from cache\n");
|
||||||
|
*addresses = grub_malloc (dns_cache[h].naddresses
|
||||||
|
* sizeof ((*addresses)[0]));
|
||||||
|
if (!*addresses)
|
||||||
|
return grub_errno;
|
||||||
|
*naddresses = dns_cache[h].naddresses;
|
||||||
|
grub_memcpy (*addresses, dns_cache[h].addresses,
|
||||||
|
dns_cache[h].naddresses
|
||||||
|
* sizeof ((*addresses)[0]));
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data.name = grub_strdup (name);
|
data.name = grub_strdup (name);
|
||||||
if (!data.name)
|
if (!data.name)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
*naddresses = 0;
|
|
||||||
/* if (cache && cache_lookup (name, servers, n_servers, addresses))
|
|
||||||
return GRUB_ERR_NONE;*/
|
|
||||||
|
|
||||||
nb = grub_netbuff_alloc (GRUB_NET_OUR_MAX_IP_HEADER_SIZE
|
nb = grub_netbuff_alloc (GRUB_NET_OUR_MAX_IP_HEADER_SIZE
|
||||||
+ GRUB_NET_MAX_LINK_HEADER_SIZE
|
+ GRUB_NET_MAX_LINK_HEADER_SIZE
|
||||||
+ GRUB_NET_UDP_HEADER_SIZE
|
+ GRUB_NET_UDP_HEADER_SIZE
|
||||||
|
|
Loading…
Add table
Reference in a new issue