Add --cache-rr to enable caching of arbitrary RR types.

This commit is contained in:
Simon Kelley committed 2023-03-23 17:15:35 +00:00
1 parent 88fc6c8023
commit 638c7c4d20
9 files changed
+416 -174

No files matched your search

+37 -8
View File
@@ -29,6 +29,7 @@ static void make_non_terminals(struct crec *source);
static struct crec *really_insert(char *name, union all_addr *addr, unsigned short class,
time_t now, unsigned long ttl, unsigned int flags);
static void dump_cache_entry(struct crec *cache, time_t now);
static char *querystr(char *desc, unsigned short type);
/* type->string mapping: this is also used by the name-hash function as a mixing table. */
/* taken from https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml */
@@ -133,6 +134,17 @@ static void cache_link(struct crec *crecp);
static void rehash(int size);
static void cache_hash(struct crec *crecp);
unsigned short rrtype(char *in)
{
int i;
for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
if (strcasecmp(in, typestr[i].name) == 0)
return typestr[i].type;
return 0;
}
void next_uid(struct crec *crecp)
{
static unsigned int uid = 0;
@@ -265,6 +277,8 @@ static void cache_blockdata_free(struct crec *crecp)
{
if (crecp->flags & F_SRV)
blockdata_free(crecp->addr.srv.target);
else if (crecp->flags & F_RR)
blockdata_free(crecp->addr.rr.rrdata);
#ifdef HAVE_DNSSEC
else if (crecp->flags & F_DNSKEY)
blockdata_free(crecp->addr.key.keydata);
@@ -459,7 +473,8 @@ static struct crec *cache_scan_free(char *name, union all_addr *addr, unsigned s
{
/* Don't delete DNSSEC in favour of a CNAME, they can co-exist */
if ((flags & crecp->flags & (F_IPV4 | F_IPV6 | F_SRV | F_NXDOMAIN)) ||
(((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS))))
(((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS))) ||
((crecp->flags & flags & F_RR) && addr->rr.rrtype == crecp->addr.rr.rrtype))
{
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
return crecp;
@@ -776,7 +791,7 @@ void cache_end_insert(void)
read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->ttd, sizeof(new_chain->ttd), 0);
read_write(daemon->pipe_to_parent, (unsigned char *)&flags, sizeof(flags), 0);
if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS | F_SRV))
if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS | F_SRV | F_RR))
read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr, sizeof(new_chain->addr), 0);
if (flags & F_SRV)
{
@@ -784,6 +799,12 @@ void cache_end_insert(void)
if (!(flags & F_NEG))
blockdata_write(new_chain->addr.srv.target, new_chain->addr.srv.targetlen, daemon->pipe_to_parent);
}
if (flags & F_RR)
{
/* A negative RR entry is possible and has no data, obviously. */
if (!(flags & F_NEG))
blockdata_write(new_chain->addr.rr.rrdata, new_chain->addr.rr.datalen, daemon->pipe_to_parent);
}
#ifdef HAVE_DNSSEC
if (flags & F_DNSKEY)
{
@@ -848,16 +869,18 @@ int cache_recv_insert(time_t now, int fd)
ttl = difftime(ttd, now);
if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS | F_SRV))
if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS | F_SRV | F_RR))
{
unsigned short class = C_IN;
if (!read_write(fd, (unsigned char *)&addr, sizeof(addr), 1))
return 0;
if ((flags & F_SRV) && !(flags & F_NEG) && !(addr.srv.target = blockdata_read(fd, addr.srv.targetlen)))
return 0;
if ((flags & F_RR) && !(flags & F_NEG) && !(addr.rr.rrdata = blockdata_read(fd, addr.rr.datalen)))
return 0;
#ifdef HAVE_DNSSEC
if (flags & F_DNSKEY)
{
@@ -1587,7 +1610,7 @@ static void make_non_terminals(struct crec *source)
if (!is_outdated_cname_pointer(crecp) &&
(crecp->flags & F_FORWARD) &&
(crecp->flags & type) &&
!(crecp->flags & (F_IPV4 | F_IPV6 | F_CNAME | F_SRV | F_DNSKEY | F_DS)) &&
!(crecp->flags & (F_IPV4 | F_IPV6 | F_CNAME | F_SRV | F_DNSKEY | F_DS | F_RR)) &&
hostname_isequal(name, cache_get_name(crecp)))
{
*up = crecp->hash_next;
@@ -1644,7 +1667,7 @@ static void make_non_terminals(struct crec *source)
if (crecp)
{
crecp->flags = (source->flags | F_NAMEP) & ~(F_IPV4 | F_IPV6 | F_CNAME | F_SRV | F_DNSKEY | F_DS | F_REVERSE);
crecp->flags = (source->flags | F_NAMEP) & ~(F_IPV4 | F_IPV6 | F_CNAME | F_SRV | F_RR | F_DNSKEY | F_DS | F_REVERSE);
if (!(crecp->flags & F_IMMORTAL))
crecp->ttd = source->ttd;
crecp->name.namep = name;
@@ -1792,6 +1815,8 @@ static void dump_cache_entry(struct crec *cache, time_t now)
blockdata_retrieve(cache->addr.srv.target, targetlen, a + len);
a[len + targetlen] = 0;
}
else if (cache->flags & F_RR)
sprintf(a, "%s", querystr(NULL, cache->addr.rr.rrtype));
#ifdef HAVE_DNSSEC
else if (cache->flags & F_DS)
{
@@ -1820,6 +1845,8 @@ static void dump_cache_entry(struct crec *cache, time_t now)
t = "C";
else if (cache->flags & F_SRV)
t = "V";
else if (cache->flags & F_RR)
t = "T";
#ifdef HAVE_DNSSEC
else if (cache->flags & F_DS)
t = "S";
@@ -2078,6 +2105,8 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg,
sprintf(portstring, "#%u", type);
}
}
else if (flags & F_RR)
dest = querystr(NULL, addr->rr.rrtype);
else
dest = arg;
}