From a1d973f987e392870ba42a7e9d4d3cd166879ea0 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Thu, 22 Dec 2016 22:09:50 +0000 Subject: [PATCH] Allow multiple CNAMEs in a single --cname= option. --- man/dnsmasq.8 | 6 ++++-- src/option.c | 33 ++++++++++++++++++++------------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 index 248bc83..5bad224 100644 --- a/man/dnsmasq.8 +++ b/man/dnsmasq.8 @@ -581,7 +581,7 @@ Return a PTR DNS record. .B --naptr-record=,,,,,[,] Return an NAPTR DNS record, as specified in RFC3403. .TP -.B --cname=,[,] +.B --cname=,[,][,] Return a CNAME record which indicates that is really . There are significant limitations on the target; it must be a DNS name which is known to dnsmasq from /etc/hosts (or additional @@ -589,7 +589,9 @@ 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 -is permissable to have more than one cname pointing to the same target. +is permissable to have more than one cname pointing to the same target. Indeed +it's possible to declare multiple cnames to a target in a single line, like so: +.B --cname=cname1,cname2,target If the time-to-live is given, it overrides the default, which is zero or the value of -local-ttl. The value is a positive integer and gives diff --git a/src/option.c b/src/option.c index d811ed3..683d4da 100644 --- a/src/option.c +++ b/src/option.c @@ -3728,22 +3728,27 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma case LOPT_CNAME: /* --cname */ { struct cname *new; - char *alias, *target, *ttls; + char *alias, *target, *last, *pen; int ttl = -1; - if (!(comma = split(arg))) - ret_err(gen_err); - - if ((ttls = split(comma)) && !atoi_check(ttls, &ttl)) - ret_err(_("bad TTL")); - - alias = canonicalise_opt(arg); - target = canonicalise_opt(comma); - - if (!alias || !target) - ret_err(_("bad CNAME")); - else + for (last = pen = NULL, comma = arg; comma; comma = split(comma)) { + pen = last; + last = comma; + } + + if (!pen) + ret_err(_("bad CNAME")); + + if (pen != arg && atoi_check(last, &ttl)) + last = pen; + + target = canonicalise_opt(last); + + while (arg != last) + { + alias = canonicalise_opt(arg); + for (new = daemon->cnames; new; new = new->next) if (hostname_isequal(new->alias, arg)) ret_err(_("duplicate CNAME")); @@ -3753,6 +3758,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma new->alias = alias; new->target = target; new->ttl = ttl; + + arg += strlen(arg)+1; } break;