summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Kelley <simon@thekelleys.org.uk>2022-02-08 11:37:06 +0000
committerSimon Kelley <simon@thekelleys.org.uk>2022-02-08 12:10:27 +0000
commite426c2d3bc182d790f83039b77a09d55230ca71f (patch)
treef79f154bb67260fcc4045a1c52b091fc5c66c4b8
parent6279d9eaf3537be156bb722fbb700cdb673eeb38 (diff)
downloaddnsmasq-e426c2d3bc182d790f83039b77a09d55230ca71f.tar.gz
Add --conf-scriptv2.87test8
-rw-r--r--CHANGELOG2
-rw-r--r--man/dnsmasq.821
-rw-r--r--src/option.c74
3 files changed, 85 insertions, 12 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 82835ee..e6fe8fd 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -47,6 +47,8 @@ version 2.87
always allocates a fresh index, they are not reused). We now
take this behaviour into account and keep up with changing indexes.
+ Add --conf-script configuration option.
+
version 2.86
Handle DHCPREBIND requests in the DHCPv6 server code.
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index 6ce61dd..ca155f0 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -2141,6 +2141,23 @@ A special case of
which differs in two respects. Firstly, only \fB--server\fP and \fB--rev-server\fP are allowed
in the configuration file included. Secondly, the file is re-read and the configuration
therein is updated when dnsmasq receives SIGHUP.
+.TP
+.B \--conf-script=<file>[ <arg]
+Execute <file>, and treat what it emits to stdout as the contents of a configuration file.
+If the script exits with a non-zero exit code, dnsmasq treats this as a fatal error.
+The script can be passed arguments, space seperated from the filename and each other so, for instance
+.B --conf-dir="/etc/dnsmasq-uncompress-ads /share/ads-domains.gz"
+
+with /etc/dnsmasq-uncompress-ads containing
+
+set -e
+
+zcat ${1} | sed -e "s:^:address=/:" -e "s:$:/:"
+
+exit 0
+
+and /share/ads-domains.gz containing a compressed
+list of ad server domains will save disk space with large ad-server blocklists.
.SH CONFIG FILE
At startup, dnsmasq reads
.I /etc/dnsmasq.conf,
@@ -2537,7 +2554,9 @@ file/directory, permissions).
5 - Other miscellaneous problem.
.PP
11 or greater - a non zero return code was received from the
-lease-script process "init" call. The exit code from dnsmasq is the
+lease-script process "init" call or a
+.B \--conf-script
+file. The exit code from dnsmasq is the
script's exit code with 10 added.
.SH LIMITS
diff --git a/src/option.c b/src/option.c
index fded28e..d9dd6a3 100644
--- a/src/option.c
+++ b/src/option.c
@@ -179,6 +179,8 @@ struct myoption {
#define LOPT_FILTER_AAAA 370
#define LOPT_STRIP_SBNET 371
#define LOPT_STRIP_MAC 372
+#define LOPT_CONF_OPT 373
+#define LOPT_CONF_SCRIPT 374
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -225,6 +227,7 @@ static const struct myoption opts[] =
{ "local", 1, 0, LOPT_LOCAL },
{ "address", 1, 0, 'A' },
{ "conf-file", 2, 0, 'C' },
+ { "conf-script", 1, 0, LOPT_CONF_SCRIPT },
{ "no-resolv", 0, 0, 'R' },
{ "expand-hosts", 0, 0, 'E' },
{ "localmx", 0, 0, 'L' },
@@ -467,6 +470,7 @@ static struct {
{ LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change scripts as this user."), NULL },
{ LOPT_SCRIPT_ARP, OPT_SCRIPT_ARP, NULL, gettext_noop("Call dhcp-script with changes to local ARP table."), NULL },
{ '7', ARG_DUP, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL },
+ { LOPT_CONF_SCRIPT, ARG_DUP, "<path>", gettext_noop("Execute file and read configuration from stdin."), NULL },
{ '8', ARG_ONE, "<facility>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
{ '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
{ '0', ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
@@ -1810,6 +1814,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
break;
}
+ case LOPT_CONF_SCRIPT: /* --conf-script */
+ {
+ char *file = opt_string_alloc(arg);
+ if (file)
+ {
+ one_file(file, LOPT_CONF_SCRIPT);
+ free(file);
+ }
+ break;
+ }
+
case '7': /* --conf-dir */
{
DIR *dir_stream;
@@ -4966,11 +4981,19 @@ static void read_file(char *file, FILE *f, int hard_opt)
while (fgets(buff, MAXDNAME, f))
{
- int white, i;
- volatile int option = (hard_opt == LOPT_REV_SERV) ? 0 : hard_opt;
+ int white, i, script = 0;
+ volatile int option;
char *errmess, *p, *arg, *start;
size_t len;
+ if (hard_opt == LOPT_CONF_SCRIPT)
+ {
+ hard_opt = 0;
+ script = 1;
+ }
+
+ option = (hard_opt == LOPT_REV_SERV) ? 0 : hard_opt;
+
/* Memory allocation failure longjmps here if mem_recover == 1 */
if (option != 0 || hard_opt == LOPT_REV_SERV)
{
@@ -5084,7 +5107,11 @@ static void read_file(char *file, FILE *f, int hard_opt)
if (errmess || !one_opt(option, arg, daemon->namebuff, _("error"), 0, hard_opt == LOPT_REV_SERV))
{
- sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
+ if (script)
+ sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" in output from %s"), file);
+ else
+ sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
+
if (hard_opt != 0)
my_syslog(LOG_ERR, "%s", daemon->namebuff);
else
@@ -5093,7 +5120,6 @@ static void read_file(char *file, FILE *f, int hard_opt)
}
mem_recover = 0;
- fclose(f);
}
#if defined(HAVE_DHCP) && defined(HAVE_INOTIFY)
@@ -5113,7 +5139,7 @@ int option_read_dynfile(char *file, int flags)
static int one_file(char *file, int hard_opt)
{
FILE *f;
- int nofile_ok = 0;
+ int nofile_ok = 0, do_popen = 0;
static int read_stdin = 0;
static struct fileread {
dev_t dev;
@@ -5121,13 +5147,13 @@ static int one_file(char *file, int hard_opt)
struct fileread *next;
} *filesread = NULL;
- if (hard_opt == '7')
+ if (hard_opt == LOPT_CONF_OPT)
{
/* default conf-file reading */
hard_opt = 0;
nofile_ok = 1;
}
-
+
if (hard_opt == 0 && strcmp(file, "-") == 0)
{
if (read_stdin == 1)
@@ -5141,6 +5167,12 @@ static int one_file(char *file, int hard_opt)
/* ignore repeated files. */
struct stat statbuf;
+ if (hard_opt == LOPT_CONF_SCRIPT)
+ {
+ hard_opt = 0;
+ do_popen = 1;
+ }
+
if (hard_opt == 0 && stat(file, &statbuf) == 0)
{
struct fileread *r;
@@ -5155,8 +5187,13 @@ static int one_file(char *file, int hard_opt)
r->dev = statbuf.st_dev;
r->ino = statbuf.st_ino;
}
-
- if (!(f = fopen(file, "r")))
+
+ if (do_popen)
+ {
+ if (!(f = popen(file, "r")))
+ die(_("cannot execute %s: %s"), file, EC_FILE);
+ }
+ else if (!(f = fopen(file, "r")))
{
if (errno == ENOENT && nofile_ok)
return 1; /* No conffile, all done. */
@@ -5174,7 +5211,21 @@ static int one_file(char *file, int hard_opt)
}
}
- read_file(file, f, hard_opt);
+ read_file(file, f, do_popen ? LOPT_CONF_SCRIPT : hard_opt);
+
+ if (do_popen)
+ {
+ int rc;
+
+ if ((rc = pclose(f)) == -1)
+ die(_("error executing %s: %s"), file, EC_MISC);
+
+ if (rc != 0)
+ die(_("%s returns non-zero error code"), file, rc+10);
+ }
+ else
+ fclose(f);
+
return 1;
}
@@ -5315,6 +5366,7 @@ void read_servers_file(void)
mark_servers(SERV_FROM_FILE);
read_file(daemon->servers_file, f, LOPT_REV_SERV);
+ fclose(f);
cleanup_servers();
check_servers(0);
}
@@ -5540,7 +5592,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
free(conffile);
}
else
- one_file(CONFFILE, '7');
+ one_file(CONFFILE, LOPT_CONF_OPT);
/* port might not be known when the address is parsed - fill in here */
if (daemon->servers)