mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
Allow wildcard CNAME records in authoritative zones.
This commit is contained in:
@@ -35,6 +35,10 @@ version 2.77
|
|||||||
is destroyed and recreated in the kernel. Thanks to
|
is destroyed and recreated in the kernel. Thanks to
|
||||||
Beniamino Galvani for the patch.
|
Beniamino Galvani for the patch.
|
||||||
|
|
||||||
|
Allow wildcard CNAME records in authoritative zones.
|
||||||
|
For example --cname=*.example.com,default.example.com
|
||||||
|
Thanks to Pro Backup for sponsoring this development.
|
||||||
|
|
||||||
|
|
||||||
version 2.76
|
version 2.76
|
||||||
Include 0.0.0.0/8 in DNS rebind checks. This range
|
Include 0.0.0.0/8 in DNS rebind checks. This range
|
||||||
|
|||||||
@@ -2206,7 +2206,12 @@ following data is used to populate the authoritative zone.
|
|||||||
.B --cname
|
.B --cname
|
||||||
as long as the record name is in the authoritative domain. If the
|
as long as the record name is in the authoritative domain. If the
|
||||||
target of the CNAME is unqualified, then it is qualified with the
|
target of the CNAME is unqualified, then it is qualified with the
|
||||||
authoritative zone name.
|
authoritative zone name. CNAME used in this way (only) may be wildcards, as in
|
||||||
|
|
||||||
|
.nf
|
||||||
|
.B cname=*.example.com,default.example.com
|
||||||
|
.fi
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
IPv4 and IPv6 addresses from /etc/hosts (and
|
IPv4 and IPv6 addresses from /etc/hosts (and
|
||||||
.B --addn-hosts
|
.B --addn-hosts
|
||||||
|
|||||||
78
src/auth.c
78
src/auth.c
@@ -116,7 +116,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
struct interface_name *intr;
|
struct interface_name *intr;
|
||||||
struct naptr *na;
|
struct naptr *na;
|
||||||
struct all_addr addr;
|
struct all_addr addr;
|
||||||
struct cname *a;
|
struct cname *a, *candidate;
|
||||||
|
unsigned int wclen;
|
||||||
|
|
||||||
/* Clear buffer beyond request to avoid risk of
|
/* Clear buffer beyond request to avoid risk of
|
||||||
information disclosure. */
|
information disclosure. */
|
||||||
@@ -137,6 +138,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
{
|
{
|
||||||
unsigned short flag = 0;
|
unsigned short flag = 0;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
|
int cname_wildcard = 0;
|
||||||
|
|
||||||
/* save pointer to name for copying into answers */
|
/* save pointer to name for copying into answers */
|
||||||
nameoffset = p - (unsigned char *)header;
|
nameoffset = p - (unsigned char *)header;
|
||||||
@@ -411,25 +413,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (a = daemon->cnames; a; a = a->next)
|
|
||||||
if (hostname_isequal(name, a->alias) )
|
|
||||||
{
|
|
||||||
log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
|
|
||||||
strcpy(name, a->target);
|
|
||||||
if (!strchr(name, '.'))
|
|
||||||
{
|
|
||||||
strcat(name, ".");
|
|
||||||
strcat(name, zone->domain);
|
|
||||||
}
|
|
||||||
found = 1;
|
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
|
||||||
daemon->auth_ttl, &nameoffset,
|
|
||||||
T_CNAME, C_IN, "d", name))
|
|
||||||
anscount++;
|
|
||||||
|
|
||||||
goto cname_restart;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cut)
|
if (!cut)
|
||||||
{
|
{
|
||||||
nxdomain = 0;
|
nxdomain = 0;
|
||||||
@@ -536,7 +519,60 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
|
{
|
||||||
|
/* Check for possible wildcard match against *.domain
|
||||||
|
return length of match, to get longest.
|
||||||
|
Note that if return length of wildcard section, so
|
||||||
|
we match b.simon to _both_ *.simon and b.simon
|
||||||
|
but return a longer (better) match to b.simon.
|
||||||
|
*/
|
||||||
|
for (wclen = 0, candidate = NULL, a = daemon->cnames; a; a = a->next)
|
||||||
|
if (a->alias[0] == '*')
|
||||||
|
{
|
||||||
|
char *test = name;
|
||||||
|
|
||||||
|
while ((test = strchr(test+1, '.')))
|
||||||
|
{
|
||||||
|
if (hostname_isequal(test, &(a->alias[1])))
|
||||||
|
{
|
||||||
|
if (strlen(test) > wclen && !cname_wildcard)
|
||||||
|
{
|
||||||
|
wclen = strlen(test);
|
||||||
|
candidate = a;
|
||||||
|
cname_wildcard = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (hostname_isequal(a->alias, name) && strlen(a->alias) > wclen)
|
||||||
|
{
|
||||||
|
/* Simple case, no wildcard */
|
||||||
|
wclen = strlen(a->alias);
|
||||||
|
candidate = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (candidate)
|
||||||
|
{
|
||||||
|
log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
|
||||||
|
strcpy(name, candidate->target);
|
||||||
|
if (!strchr(name, '.'))
|
||||||
|
{
|
||||||
|
strcat(name, ".");
|
||||||
|
strcat(name, zone->domain);
|
||||||
|
}
|
||||||
|
found = 1;
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->auth_ttl, &nameoffset,
|
||||||
|
T_CNAME, C_IN, "d", name))
|
||||||
|
anscount++;
|
||||||
|
|
||||||
|
goto cname_restart;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -774,7 +774,8 @@ static void add_hosts_cname(struct crec *target)
|
|||||||
struct cname *a;
|
struct cname *a;
|
||||||
|
|
||||||
for (a = daemon->cnames; a; a = a->next)
|
for (a = daemon->cnames; a; a = a->next)
|
||||||
if (hostname_isequal(cache_get_name(target), a->target) &&
|
if (a->alias[1] != '*' &&
|
||||||
|
hostname_isequal(cache_get_name(target), a->target) &&
|
||||||
(crec = whine_malloc(sizeof(struct crec))))
|
(crec = whine_malloc(sizeof(struct crec))))
|
||||||
{
|
{
|
||||||
crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_CONFIG | F_CNAME;
|
crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_CONFIG | F_CNAME;
|
||||||
@@ -1056,7 +1057,8 @@ void cache_reload(void)
|
|||||||
/* Add CNAMEs to interface_names to the cache */
|
/* Add CNAMEs to interface_names to the cache */
|
||||||
for (a = daemon->cnames; a; a = a->next)
|
for (a = daemon->cnames; a; a = a->next)
|
||||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||||
if (hostname_isequal(a->target, intr->name) &&
|
if (a->alias[1] != '*' &&
|
||||||
|
hostname_isequal(a->target, intr->name) &&
|
||||||
((cache = whine_malloc(sizeof(struct crec)))))
|
((cache = whine_malloc(sizeof(struct crec)))))
|
||||||
{
|
{
|
||||||
cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
|
cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
|
||||||
@@ -1177,7 +1179,8 @@ static void add_dhcp_cname(struct crec *target, time_t ttd)
|
|||||||
struct cname *a;
|
struct cname *a;
|
||||||
|
|
||||||
for (a = daemon->cnames; a; a = a->next)
|
for (a = daemon->cnames; a; a = a->next)
|
||||||
if (hostname_isequal(cache_get_name(target), a->target))
|
if (a->alias[1] != '*' &&
|
||||||
|
hostname_isequal(cache_get_name(target), a->target))
|
||||||
{
|
{
|
||||||
if ((aliasc = dhcp_spare))
|
if ((aliasc = dhcp_spare))
|
||||||
dhcp_spare = dhcp_spare->next;
|
dhcp_spare = dhcp_spare->next;
|
||||||
|
|||||||
Reference in New Issue
Block a user