summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Kelley <simon@thekelleys.org.uk>2014-02-20 13:43:28 +0000
committerSimon Kelley <simon@thekelleys.org.uk>2014-02-20 13:43:28 +0000
commit7b1eae4f503ba81b9b3a41a52bede6d0eeab9f49 (patch)
treeafc613336ec0b2104ae9eff61a90183f12ce5437
parentc152dc8492773313165a807495ac99dbbe83b9fe (diff)
downloaddnsmasq-7b1eae4f503ba81b9b3a41a52bede6d0eeab9f49.tar.gz
Add --servers-file option.
-rw-r--r--CHANGELOG3
-rw-r--r--man/dnsmasq.87
-rw-r--r--src/dbus.c2
-rw-r--r--src/dnsmasq.c22
-rw-r--r--src/dnsmasq.h3
-rw-r--r--src/dnssec.c2
-rw-r--r--src/network.c34
-rw-r--r--src/option.c46
8 files changed, 92 insertions, 27 deletions
diff --git a/CHANGELOG b/CHANGELOG
index c2e1866..806fc8e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -63,6 +63,9 @@ version 2.69
a workable state.
Add --rev-server. Thanks to Dave Taht for suggesting this.
+
+ Add --servers-file. Allows dynamic update of upstream servers
+ full access to configuration.
version 2.68
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index 8d2c95d..ed71ebe 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -1678,6 +1678,13 @@ files. If extension(s) are given, any files which end in those
extensions are skipped. Any files whose names end in ~ or start with . or start and end
with # are always skipped. This flag may be given on the command
line or in a configuration file.
+.TP
+.B --servers-file=<file>
+A special case of
+.B --conf-file
+which differs in two respects. Firstly, only --server and --rev-server are allowed
+in the configuration file included. Secondly, the file is re-read and the configuration
+therein is updated when dnsmasq recieves SIGHUP.
.SH CONFIG FILE
At startup, dnsmasq reads
.I /etc/dnsmasq.conf,
diff --git a/src/dbus.c b/src/dbus.c
index eb0ce6b..ed7ac8a 100644
--- a/src/dbus.c
+++ b/src/dbus.c
@@ -225,7 +225,7 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
{
const char *str = NULL;
union mysockaddr addr, source_addr;
- int flags;
+ int flags = 0;
char interface[IF_NAMESIZE];
char *str_addr, *str_domain = NULL;
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index 3c8a847..b1a0964 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -1114,7 +1114,7 @@ static void async_event(int pipe, time_t now)
{
pid_t p;
struct event_desc ev;
- int i;
+ int i, check = 0;
char *msg;
/* NOTE: the memory used to return msg is leaked: use msgs in events only
@@ -1125,11 +1125,25 @@ static void async_event(int pipe, time_t now)
{
case EVENT_RELOAD:
clear_cache_and_reload(now);
- if (daemon->port != 0 && daemon->resolv_files && option_bool(OPT_NO_POLL))
+
+ if (daemon->port != 0)
{
- reload_servers(daemon->resolv_files->name);
- check_servers();
+ if (daemon->resolv_files && option_bool(OPT_NO_POLL))
+ {
+ reload_servers(daemon->resolv_files->name);
+ check = 1;
+ }
+
+ if (daemon->servers_file)
+ {
+ read_servers_file();
+ check = 1;
+ }
+
+ if (check)
+ check_servers();
}
+
#ifdef HAVE_DHCP
rerun_scripts();
#endif
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 59d9e9e..caa8ce7 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -456,6 +456,7 @@ union mysockaddr {
#define SERV_COUNTED 512 /* workspace for log code */
#define SERV_USE_RESOLV 1024 /* forward this domain in the normal way */
#define SERV_NO_REBIND 2048 /* inhibit dns-rebind protection */
+#define SERV_FROM_FILE 4096 /* read from --servers-file */
struct serverfd {
int fd;
@@ -864,6 +865,7 @@ extern struct daemon {
unsigned int options, options2;
struct resolvc default_resolv, *resolv_files;
time_t last_resolv;
+ char *servers_file;
struct mx_srv_record *mxnames;
struct naptr *naptr;
struct txt_record *txt, *rr;
@@ -1130,6 +1132,7 @@ void read_opts (int argc, char **argv, char *compile_opts);
char *option_string(int prot, unsigned int opt, unsigned char *val,
int opt_len, char *buf, int buf_len);
void reread_dhcp(void);
+void read_servers_file(void);
void set_option_bool(unsigned int opt);
void reset_option_bool(unsigned int opt);
struct hostsfile *expand_filelist(struct hostsfile *list);
diff --git a/src/dnssec.c b/src/dnssec.c
index 5511143..8bd7c29 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -287,6 +287,8 @@ static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len
static int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
unsigned char *digest, size_t digest_len, int algo)
{
+ (void)digest_len;
+
switch (algo)
{
case 1: case 5: case 7: case 8: case 10:
diff --git a/src/network.c b/src/network.c
index 6eb516b..a4380ae 100644
--- a/src/network.c
+++ b/src/network.c
@@ -1291,7 +1291,8 @@ void add_update_server(int flags,
const char *interface,
const char *domain)
{
- struct server *serv;
+ struct server *serv, *next = NULL;
+ char *domain_str = NULL;
/* See if there is a suitable candidate, and unmark */
for (serv = daemon->servers; serv; serv = serv->next)
@@ -1308,17 +1309,18 @@ void add_update_server(int flags,
continue;
}
- serv->flags &= ~SERV_MARK;
-
break;
}
-
- if (!serv && (serv = whine_malloc(sizeof (struct server))))
+
+ if (serv)
+ {
+ domain_str = serv->domain;
+ next = serv->next;
+ }
+ else if ((serv = whine_malloc(sizeof (struct server))))
{
/* Not found, create a new one. */
- memset(serv, 0, sizeof(struct server));
-
- if (domain && !(serv->domain = whine_malloc(strlen(domain)+1)))
+ if (domain && !(domain_str = whine_malloc(strlen(domain)+1)))
{
free(serv);
serv = NULL;
@@ -1335,25 +1337,27 @@ void add_update_server(int flags,
s->next = serv;
}
if (domain)
- strcpy(serv->domain, domain);
+ strcpy(domain_str, domain);
}
}
if (serv)
{
+ memset(serv, 0, sizeof(struct server));
serv->flags = flags;
+ serv->domain = domain_str;
+ serv->next = next;
serv->queries = serv->failed_queries = 0;
if (domain)
serv->flags |= SERV_HAS_DOMAIN;
if (interface)
- strcpy(serv->interface, interface);
- else
- serv->interface[0] = 0;
-
- serv->addr = *addr;
- serv->source_addr = *source_addr;
+ strcpy(serv->interface, interface);
+ if (addr)
+ serv->addr = *addr;
+ if (source_addr)
+ serv->source_addr = *source_addr;
}
}
diff --git a/src/option.c b/src/option.c
index b090381..2d860d5 100644
--- a/src/option.c
+++ b/src/option.c
@@ -142,6 +142,7 @@ struct myoption {
#define LOPT_TRUST_ANCHOR 330
#define LOPT_DNSSEC_DEBUG 331
#define LOPT_REV_SERV 332
+#define LOPT_SERVERS_FILE 333
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -158,6 +159,7 @@ static const struct myoption opts[] =
{ "user", 2, 0, 'u' },
{ "group", 2, 0, 'g' },
{ "resolv-file", 2, 0, 'r' },
+ { "servers-file", 1, 0, LOPT_SERVERS_FILE },
{ "mx-host", 1, 0, 'm' },
{ "mx-target", 1, 0, 't' },
{ "cache-size", 2, 0, 'c' },
@@ -349,6 +351,7 @@ static struct {
{ 'Q', ARG_ONE, "<integer>", gettext_noop("Force the originating port for upstream DNS queries."), NULL },
{ 'R', OPT_NO_RESOLV, NULL, gettext_noop("Do NOT read resolv.conf."), NULL },
{ 'r', ARG_DUP, "<path>", gettext_noop("Specify path to resolv.conf (defaults to %s)."), RESOLVFILE },
+ { LOPT_SERVERS_FILE, ARG_ONE, "<path>", gettext_noop("Specify path to file with server= options"), NULL },
{ 'S', ARG_DUP, "/<domain>/<ipaddr>", gettext_noop("Specify address(es) of upstream servers with optional domains."), NULL },
{ LOPT_REV_SERV, ARG_DUP, "<addr>/<prefix>,<ipaddr>", gettext_noop("Specify address of upstream servers for reverse address queries"), NULL },
{ LOPT_LOCAL, ARG_DUP, "/<domain>/", gettext_noop("Never forward queries to specified domains."), NULL },
@@ -1385,7 +1388,7 @@ void reset_option_bool(unsigned int opt)
daemon->options2 &= ~(1u << (opt - 32));
}
-static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line)
+static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line, int servers_only)
{
int i;
char *comma;
@@ -1588,6 +1591,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
daemon->resolv_files = list;
break;
}
+
+ case LOPT_SERVERS_FILE:
+ daemon->servers_file = opt_string_alloc(arg);
+ break;
case 'm': /* --mx-host */
{
@@ -2152,6 +2159,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
memset(newlist, 0, sizeof(struct server));
}
+ if (servers_only && option == 'S')
+ newlist->flags |= SERV_FROM_FILE;
+
if (option == 'A')
{
newlist->flags |= SERV_LITERAL_ADDRESS;
@@ -2223,7 +2233,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if (string)
ret_err(string);
-
+
+ if (servers_only)
+ serv->flags |= SERV_FROM_FILE;
+
break;
}
@@ -3801,12 +3814,13 @@ static void read_file(char *file, FILE *f, int hard_opt)
while (fgets(buff, MAXDNAME, f))
{
- int white, i, option = hard_opt;
+ int white, i;
+ volatile int option = (hard_opt == LOPT_REV_SERV) ? 0 : hard_opt;
char *errmess, *p, *arg = NULL, *start;
size_t len;
/* Memory allocation failure longjmps here if mem_recover == 1 */
- if (option != 0)
+ if (option != 0 || hard_opt == LOPT_REV_SERV)
{
if (setjmp(mem_jmp))
continue;
@@ -3907,13 +3921,15 @@ static void read_file(char *file, FILE *f, int hard_opt)
errmess = _("extraneous parameter");
else if (opts[i].has_arg == 1 && !arg)
errmess = _("missing parameter");
+ else if (hard_opt == LOPT_REV_SERV && option != 'S' && option != LOPT_REV_SERV)
+ errmess = _("illegal option");
}
oops:
if (errmess)
strcpy(daemon->namebuff, errmess);
- if (errmess || !one_opt(option, arg, buff, _("error"), 0))
+ if (errmess || !one_opt(option, arg, buff, _("error"), 0, hard_opt == LOPT_REV_SERV))
{
sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
if (hard_opt != 0)
@@ -4095,6 +4111,22 @@ struct hostsfile *expand_filelist(struct hostsfile *list)
return list;
}
+void read_servers_file(void)
+{
+ FILE *f;
+
+ if (!(f = fopen(daemon->servers_file, "r")))
+ {
+ my_syslog(LOG_ERR, _("cannot read %s: %s"), daemon->servers_file, strerror(errno));
+ return;
+ }
+
+ mark_servers(SERV_FROM_FILE);
+ cleanup_servers();
+
+ read_file(daemon->servers_file, f, LOPT_REV_SERV);
+}
+
#ifdef HAVE_DHCP
void reread_dhcp(void)
@@ -4288,9 +4320,9 @@ void read_opts(int argc, char **argv, char *compile_opts)
else
{
#ifdef HAVE_GETOPT_LONG
- if (!one_opt(option, arg, daemon->namebuff, _("try --help"), 1))
+ if (!one_opt(option, arg, daemon->namebuff, _("try --help"), 1, 0))
#else
- if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1))
+ if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1, 0))
#endif
die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF);
}