summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Kelley <simon@thekelleys.org.uk>2012-07-16 16:23:46 +0100
committerSimon Kelley <simon@thekelleys.org.uk>2012-07-16 16:23:46 +0100
commit611ebc5f1e1d082a9763334d9de2c27cf436fb4e (patch)
treee5fb650f101d601c28febd1e0a51be81c6b50553
parentbe0f45cdbc6f1cf6bb515412aa5102a120ea8a60 (diff)
downloaddnsmasq-611ebc5f1e1d082a9763334d9de2c27cf436fb4e.tar.gz
Fix broken caching of CNAME chains.v2.63test3
-rw-r--r--CHANGELOG5
-rw-r--r--man/dnsmasq.84
-rw-r--r--src/cache.c88
-rw-r--r--src/option.c12
4 files changed, 64 insertions, 45 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 466f89f..290ab84 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -24,6 +24,11 @@ version 2.63
Fixed bug logging filenames when duplicate dhcp-host
addresses are found. Thanks to John Hanks for the patch.
+ Fix regression in 2.61 which broke caching of CNAME
+ chains. Thanks to Atul Gupta for the bug report.
+
+ Allow the target of a --cname flag to be anothe --cname.
+
version 2.62
Update German translation. Thanks to Conrad Kostecki.
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index 9357cf5..0b51f14 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -461,7 +461,9 @@ 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) or from DHCP. If the target does not satisfy this
+hosts files), from DHCP 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
is permissable to have more than one cname pointing to the same target.
.TP
diff --git a/src/cache.c b/src/cache.c
index 5826a32..d0d806c 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -243,7 +243,7 @@ static int is_outdated_cname_pointer(struct crec *crecp)
/* 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)) &&
+ (crecp->addr.cname.cache->flags & (F_IPV4 | F_IPV6 | F_CNAME)) &&
crecp->addr.cname.uid == crecp->addr.cname.cache->uid)
return 0;
@@ -645,13 +645,29 @@ struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
return NULL;
}
-
+static void add_hosts_cname(struct crec *target)
+{
+ struct crec *crec;
+ struct cname *a;
+
+ for (a = daemon->cnames; a; a = a->next)
+ 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->name.namep = a->alias;
+ crec->addr.cname.cache = target;
+ crec->addr.cname.uid = target->uid;
+ cache_hash(crec);
+ add_hosts_cname(crec); /* handle chains */
+ }
+}
+
static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen,
int index, struct crec **rhash, int hashsz)
{
struct crec *lookup = cache_find_by_name(NULL, cache_get_name(cache), 0, cache->flags & (F_IPV4 | F_IPV6));
int i, nameexists = 0;
- struct cname *a;
unsigned int j;
/* Remove duplicates in hosts files. */
@@ -702,16 +718,7 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl
/* don't need to do alias stuff for second and subsequent addresses. */
if (!nameexists)
- for (a = daemon->cnames; a; a = a->next)
- if (hostname_isequal(cache_get_name(cache), a->target) &&
- (lookup = whine_malloc(sizeof(struct crec))))
- {
- lookup->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_HOSTS | F_CNAME;
- lookup->name.namep = a->alias;
- lookup->addr.cname.cache = cache;
- lookup->addr.cname.uid = index;
- cache_hash(lookup);
- }
+ add_hosts_cname(cache);
}
static int eatspace(FILE *f)
@@ -1003,13 +1010,41 @@ void cache_unhash_dhcp(void)
up = &cache->hash_next;
}
+static void add_dhcp_cname(struct crec *target, time_t ttd)
+{
+ struct crec *aliasc;
+ struct cname *a;
+
+ for (a = daemon->cnames; a; a = a->next)
+ if (hostname_isequal(cache_get_name(target), a->target))
+ {
+ if ((aliasc = dhcp_spare))
+ dhcp_spare = dhcp_spare->next;
+ else /* need new one */
+ aliasc = whine_malloc(sizeof(struct crec));
+
+ if (aliasc)
+ {
+ aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME;
+ if (ttd == 0)
+ aliasc->flags |= F_IMMORTAL;
+ else
+ aliasc->ttd = ttd;
+ aliasc->name.namep = a->alias;
+ aliasc->addr.cname.cache = target;
+ aliasc->addr.cname.uid = target->uid;
+ cache_hash(aliasc);
+ add_dhcp_cname(aliasc, ttd);
+ }
+ }
+}
+
void cache_add_dhcp_entry(char *host_name, int prot,
struct all_addr *host_address, time_t ttd)
{
- struct crec *crec = NULL, *aliasc;
+ struct crec *crec = NULL;
unsigned short flags = F_IPV4;
int in_hosts = 0;
- struct cname *a;
size_t addrlen = sizeof(struct in_addr);
#ifdef HAVE_IPV6
@@ -1030,7 +1065,6 @@ void cache_add_dhcp_entry(char *host_name, int prot,
inet_ntop(prot, host_address, daemon->addrbuff, ADDRSTRLEN);
if (crec->flags & F_CNAME)
-
my_syslog(MS_DHCP | LOG_WARNING,
_("%s is a CNAME, not giving it to the DHCP lease of %s"),
host_name, daemon->addrbuff);
@@ -1083,27 +1117,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
crec->uid = uid++;
cache_hash(crec);
- for (a = daemon->cnames; a; a = a->next)
- if (hostname_isequal(host_name, a->target))
- {
- if ((aliasc = dhcp_spare))
- dhcp_spare = dhcp_spare->next;
- else /* need new one */
- aliasc = whine_malloc(sizeof(struct crec));
-
- if (aliasc)
- {
- aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME;
- if (ttd == 0)
- aliasc->flags |= F_IMMORTAL;
- else
- aliasc->ttd = ttd;
- aliasc->name.namep = a->alias;
- aliasc->addr.cname.cache = crec;
- aliasc->addr.cname.uid = crec->uid;
- cache_hash(aliasc);
- }
- }
+ add_dhcp_cname(crec, ttd);
}
}
#endif
diff --git a/src/option.c b/src/option.c
index c474db8..faef72a 100644
--- a/src/option.c
+++ b/src/option.c
@@ -3129,12 +3129,12 @@ static void read_file(char *file, FILE *f, int hard_opt)
while (fgets(buff, MAXDNAME, f))
{
- int white, i, option; ;
- char *errmess, *p, *arg, *start;
+ int white, i, option = hard_opt;
+ char *errmess, *p, *arg = NULL, *start;
size_t len;
/* Memory allocation failure longjmps here if mem_recover == 1 */
- if (hard_opt)
+ if (option != 0)
{
if (setjmp(mem_jmp))
continue;
@@ -3208,7 +3208,7 @@ static void read_file(char *file, FILE *f, int hard_opt)
else
start[len] = 0;
- if (hard_opt != 0)
+ if (option != 0)
arg = start;
else if ((p=strchr(start, '=')))
{
@@ -3220,9 +3220,7 @@ static void read_file(char *file, FILE *f, int hard_opt)
else
arg = NULL;
- if (hard_opt != 0)
- option = hard_opt;
- else
+ if (option == 0)
{
for (option = 0, i = 0; opts[i].name; i++)
if (strcmp(opts[i].name, start) == 0)