mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 18:28:25 +00:00
Use a simpler arrangement for the all_addr union to avoid
the compiler padding it with an extra 8 bytes. Use the F_KEYTAG flag in a a cache record to discriminate between an arbitrary RR stored entirely in the addr union and one which has a point to block storage.
This commit is contained in:
44
src/cache.c
44
src/cache.c
@@ -275,8 +275,8 @@ static void cache_blockdata_free(struct crec *crecp)
|
|||||||
{
|
{
|
||||||
if (!(crecp->flags & F_NEG))
|
if (!(crecp->flags & F_NEG))
|
||||||
{
|
{
|
||||||
if (crecp->flags & F_RR && crecp->addr.rr.len == -1)
|
if ((crecp->flags & F_RR) && (crecp->flags & F_KEYTAG))
|
||||||
blockdata_free(crecp->addr.rr.u.block.rrdata);
|
blockdata_free(crecp->addr.rrblock.rrdata);
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
else if (crecp->flags & F_DNSKEY)
|
else if (crecp->flags & F_DNSKEY)
|
||||||
blockdata_free(crecp->addr.key.keydata);
|
blockdata_free(crecp->addr.key.keydata);
|
||||||
@@ -469,10 +469,20 @@ static struct crec *cache_scan_free(char *name, union all_addr *addr, unsigned s
|
|||||||
{
|
{
|
||||||
if ((crecp->flags & F_FORWARD) && hostname_isequal(cache_get_name(crecp), name))
|
if ((crecp->flags & F_FORWARD) && hostname_isequal(cache_get_name(crecp), name))
|
||||||
{
|
{
|
||||||
|
int rrmatch = 0;
|
||||||
|
if (crecp->flags & flags & F_RR)
|
||||||
|
{
|
||||||
|
unsigned short rrc = (crecp->flags & F_KEYTAG) ? crecp->addr.rrblock.rrtype : crecp->addr.rrdata.rrtype;
|
||||||
|
unsigned short rra = (flags & F_KEYTAG) ? addr->rrblock.rrtype : addr->rrdata.rrtype;
|
||||||
|
|
||||||
|
if (rrc == rra)
|
||||||
|
rrmatch = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Don't delete DNSSEC in favour of a CNAME, they can co-exist */
|
/* Don't delete DNSSEC in favour of a CNAME, they can co-exist */
|
||||||
if ((flags & crecp->flags & (F_IPV4 | F_IPV6 | F_RR | F_NXDOMAIN)) ||
|
if ((flags & crecp->flags & (F_IPV4 | F_IPV6 | 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))
|
rrmatch)
|
||||||
{
|
{
|
||||||
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
|
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
|
||||||
return crecp;
|
return crecp;
|
||||||
@@ -795,8 +805,8 @@ void cache_end_insert(void)
|
|||||||
if (flags & F_RR)
|
if (flags & F_RR)
|
||||||
{
|
{
|
||||||
/* A negative RR entry is possible and has no data, obviously. */
|
/* A negative RR entry is possible and has no data, obviously. */
|
||||||
if (!(flags & F_NEG) && new_chain->addr.rr.len == -1)
|
if (!(flags & F_NEG) && (flags & F_KEYTAG))
|
||||||
blockdata_write(new_chain->addr.rr.u.block.rrdata, new_chain->addr.rr.u.block.datalen, daemon->pipe_to_parent);
|
blockdata_write(new_chain->addr.rrblock.rrdata, new_chain->addr.rrblock.datalen, daemon->pipe_to_parent);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (flags & F_DNSKEY)
|
if (flags & F_DNSKEY)
|
||||||
@@ -869,8 +879,8 @@ int cache_recv_insert(time_t now, int fd)
|
|||||||
if (!read_write(fd, (unsigned char *)&addr, sizeof(addr), 1))
|
if (!read_write(fd, (unsigned char *)&addr, sizeof(addr), 1))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if ((flags & F_RR) && !(flags & F_NEG) &&
|
if ((flags & F_RR) && !(flags & F_NEG) && (flags & F_KEYTAG)
|
||||||
addr.rr.len == -1 && !(addr.rr.u.block.rrdata = blockdata_read(fd, addr.rr.u.block.datalen)))
|
&& !(addr.rrblock.rrdata = blockdata_read(fd, addr.rrblock.datalen)))
|
||||||
return 0;
|
return 0;
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (flags & F_DNSKEY)
|
if (flags & F_DNSKEY)
|
||||||
@@ -1796,7 +1806,12 @@ static void dump_cache_entry(struct crec *cache, time_t now)
|
|||||||
if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
|
if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
|
||||||
a = sanitise(cache_get_cname_target(cache));
|
a = sanitise(cache_get_cname_target(cache));
|
||||||
else if (cache->flags & F_RR)
|
else if (cache->flags & F_RR)
|
||||||
sprintf(a, "%s", querystr(NULL, cache->addr.rr.rrtype));
|
{
|
||||||
|
if (cache->flags & F_KEYTAG)
|
||||||
|
sprintf(a, "%s", querystr(NULL, cache->addr.rrblock.rrtype));
|
||||||
|
else
|
||||||
|
sprintf(a, "%s", querystr(NULL, cache->addr.rrdata.rrtype));
|
||||||
|
}
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
else if (cache->flags & F_DS)
|
else if (cache->flags & F_DS)
|
||||||
{
|
{
|
||||||
@@ -2052,7 +2067,14 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg,
|
|||||||
{
|
{
|
||||||
dest = daemon->addrbuff;
|
dest = daemon->addrbuff;
|
||||||
|
|
||||||
if (flags & F_KEYTAG)
|
if (flags & F_RR)
|
||||||
|
{
|
||||||
|
if (flags & F_KEYTAG)
|
||||||
|
dest = querystr(NULL, addr->rrblock.rrtype);
|
||||||
|
else
|
||||||
|
dest = querystr(NULL, addr->rrdata.rrtype);
|
||||||
|
}
|
||||||
|
else if (flags & F_KEYTAG)
|
||||||
sprintf(daemon->addrbuff, arg, addr->log.keytag, addr->log.algo, addr->log.digest);
|
sprintf(daemon->addrbuff, arg, addr->log.keytag, addr->log.algo, addr->log.digest);
|
||||||
else if (flags & F_RCODE)
|
else if (flags & F_RCODE)
|
||||||
{
|
{
|
||||||
@@ -2083,8 +2105,6 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg,
|
|||||||
sprintf(portstring, "#%u", type);
|
sprintf(portstring, "#%u", type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (flags & F_RR)
|
|
||||||
dest = querystr(NULL, addr->rr.rrtype);
|
|
||||||
else
|
else
|
||||||
dest = arg;
|
dest = arg;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -329,21 +329,23 @@ union all_addr {
|
|||||||
unsigned short keytag, algo, digest, rcode;
|
unsigned short keytag, algo, digest, rcode;
|
||||||
int ede;
|
int ede;
|
||||||
} log;
|
} log;
|
||||||
/* for arbitrary RR record. */
|
/* for arbitrary RR record stored in block */
|
||||||
struct {
|
struct {
|
||||||
#define RR_IMDATALEN 13 /* 16 - sizeof(short) - sizeof (char) */
|
|
||||||
unsigned short rrtype;
|
unsigned short rrtype;
|
||||||
char len; /* -1 for blockdata */
|
unsigned short datalen;
|
||||||
union {
|
struct blockdata *rrdata;
|
||||||
char data[RR_IMDATALEN];
|
} rrblock;
|
||||||
struct {
|
/* for arbitrary RR record small enough to go in addr.
|
||||||
unsigned short datalen;
|
NOTE: rrblock and rrdata are discriminated by the F_KEYTAG bit
|
||||||
struct blockdata *rrdata;
|
in the cache flags. */
|
||||||
} block;
|
struct datablock {
|
||||||
} u;
|
unsigned short rrtype;
|
||||||
} rr;
|
unsigned char datalen;
|
||||||
|
char data[];
|
||||||
|
} rrdata;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define RR_IMDATALEN (sizeof(union all_addr) - offsetof(struct datablock, data))
|
||||||
|
|
||||||
struct bogus_addr {
|
struct bogus_addr {
|
||||||
int is6, prefix;
|
int is6, prefix;
|
||||||
|
|||||||
@@ -806,20 +806,20 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
if (!CHECK_LEN(header, p1, qlen, ardlen))
|
if (!CHECK_LEN(header, p1, qlen, ardlen))
|
||||||
return 2; /* bad packet */
|
return 2; /* bad packet */
|
||||||
|
|
||||||
addr.rr.rrtype = aqtype;
|
|
||||||
|
|
||||||
/* If the data has no names and is small enough, store it in
|
/* If the data has no names and is small enough, store it in
|
||||||
the crec address field rather than allocate a block. */
|
the crec address field rather than allocate a block. */
|
||||||
if (*rrdesc == -1 && ardlen <= RR_IMDATALEN)
|
if (*rrdesc == -1 && ardlen <= (int)RR_IMDATALEN)
|
||||||
{
|
{
|
||||||
addr.rr.len = (char)ardlen;
|
addr.rrdata.rrtype = aqtype;
|
||||||
if (ardlen != 0)
|
addr.rrdata.datalen = (char)ardlen;
|
||||||
memcpy(addr.rr.u.data, p1, ardlen);
|
if (ardlen != 0)
|
||||||
|
memcpy(addr.rrdata.data, p1, ardlen);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
addr.rr.len = -1;
|
addr.rrblock.rrtype = aqtype;
|
||||||
addr.rr.u.block.datalen = 0;
|
addr.rrblock.datalen = 0;
|
||||||
|
flags |= F_KEYTAG; /* discriminates between rrdata and rrblock */
|
||||||
|
|
||||||
/* The RR data may include names, and those names may include
|
/* The RR data may include names, and those names may include
|
||||||
compression, which will be rendered meaningless when
|
compression, which will be rendered meaningless when
|
||||||
@@ -827,7 +827,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
Here we go through a description of the packet type to
|
Here we go through a description of the packet type to
|
||||||
find the names, and extract them to a c-string and then
|
find the names, and extract them to a c-string and then
|
||||||
re-encode them to standalone DNS format without compression. */
|
re-encode them to standalone DNS format without compression. */
|
||||||
if (!(addr.rr.u.block.rrdata = blockdata_alloc(NULL, 0)))
|
if (!(addr.rrblock.rrdata = blockdata_alloc(NULL, 0)))
|
||||||
return 0;
|
return 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -836,9 +836,9 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
if (desc == -1)
|
if (desc == -1)
|
||||||
{
|
{
|
||||||
/* Copy the rest of the RR and end. */
|
/* Copy the rest of the RR and end. */
|
||||||
if (!blockdata_expand(addr.rr.u.block.rrdata, addr.rr.u.block.datalen, (char *)p1, endrr - p1))
|
if (!blockdata_expand(addr.rrblock.rrdata, addr.rrblock.datalen, (char *)p1, endrr - p1))
|
||||||
return 0;
|
return 0;
|
||||||
addr.rr.u.block.datalen += endrr - p1;
|
addr.rrblock.datalen += endrr - p1;
|
||||||
}
|
}
|
||||||
else if (desc == 0)
|
else if (desc == 0)
|
||||||
{
|
{
|
||||||
@@ -849,18 +849,18 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
len = to_wire(name);
|
len = to_wire(name);
|
||||||
if (!blockdata_expand(addr.rr.u.block.rrdata, addr.rr.u.block.datalen, name, len))
|
if (!blockdata_expand(addr.rrblock.rrdata, addr.rrblock.datalen, name, len))
|
||||||
return 0;
|
return 0;
|
||||||
addr.rr.u.block.datalen += len;
|
addr.rrblock.datalen += len;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* desc is length of a block of data to be used as-is */
|
/* desc is length of a block of data to be used as-is */
|
||||||
if (desc > endrr - p1)
|
if (desc > endrr - p1)
|
||||||
desc = endrr - p1;
|
desc = endrr - p1;
|
||||||
if (!blockdata_expand(addr.rr.u.block.rrdata, addr.rr.u.block.datalen, (char *)p1, desc))
|
if (!blockdata_expand(addr.rrblock.rrdata, addr.rrblock.datalen, (char *)p1, desc))
|
||||||
return 0;
|
return 0;
|
||||||
addr.rr.u.block.datalen += desc;
|
addr.rrblock.datalen += desc;
|
||||||
p1 += desc;
|
p1 += desc;
|
||||||
}
|
}
|
||||||
} while (desc != -1);
|
} while (desc != -1);
|
||||||
@@ -968,7 +968,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
ttl = cttl;
|
ttl = cttl;
|
||||||
|
|
||||||
if (flags & F_RR)
|
if (flags & F_RR)
|
||||||
addr.rr.rrtype = qtype;
|
addr.rrdata.rrtype = qtype;
|
||||||
|
|
||||||
newc = cache_insert(name, &addr, C_IN, now, ttl, F_FORWARD | F_NEG | flags | (secure ? F_DNSSECOK : 0));
|
newc = cache_insert(name, &addr, C_IN, now, ttl, F_FORWARD | F_NEG | flags | (secure ? F_DNSSECOK : 0));
|
||||||
if (newc && cpp)
|
if (newc && cpp)
|
||||||
@@ -2103,8 +2103,14 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
int flags = crecp->flags;
|
int flags = crecp->flags;
|
||||||
|
unsigned short rrtype;
|
||||||
|
|
||||||
|
if (flags & F_KEYTAG)
|
||||||
|
rrtype = crecp->addr.rrblock.rrtype;
|
||||||
|
else
|
||||||
|
rrtype = crecp->addr.rrdata.rrtype;
|
||||||
|
|
||||||
if ((flags & F_NXDOMAIN) || crecp->addr.rr.rrtype == qtype)
|
if ((flags & F_NXDOMAIN) || rrtype == qtype)
|
||||||
{
|
{
|
||||||
if (crec_isstale(crecp, now))
|
if (crec_isstale(crecp, now))
|
||||||
{
|
{
|
||||||
@@ -2127,23 +2133,28 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
|
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
char *rrdata = crecp->addr.rr.u.data;
|
char *rrdata = NULL;
|
||||||
unsigned short rrlen = crecp->addr.rr.len;
|
unsigned short rrlen = 0;
|
||||||
|
|
||||||
if (!(flags & F_NEG))
|
if (!(flags & F_NEG))
|
||||||
{
|
{
|
||||||
if (crecp->addr.rr.len == -1)
|
if (flags & F_KEYTAG)
|
||||||
{
|
{
|
||||||
rrlen = crecp->addr.rr.u.block.datalen;
|
rrlen = crecp->addr.rrblock.datalen;
|
||||||
rrdata = blockdata_retrieve(crecp->addr.rr.u.block.rrdata, crecp->addr.rr.u.block.datalen, NULL);
|
rrdata = blockdata_retrieve(crecp->addr.rrblock.rrdata, crecp->addr.rrblock.datalen, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rrlen = crecp->addr.rrdata.datalen;
|
||||||
|
rrdata = crecp->addr.rrdata.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
|
||||||
crec_ttl(crecp, now), NULL, qtype, C_IN, "t",
|
|
||||||
rrlen, rrdata))
|
|
||||||
anscount++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(flags & F_NEG) && add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
crec_ttl(crecp, now), NULL, qtype, C_IN, "t",
|
||||||
|
rrlen, rrdata))
|
||||||
|
anscount++;
|
||||||
|
|
||||||
/* log after cache insertion as log_txt mangles rrdata */
|
/* log after cache insertion as log_txt mangles rrdata */
|
||||||
if (qtype == T_TXT && !(crecp->flags & F_NEG))
|
if (qtype == T_TXT && !(crecp->flags & F_NEG))
|
||||||
log_txt(name, (unsigned char *)rrdata, rrlen, crecp->flags & F_DNSSECOK);
|
log_txt(name, (unsigned char *)rrdata, rrlen, crecp->flags & F_DNSSECOK);
|
||||||
|
|||||||
Reference in New Issue
Block a user