mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
CNAMEs can now point to interface names.
This commit is contained in:
@@ -140,6 +140,10 @@ version 2.67
|
||||
Add --quiet-dhcp, --quiet-dhcp6 and --quiet-ra. Thanks to
|
||||
Kevin Darbyshire-Bryant for the initial patch.
|
||||
|
||||
Allow A/AAAA records created by --interface-name to be the
|
||||
target of --cname. Thanks to Hadmut Danisch for the
|
||||
suggestion.
|
||||
|
||||
|
||||
version 2.66
|
||||
Add the ability to act as an authoritative DNS
|
||||
|
||||
@@ -497,7 +497,7 @@ Return an NAPTR DNS record, as specified in RFC3403.
|
||||
Return a CNAME record which indicates that <cname> is really
|
||||
<target>. There are significant limitations on the target; it must be a
|
||||
DNS name which is known to dnsmasq from /etc/hosts (or additional
|
||||
hosts files), from DHCP or from another
|
||||
hosts files), from DHCP, from --interface-name or from another
|
||||
.B --cname.
|
||||
If the target does not satisfy this
|
||||
criteria, the whole cname is ignored. The cname must be unique, but it
|
||||
|
||||
53
src/cache.c
53
src/cache.c
@@ -24,7 +24,7 @@ static struct crec *new_chain = NULL;
|
||||
static int cache_inserted = 0, cache_live_freed = 0, insert_error;
|
||||
static union bigname *big_free = NULL;
|
||||
static int bignames_left, hash_size;
|
||||
static int uid = 0;
|
||||
static int uid = 1;
|
||||
#ifdef HAVE_DNSSEC
|
||||
static struct keydata *keyblock_free = NULL;
|
||||
#endif
|
||||
@@ -76,7 +76,7 @@ void cache_init(void)
|
||||
{
|
||||
struct crec *crecp;
|
||||
int i;
|
||||
|
||||
|
||||
bignames_left = daemon->cachesize/10;
|
||||
|
||||
if (daemon->cachesize > 0)
|
||||
@@ -177,7 +177,10 @@ static void cache_free(struct crec *crecp)
|
||||
crecp->flags &= ~F_FORWARD;
|
||||
crecp->flags &= ~F_REVERSE;
|
||||
crecp->uid = uid++; /* invalidate CNAMES pointing to this. */
|
||||
|
||||
|
||||
if (uid == -1)
|
||||
uid++;
|
||||
|
||||
if (cache_tail)
|
||||
cache_tail->next = crecp;
|
||||
else
|
||||
@@ -235,6 +238,16 @@ char *cache_get_name(struct crec *crecp)
|
||||
return crecp->name.sname;
|
||||
}
|
||||
|
||||
char *cache_get_cname_target(struct crec *crecp)
|
||||
{
|
||||
if (crecp->addr.cname.uid != -1)
|
||||
return cache_get_name(crecp->addr.cname.target.cache);
|
||||
|
||||
return crecp->addr.cname.target.int_name->name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct crec *cache_enumerate(int init)
|
||||
{
|
||||
static int bucket;
|
||||
@@ -260,14 +273,14 @@ struct crec *cache_enumerate(int init)
|
||||
|
||||
static int is_outdated_cname_pointer(struct crec *crecp)
|
||||
{
|
||||
if (!(crecp->flags & F_CNAME))
|
||||
if (!(crecp->flags & F_CNAME) || crecp->addr.cname.uid == -1)
|
||||
return 0;
|
||||
|
||||
/* NB. record may be reused as DS or DNSKEY, where uid is
|
||||
overloaded for something completely different */
|
||||
if (crecp->addr.cname.cache &&
|
||||
(crecp->addr.cname.cache->flags & (F_IPV4 | F_IPV6 | F_CNAME)) &&
|
||||
crecp->addr.cname.uid == crecp->addr.cname.cache->uid)
|
||||
if (crecp->addr.cname.target.cache &&
|
||||
(crecp->addr.cname.target.cache->flags & (F_IPV4 | F_IPV6 | F_CNAME)) &&
|
||||
crecp->addr.cname.uid == crecp->addr.cname.target.cache->uid)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@@ -680,9 +693,9 @@ static void add_hosts_cname(struct crec *target)
|
||||
if (hostname_isequal(cache_get_name(target), a->target) &&
|
||||
(crec = whine_malloc(sizeof(struct crec))))
|
||||
{
|
||||
crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_HOSTS | F_CNAME;
|
||||
crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_CONFIG | F_CNAME;
|
||||
crec->name.namep = a->alias;
|
||||
crec->addr.cname.cache = target;
|
||||
crec->addr.cname.target.cache = target;
|
||||
crec->addr.cname.uid = target->uid;
|
||||
cache_hash(crec);
|
||||
add_hosts_cname(crec); /* handle chains */
|
||||
@@ -901,6 +914,8 @@ void cache_reload(void)
|
||||
struct hostsfile *ah;
|
||||
struct host_record *hr;
|
||||
struct name_list *nl;
|
||||
struct cname *a;
|
||||
struct interface_name *intr;
|
||||
|
||||
cache_inserted = cache_live_freed = 0;
|
||||
|
||||
@@ -927,6 +942,20 @@ void cache_reload(void)
|
||||
up = &cache->hash_next;
|
||||
}
|
||||
|
||||
/* Add CNAMEs to interface_names to the cache */
|
||||
for (a = daemon->cnames; a; a = a->next)
|
||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||
if (hostname_isequal(a->target, intr->name))
|
||||
{
|
||||
struct crec *aliasc = safe_malloc(sizeof(struct crec));
|
||||
aliasc->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
|
||||
aliasc->name.namep = a->alias;
|
||||
aliasc->addr.cname.target.int_name = intr;
|
||||
aliasc->addr.cname.uid = -1;
|
||||
cache_hash(aliasc);
|
||||
add_hosts_cname(aliasc); /* handle chains */
|
||||
}
|
||||
|
||||
/* borrow the packet buffer for a temporary by-address hash */
|
||||
memset(daemon->packet, 0, daemon->packet_buff_sz);
|
||||
revhashsz = daemon->packet_buff_sz / sizeof(struct crec *);
|
||||
@@ -1019,13 +1048,13 @@ static void add_dhcp_cname(struct crec *target, time_t ttd)
|
||||
|
||||
if (aliasc)
|
||||
{
|
||||
aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME;
|
||||
aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME | F_CONFIG;
|
||||
if (ttd == 0)
|
||||
aliasc->flags |= F_IMMORTAL;
|
||||
else
|
||||
aliasc->ttd = ttd;
|
||||
aliasc->name.namep = a->alias;
|
||||
aliasc->addr.cname.cache = target;
|
||||
aliasc->addr.cname.target.cache = target;
|
||||
aliasc->addr.cname.uid = target->uid;
|
||||
cache_hash(aliasc);
|
||||
add_dhcp_cname(aliasc, ttd);
|
||||
@@ -1173,7 +1202,7 @@ void dump_cache(time_t now)
|
||||
{
|
||||
a = "";
|
||||
if (!is_outdated_cname_pointer(cache))
|
||||
a = cache_get_name(cache->addr.cname.cache);
|
||||
a = cache_get_cname_target(cache);
|
||||
}
|
||||
#ifdef HAVE_DNSSEC
|
||||
else if (cache->flags & F_DNSKEY)
|
||||
|
||||
@@ -337,8 +337,11 @@ struct crec {
|
||||
union {
|
||||
struct all_addr addr;
|
||||
struct {
|
||||
struct crec *cache;
|
||||
int uid;
|
||||
union {
|
||||
struct crec *cache;
|
||||
struct interface_name *int_name;
|
||||
} target;
|
||||
int uid; /* -1 if union is interface-name */
|
||||
} cname;
|
||||
struct {
|
||||
struct keydata *keydata;
|
||||
@@ -941,6 +944,7 @@ struct in_addr a_record_from_hosts(char *name, time_t now);
|
||||
void cache_unhash_dhcp(void);
|
||||
void dump_cache(time_t now);
|
||||
char *cache_get_name(struct crec *crecp);
|
||||
char *cache_get_cname_target(struct crec *crecp);
|
||||
struct crec *cache_enumerate(int init);
|
||||
#ifdef HAVE_DNSSEC
|
||||
struct keydata *keydata_alloc(char *data, size_t len);
|
||||
|
||||
@@ -1042,10 +1042,10 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
||||
newc = cache_insert(name, NULL, now, attl, F_CNAME | F_FORWARD);
|
||||
if (newc)
|
||||
{
|
||||
newc->addr.cname.cache = NULL;
|
||||
newc->addr.cname.target.cache = NULL;
|
||||
if (cpp)
|
||||
{
|
||||
cpp->addr.cname.cache = newc;
|
||||
cpp->addr.cname.target.cache = newc;
|
||||
cpp->addr.cname.uid = newc->uid;
|
||||
}
|
||||
}
|
||||
@@ -1085,7 +1085,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
||||
newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD);
|
||||
if (newc && cpp)
|
||||
{
|
||||
cpp->addr.cname.cache = newc;
|
||||
cpp->addr.cname.target.cache = newc;
|
||||
cpp->addr.cname.uid = newc->uid;
|
||||
}
|
||||
cpp = NULL;
|
||||
@@ -1112,7 +1112,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
||||
newc = cache_insert(name, NULL, now, ttl ? ttl : cttl, F_FORWARD | F_NEG | flags);
|
||||
if (newc && cpp)
|
||||
{
|
||||
cpp->addr.cname.cache = newc;
|
||||
cpp->addr.cname.target.cache = newc;
|
||||
cpp->addr.cname.uid = newc->uid;
|
||||
}
|
||||
}
|
||||
@@ -1720,7 +1720,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
}
|
||||
|
||||
/* interface name stuff */
|
||||
|
||||
intname_restart:
|
||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||
if (hostname_isequal(name, intr->name))
|
||||
break;
|
||||
@@ -1784,17 +1784,23 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
|
||||
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", cache_get_name(crecp->addr.cname.cache)))
|
||||
T_CNAME, C_IN, "d", cname_target))
|
||||
anscount++;
|
||||
}
|
||||
|
||||
strcpy(name, cache_get_name(crecp->addr.cname.cache));
|
||||
goto cname_restart;
|
||||
strcpy(name, cname_target);
|
||||
/* check if target interface_name */
|
||||
if (crecp->addr.cname.uid == -1)
|
||||
goto intname_restart;
|
||||
else
|
||||
goto cname_restart;
|
||||
}
|
||||
|
||||
if (crecp->flags & F_NEG)
|
||||
@@ -1856,7 +1862,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
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_name(crecp->addr.cname.cache)))
|
||||
T_CNAME, C_IN, "d", cache_get_cname_target(crecp)))
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user