Add --conf-script

This commit is contained in:
Simon Kelley
2022-02-08 11:37:06 +00:00
parent 6279d9eaf3
commit e426c2d3bc
3 changed files with 85 additions and 12 deletions

View File

@@ -47,6 +47,8 @@ version 2.87
always allocates a fresh index, they are not reused). We now always allocates a fresh index, they are not reused). We now
take this behaviour into account and keep up with changing indexes. take this behaviour into account and keep up with changing indexes.
Add --conf-script configuration option.
version 2.86 version 2.86
Handle DHCPREBIND requests in the DHCPv6 server code. Handle DHCPREBIND requests in the DHCPv6 server code.

View File

@@ -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 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 in the configuration file included. Secondly, the file is re-read and the configuration
therein is updated when dnsmasq receives SIGHUP. 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 .SH CONFIG FILE
At startup, dnsmasq reads At startup, dnsmasq reads
.I /etc/dnsmasq.conf, .I /etc/dnsmasq.conf,
@@ -2537,7 +2554,9 @@ file/directory, permissions).
5 - Other miscellaneous problem. 5 - Other miscellaneous problem.
.PP .PP
11 or greater - a non zero return code was received from the 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. script's exit code with 10 added.
.SH LIMITS .SH LIMITS

View File

@@ -179,6 +179,8 @@ struct myoption {
#define LOPT_FILTER_AAAA 370 #define LOPT_FILTER_AAAA 370
#define LOPT_STRIP_SBNET 371 #define LOPT_STRIP_SBNET 371
#define LOPT_STRIP_MAC 372 #define LOPT_STRIP_MAC 372
#define LOPT_CONF_OPT 373
#define LOPT_CONF_SCRIPT 374
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
static const struct option opts[] = static const struct option opts[] =
@@ -225,6 +227,7 @@ static const struct myoption opts[] =
{ "local", 1, 0, LOPT_LOCAL }, { "local", 1, 0, LOPT_LOCAL },
{ "address", 1, 0, 'A' }, { "address", 1, 0, 'A' },
{ "conf-file", 2, 0, 'C' }, { "conf-file", 2, 0, 'C' },
{ "conf-script", 1, 0, LOPT_CONF_SCRIPT },
{ "no-resolv", 0, 0, 'R' }, { "no-resolv", 0, 0, 'R' },
{ "expand-hosts", 0, 0, 'E' }, { "expand-hosts", 0, 0, 'E' },
{ "localmx", 0, 0, 'L' }, { "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_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 }, { 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 }, { '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 }, { '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 }, { '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)"), "!" }, { '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; 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 */ case '7': /* --conf-dir */
{ {
DIR *dir_stream; DIR *dir_stream;
@@ -4966,11 +4981,19 @@ static void read_file(char *file, FILE *f, int hard_opt)
while (fgets(buff, MAXDNAME, f)) while (fgets(buff, MAXDNAME, f))
{ {
int white, i; int white, i, script = 0;
volatile int option = (hard_opt == LOPT_REV_SERV) ? 0 : hard_opt; volatile int option;
char *errmess, *p, *arg, *start; char *errmess, *p, *arg, *start;
size_t len; 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 */ /* Memory allocation failure longjmps here if mem_recover == 1 */
if (option != 0 || hard_opt == LOPT_REV_SERV) 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)) if (errmess || !one_opt(option, arg, daemon->namebuff, _("error"), 0, hard_opt == LOPT_REV_SERV))
{ {
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); sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
if (hard_opt != 0) if (hard_opt != 0)
my_syslog(LOG_ERR, "%s", daemon->namebuff); my_syslog(LOG_ERR, "%s", daemon->namebuff);
else else
@@ -5093,7 +5120,6 @@ static void read_file(char *file, FILE *f, int hard_opt)
} }
mem_recover = 0; mem_recover = 0;
fclose(f);
} }
#if defined(HAVE_DHCP) && defined(HAVE_INOTIFY) #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) static int one_file(char *file, int hard_opt)
{ {
FILE *f; FILE *f;
int nofile_ok = 0; int nofile_ok = 0, do_popen = 0;
static int read_stdin = 0; static int read_stdin = 0;
static struct fileread { static struct fileread {
dev_t dev; dev_t dev;
@@ -5121,7 +5147,7 @@ static int one_file(char *file, int hard_opt)
struct fileread *next; struct fileread *next;
} *filesread = NULL; } *filesread = NULL;
if (hard_opt == '7') if (hard_opt == LOPT_CONF_OPT)
{ {
/* default conf-file reading */ /* default conf-file reading */
hard_opt = 0; hard_opt = 0;
@@ -5141,6 +5167,12 @@ static int one_file(char *file, int hard_opt)
/* ignore repeated files. */ /* ignore repeated files. */
struct stat statbuf; struct stat statbuf;
if (hard_opt == LOPT_CONF_SCRIPT)
{
hard_opt = 0;
do_popen = 1;
}
if (hard_opt == 0 && stat(file, &statbuf) == 0) if (hard_opt == 0 && stat(file, &statbuf) == 0)
{ {
struct fileread *r; struct fileread *r;
@@ -5156,7 +5188,12 @@ static int one_file(char *file, int hard_opt)
r->ino = statbuf.st_ino; 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) if (errno == ENOENT && nofile_ok)
return 1; /* No conffile, all done. */ 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; return 1;
} }
@@ -5315,6 +5366,7 @@ void read_servers_file(void)
mark_servers(SERV_FROM_FILE); mark_servers(SERV_FROM_FILE);
read_file(daemon->servers_file, f, LOPT_REV_SERV); read_file(daemon->servers_file, f, LOPT_REV_SERV);
fclose(f);
cleanup_servers(); cleanup_servers();
check_servers(0); check_servers(0);
} }
@@ -5540,7 +5592,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
free(conffile); free(conffile);
} }
else else
one_file(CONFFILE, '7'); one_file(CONFFILE, LOPT_CONF_OPT);
/* port might not be known when the address is parsed - fill in here */ /* port might not be known when the address is parsed - fill in here */
if (daemon->servers) if (daemon->servers)