mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
Fix long-term bug in TCP caching code which would lose NXDOMAIN.
A NXDOMAIN answer recieved over TCP by a child process would be correctly sent back to the master process which would then fail to insert it into the cache.
This commit is contained in:
107
src/cache.c
107
src/cache.c
@@ -800,28 +800,30 @@ void cache_end_insert(void)
|
|||||||
read_write(daemon->pipe_to_parent, (unsigned char *)&flags, sizeof(flags), 0);
|
read_write(daemon->pipe_to_parent, (unsigned char *)&flags, sizeof(flags), 0);
|
||||||
|
|
||||||
if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS | F_RR))
|
if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS | F_RR))
|
||||||
read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr, sizeof(new_chain->addr), 0);
|
{
|
||||||
|
read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr, sizeof(new_chain->addr), 0);
|
||||||
|
|
||||||
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) && (flags & F_KEYTAG))
|
if (!(flags & F_NEG) && (flags & F_KEYTAG))
|
||||||
blockdata_write(new_chain->addr.rrblock.rrdata, new_chain->addr.rrblock.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)
|
||||||
{
|
{
|
||||||
read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), 0);
|
read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), 0);
|
||||||
blockdata_write(new_chain->addr.key.keydata, new_chain->addr.key.keylen, daemon->pipe_to_parent);
|
blockdata_write(new_chain->addr.key.keydata, new_chain->addr.key.keylen, daemon->pipe_to_parent);
|
||||||
}
|
}
|
||||||
else if (flags & F_DS)
|
else if (flags & F_DS)
|
||||||
{
|
{
|
||||||
read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), 0);
|
read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), 0);
|
||||||
/* A negative DS entry is possible and has no data, obviously. */
|
/* A negative DS entry is possible and has no data, obviously. */
|
||||||
if (!(flags & F_NEG))
|
if (!(flags & F_NEG))
|
||||||
blockdata_write(new_chain->addr.ds.keydata, new_chain->addr.ds.keylen, daemon->pipe_to_parent);
|
blockdata_write(new_chain->addr.ds.keydata, new_chain->addr.ds.keylen, daemon->pipe_to_parent);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -872,34 +874,7 @@ int cache_recv_insert(time_t now, int fd)
|
|||||||
|
|
||||||
ttl = difftime(ttd, now);
|
ttl = difftime(ttd, now);
|
||||||
|
|
||||||
if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS | F_RR))
|
if (flags & F_CNAME)
|
||||||
{
|
|
||||||
unsigned short class = C_IN;
|
|
||||||
|
|
||||||
if (!read_write(fd, (unsigned char *)&addr, sizeof(addr), 1))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if ((flags & F_RR) && !(flags & F_NEG) && (flags & F_KEYTAG)
|
|
||||||
&& !(addr.rrblock.rrdata = blockdata_read(fd, addr.rrblock.datalen)))
|
|
||||||
return 0;
|
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
if (flags & F_DNSKEY)
|
|
||||||
{
|
|
||||||
if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1) ||
|
|
||||||
!(addr.key.keydata = blockdata_read(fd, addr.key.keylen)))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (flags & F_DS)
|
|
||||||
{
|
|
||||||
if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1) ||
|
|
||||||
(!(flags & F_NEG) && !(addr.key.keydata = blockdata_read(fd, addr.key.keylen))))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
crecp = really_insert(daemon->namebuff, &addr, class, now, ttl, flags);
|
|
||||||
}
|
|
||||||
else if (flags & F_CNAME)
|
|
||||||
{
|
{
|
||||||
struct crec *newc = really_insert(daemon->namebuff, NULL, C_IN, now, ttl, flags);
|
struct crec *newc = really_insert(daemon->namebuff, NULL, C_IN, now, ttl, flags);
|
||||||
/* This relies on the fact that the target of a CNAME immediately precedes
|
/* This relies on the fact that the target of a CNAME immediately precedes
|
||||||
@@ -907,11 +882,11 @@ int cache_recv_insert(time_t now, int fd)
|
|||||||
the order reversal on the new_chain. */
|
the order reversal on the new_chain. */
|
||||||
if (newc)
|
if (newc)
|
||||||
{
|
{
|
||||||
newc->addr.cname.is_name_ptr = 0;
|
newc->addr.cname.is_name_ptr = 0;
|
||||||
|
|
||||||
if (!crecp)
|
if (!crecp)
|
||||||
newc->addr.cname.target.cache = NULL;
|
newc->addr.cname.target.cache = NULL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
next_uid(crecp);
|
next_uid(crecp);
|
||||||
newc->addr.cname.target.cache = crecp;
|
newc->addr.cname.target.cache = crecp;
|
||||||
@@ -919,6 +894,36 @@ int cache_recv_insert(time_t now, int fd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned short class = C_IN;
|
||||||
|
|
||||||
|
if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS | F_RR))
|
||||||
|
{
|
||||||
|
if (!read_write(fd, (unsigned char *)&addr, sizeof(addr), 1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((flags & F_RR) && !(flags & F_NEG) && (flags & F_KEYTAG)
|
||||||
|
&& !(addr.rrblock.rrdata = blockdata_read(fd, addr.rrblock.datalen)))
|
||||||
|
return 0;
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
if (flags & F_DNSKEY)
|
||||||
|
{
|
||||||
|
if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1) ||
|
||||||
|
!(addr.key.keydata = blockdata_read(fd, addr.key.keylen)))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (flags & F_DS)
|
||||||
|
{
|
||||||
|
if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1) ||
|
||||||
|
(!(flags & F_NEG) && !(addr.key.keydata = blockdata_read(fd, addr.key.keylen))))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
crecp = really_insert(daemon->namebuff, &addr, class, now, ttl, flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user