diff --git a/CHANGELOG b/CHANGELOG index 851612b..b3fd0dd 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,8 @@ version 2.77 + Generate an error when configured with a CNAME loop, + rather than a crash. Thnaks to George Metz for + spotting this problem. + Calculate the length of TFTP error reply packet correctly. This fixes a problem when the error message in a TFTP packet exceeds the arbitrary diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 4b55bb5..4dffe1b 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -310,9 +310,9 @@ struct ptr_record { }; struct cname { - int ttl; + int ttl, flag; char *alias, *target; - struct cname *next; + struct cname *next, *targetp; }; struct ds_config { diff --git a/src/option.c b/src/option.c index 50d26ba..9bad827 100644 --- a/src/option.c +++ b/src/option.c @@ -4663,11 +4663,44 @@ void read_opts(int argc, char **argv, char *compile_opts) if (daemon->cnames) { - struct cname *cn; - + struct cname *cn, *cn2, *cn3; + +#define NOLOOP 1 +#define TESTLOOP 2 + + /* Fill in TTL for CNAMES noe we have local_ttl. + Also prepare to do loop detection. */ for (cn = daemon->cnames; cn; cn = cn->next) - if (cn->ttl == -1) - cn->ttl = daemon->local_ttl; + { + if (cn->ttl == -1) + cn->ttl = daemon->local_ttl; + cn->flag = 0; + cn->targetp = NULL; + for (cn2 = daemon->cnames; cn2; cn2 = cn2->next) + if (hostname_isequal(cn->target, cn2->alias)) + { + cn->targetp = cn2; + break; + } + } + + /* Find any CNAME loops.*/ + for (cn = daemon->cnames; cn; cn = cn->next) + { + for (cn2 = cn->targetp; cn2; cn2 = cn2->targetp) + { + if (cn2->flag == NOLOOP) + break; + + if (cn2->flag == TESTLOOP) + die(_("CNAME loop involving %s"), cn->alias, EC_BADCONF); + + cn2->flag = TESTLOOP; + } + + for (cn3 = cn->targetp; cn3 != cn2; cn3 = cn3->targetp) + cn3->flag = NOLOOP; + } } if (daemon->if_addrs)