mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 18:28:25 +00:00
Generalise CNAME handling.
Cope with cached and configured CNAMES for all record types we support, including local-config but not cached types such as TXT. Also, if we have a locally configured CNAME but no target for the requested type, don't forward the query.
This commit is contained in:
102
src/rfc1035.c
102
src/rfc1035.c
@@ -1363,6 +1363,35 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
|
|
||||||
ans = 0; /* have we answered this question */
|
ans = 0; /* have we answered this question */
|
||||||
|
|
||||||
|
while ((crecp = cache_find_by_name(NULL, name, now, F_CNAME)))
|
||||||
|
{
|
||||||
|
char *cname_target = cache_get_cname_target(crecp);
|
||||||
|
|
||||||
|
/* If the client asked for DNSSEC don't use cached data. */
|
||||||
|
if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
|
||||||
|
!do_bit ||
|
||||||
|
(option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
|
||||||
|
|
||||||
|
{
|
||||||
|
if (crecp->flags & F_CONFIG || qtype == T_CNAME)
|
||||||
|
ans = 1;
|
||||||
|
|
||||||
|
if (!(crecp->flags & F_DNSSECOK))
|
||||||
|
sec_data = 0;
|
||||||
|
|
||||||
|
if (!dryrun)
|
||||||
|
{
|
||||||
|
log_query(crecp->flags, name, NULL, record_source(crecp->uid));
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
crec_ttl(crecp, now), &nameoffset,
|
||||||
|
T_CNAME, C_IN, "d", cname_target))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(name, cname_target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (qtype == T_TXT || qtype == T_ANY)
|
if (qtype == T_TXT || qtype == T_ANY)
|
||||||
{
|
{
|
||||||
struct txt_record *t;
|
struct txt_record *t;
|
||||||
@@ -1614,7 +1643,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* interface name stuff */
|
/* interface name stuff */
|
||||||
intname_restart:
|
|
||||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||||
if (hostname_isequal(name, intr->name))
|
if (hostname_isequal(name, intr->name))
|
||||||
break;
|
break;
|
||||||
@@ -1672,8 +1700,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cname_restart:
|
if ((crecp = cache_find_by_name(NULL, name, now, flag | (dryrun ? F_NO_RR : 0))))
|
||||||
if ((crecp = cache_find_by_name(NULL, name, now, flag | F_CNAME | (dryrun ? F_NO_RR : 0))))
|
|
||||||
{
|
{
|
||||||
int localise = 0;
|
int localise = 0;
|
||||||
|
|
||||||
@@ -1689,7 +1716,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
localise = 1;
|
localise = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME)));
|
} while ((crecp = cache_find_by_name(crecp, name, now, flag)));
|
||||||
crecp = save;
|
crecp = save;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1707,27 +1734,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
if (!(crecp->flags & F_DNSSECOK))
|
if (!(crecp->flags & F_DNSSECOK))
|
||||||
sec_data = 0;
|
sec_data = 0;
|
||||||
|
|
||||||
if (crecp->flags & F_CNAME)
|
|
||||||
{
|
|
||||||
char *cname_target = cache_get_cname_target(crecp);
|
|
||||||
|
|
||||||
if (!dryrun)
|
|
||||||
{
|
|
||||||
log_query(crecp->flags, name, NULL, record_source(crecp->uid));
|
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
|
||||||
crec_ttl(crecp, now), &nameoffset,
|
|
||||||
T_CNAME, C_IN, "d", cname_target))
|
|
||||||
anscount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(name, cname_target);
|
|
||||||
/* check if target interface_name */
|
|
||||||
if (crecp->addr.cname.uid == SRC_INTERFACE)
|
|
||||||
goto intname_restart;
|
|
||||||
else
|
|
||||||
goto cname_restart;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (crecp->flags & F_NEG)
|
if (crecp->flags & F_NEG)
|
||||||
{
|
{
|
||||||
ans = 1;
|
ans = 1;
|
||||||
@@ -1761,7 +1767,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
anscount++;
|
anscount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME)));
|
} while ((crecp = cache_find_by_name(crecp, name, now, flag)));
|
||||||
}
|
}
|
||||||
else if (is_name_synthetic(flag, name, &addr))
|
else if (is_name_synthetic(flag, name, &addr))
|
||||||
{
|
{
|
||||||
@@ -1776,27 +1782,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qtype == T_CNAME || qtype == T_ANY)
|
|
||||||
{
|
|
||||||
if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME | (dryrun ? F_NO_RR : 0))) &&
|
|
||||||
(qtype == T_CNAME || (crecp->flags & F_CONFIG)) &&
|
|
||||||
((crecp->flags & F_CONFIG) || !do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))))
|
|
||||||
{
|
|
||||||
if (!(crecp->flags & F_DNSSECOK))
|
|
||||||
sec_data = 0;
|
|
||||||
|
|
||||||
ans = 1;
|
|
||||||
if (!dryrun)
|
|
||||||
{
|
|
||||||
log_query(crecp->flags, name, NULL, record_source(crecp->uid));
|
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
|
||||||
crec_ttl(crecp, now), &nameoffset,
|
|
||||||
T_CNAME, C_IN, "d", cache_get_cname_target(crecp)))
|
|
||||||
anscount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qtype == T_MX || qtype == T_ANY)
|
if (qtype == T_MX || qtype == T_ANY)
|
||||||
{
|
{
|
||||||
int found = 0;
|
int found = 0;
|
||||||
@@ -1880,8 +1865,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
cname_srv_restart:
|
if ((crecp = cache_find_by_name(NULL, name, now, F_SRV | (dryrun ? F_NO_RR : 0))) &&
|
||||||
if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME | F_SRV | (dryrun ? F_NO_RR : 0))) &&
|
|
||||||
(!do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))))
|
(!do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))))
|
||||||
{
|
{
|
||||||
if (!(crecp->flags & F_DNSSECOK))
|
if (!(crecp->flags & F_DNSSECOK))
|
||||||
@@ -1891,23 +1875,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
found = ans = 1;
|
found = ans = 1;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (crecp->flags & F_CNAME)
|
if (crecp->flags & F_NEG)
|
||||||
{
|
|
||||||
char *cname_target = cache_get_cname_target(crecp);
|
|
||||||
|
|
||||||
if (!dryrun)
|
|
||||||
{
|
|
||||||
log_query(crecp->flags, name, NULL, record_source(crecp->uid));
|
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
|
||||||
crec_ttl(crecp, now), &nameoffset,
|
|
||||||
T_CNAME, C_IN, "d", cname_target))
|
|
||||||
anscount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(name, cname_target);
|
|
||||||
goto cname_srv_restart;
|
|
||||||
}
|
|
||||||
else if (crecp->flags & F_NEG)
|
|
||||||
{
|
{
|
||||||
if (crecp->flags & F_NXDOMAIN)
|
if (crecp->flags & F_NXDOMAIN)
|
||||||
nxdomain = 1;
|
nxdomain = 1;
|
||||||
@@ -1935,7 +1903,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
return 0; /* bad packet */
|
return 0; /* bad packet */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while ((crecp = cache_find_by_name(crecp, name, now, F_SRV | F_CNAME)));
|
} while ((crecp = cache_find_by_name(crecp, name, now, F_SRV)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user