Commit 7b1eae4f authored by Simon Kelley's avatar Simon Kelley

Add --servers-file option.

parent c152dc84
...@@ -63,6 +63,9 @@ version 2.69 ...@@ -63,6 +63,9 @@ version 2.69
a workable state. a workable state.
Add --rev-server. Thanks to Dave Taht for suggesting this. 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 version 2.68
......
...@@ -1678,6 +1678,13 @@ files. If extension(s) are given, any files which end in those ...@@ -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 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 with # are always skipped. This flag may be given on the command
line or in a configuration file. 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 .SH CONFIG FILE
At startup, dnsmasq reads At startup, dnsmasq reads
.I /etc/dnsmasq.conf, .I /etc/dnsmasq.conf,
......
...@@ -225,7 +225,7 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings) ...@@ -225,7 +225,7 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
{ {
const char *str = NULL; const char *str = NULL;
union mysockaddr addr, source_addr; union mysockaddr addr, source_addr;
int flags; int flags = 0;
char interface[IF_NAMESIZE]; char interface[IF_NAMESIZE];
char *str_addr, *str_domain = NULL; char *str_addr, *str_domain = NULL;
......
...@@ -1114,7 +1114,7 @@ static void async_event(int pipe, time_t now) ...@@ -1114,7 +1114,7 @@ static void async_event(int pipe, time_t now)
{ {
pid_t p; pid_t p;
struct event_desc ev; struct event_desc ev;
int i; int i, check = 0;
char *msg; char *msg;
/* NOTE: the memory used to return msg is leaked: use msgs in events only /* 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) ...@@ -1125,11 +1125,25 @@ static void async_event(int pipe, time_t now)
{ {
case EVENT_RELOAD: case EVENT_RELOAD:
clear_cache_and_reload(now); 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); if (daemon->resolv_files && option_bool(OPT_NO_POLL))
check_servers(); {
reload_servers(daemon->resolv_files->name);
check = 1;
}
if (daemon->servers_file)
{
read_servers_file();
check = 1;
}
if (check)
check_servers();
} }
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
rerun_scripts(); rerun_scripts();
#endif #endif
......
...@@ -456,6 +456,7 @@ union mysockaddr { ...@@ -456,6 +456,7 @@ union mysockaddr {
#define SERV_COUNTED 512 /* workspace for log code */ #define SERV_COUNTED 512 /* workspace for log code */
#define SERV_USE_RESOLV 1024 /* forward this domain in the normal way */ #define SERV_USE_RESOLV 1024 /* forward this domain in the normal way */
#define SERV_NO_REBIND 2048 /* inhibit dns-rebind protection */ #define SERV_NO_REBIND 2048 /* inhibit dns-rebind protection */
#define SERV_FROM_FILE 4096 /* read from --servers-file */
struct serverfd { struct serverfd {
int fd; int fd;
...@@ -864,6 +865,7 @@ extern struct daemon { ...@@ -864,6 +865,7 @@ extern struct daemon {
unsigned int options, options2; unsigned int options, options2;
struct resolvc default_resolv, *resolv_files; struct resolvc default_resolv, *resolv_files;
time_t last_resolv; time_t last_resolv;
char *servers_file;
struct mx_srv_record *mxnames; struct mx_srv_record *mxnames;
struct naptr *naptr; struct naptr *naptr;
struct txt_record *txt, *rr; struct txt_record *txt, *rr;
...@@ -1130,6 +1132,7 @@ void read_opts (int argc, char **argv, char *compile_opts); ...@@ -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, char *option_string(int prot, unsigned int opt, unsigned char *val,
int opt_len, char *buf, int buf_len); int opt_len, char *buf, int buf_len);
void reread_dhcp(void); void reread_dhcp(void);
void read_servers_file(void);
void set_option_bool(unsigned int opt); void set_option_bool(unsigned int opt);
void reset_option_bool(unsigned int opt); void reset_option_bool(unsigned int opt);
struct hostsfile *expand_filelist(struct hostsfile *list); struct hostsfile *expand_filelist(struct hostsfile *list);
......
...@@ -287,6 +287,8 @@ static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len ...@@ -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, 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) unsigned char *digest, size_t digest_len, int algo)
{ {
(void)digest_len;
switch (algo) switch (algo)
{ {
case 1: case 5: case 7: case 8: case 10: case 1: case 5: case 7: case 8: case 10:
......
...@@ -1291,7 +1291,8 @@ void add_update_server(int flags, ...@@ -1291,7 +1291,8 @@ void add_update_server(int flags,
const char *interface, const char *interface,
const char *domain) const char *domain)
{ {
struct server *serv; struct server *serv, *next = NULL;
char *domain_str = NULL;
/* See if there is a suitable candidate, and unmark */ /* See if there is a suitable candidate, and unmark */
for (serv = daemon->servers; serv; serv = serv->next) for (serv = daemon->servers; serv; serv = serv->next)
...@@ -1308,17 +1309,18 @@ void add_update_server(int flags, ...@@ -1308,17 +1309,18 @@ void add_update_server(int flags,
continue; continue;
} }
serv->flags &= ~SERV_MARK;
break; 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. */ /* Not found, create a new one. */
memset(serv, 0, sizeof(struct server)); if (domain && !(domain_str = whine_malloc(strlen(domain)+1)))
if (domain && !(serv->domain = whine_malloc(strlen(domain)+1)))
{ {
free(serv); free(serv);
serv = NULL; serv = NULL;
...@@ -1335,25 +1337,27 @@ void add_update_server(int flags, ...@@ -1335,25 +1337,27 @@ void add_update_server(int flags,
s->next = serv; s->next = serv;
} }
if (domain) if (domain)
strcpy(serv->domain, domain); strcpy(domain_str, domain);
} }
} }
if (serv) if (serv)
{ {
memset(serv, 0, sizeof(struct server));
serv->flags = flags; serv->flags = flags;
serv->domain = domain_str;
serv->next = next;
serv->queries = serv->failed_queries = 0; serv->queries = serv->failed_queries = 0;
if (domain) if (domain)
serv->flags |= SERV_HAS_DOMAIN; serv->flags |= SERV_HAS_DOMAIN;
if (interface) if (interface)
strcpy(serv->interface, interface); strcpy(serv->interface, interface);
else if (addr)
serv->interface[0] = 0; serv->addr = *addr;
if (source_addr)
serv->addr = *addr; serv->source_addr = *source_addr;
serv->source_addr = *source_addr;
} }
} }
......
...@@ -142,6 +142,7 @@ struct myoption { ...@@ -142,6 +142,7 @@ struct myoption {
#define LOPT_TRUST_ANCHOR 330 #define LOPT_TRUST_ANCHOR 330
#define LOPT_DNSSEC_DEBUG 331 #define LOPT_DNSSEC_DEBUG 331
#define LOPT_REV_SERV 332 #define LOPT_REV_SERV 332
#define LOPT_SERVERS_FILE 333
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
static const struct option opts[] = static const struct option opts[] =
...@@ -158,6 +159,7 @@ static const struct myoption opts[] = ...@@ -158,6 +159,7 @@ static const struct myoption opts[] =
{ "user", 2, 0, 'u' }, { "user", 2, 0, 'u' },
{ "group", 2, 0, 'g' }, { "group", 2, 0, 'g' },
{ "resolv-file", 2, 0, 'r' }, { "resolv-file", 2, 0, 'r' },
{ "servers-file", 1, 0, LOPT_SERVERS_FILE },
{ "mx-host", 1, 0, 'm' }, { "mx-host", 1, 0, 'm' },
{ "mx-target", 1, 0, 't' }, { "mx-target", 1, 0, 't' },
{ "cache-size", 2, 0, 'c' }, { "cache-size", 2, 0, 'c' },
...@@ -349,6 +351,7 @@ static struct { ...@@ -349,6 +351,7 @@ static struct {
{ 'Q', ARG_ONE, "<integer>", gettext_noop("Force the originating port for upstream DNS queries."), NULL }, { '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', 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 }, { '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 }, { '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_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 }, { 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) ...@@ -1385,7 +1388,7 @@ void reset_option_bool(unsigned int opt)
daemon->options2 &= ~(1u << (opt - 32)); 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; int i;
char *comma; char *comma;
...@@ -1588,6 +1591,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma ...@@ -1588,6 +1591,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
daemon->resolv_files = list; daemon->resolv_files = list;
break; break;
} }
case LOPT_SERVERS_FILE:
daemon->servers_file = opt_string_alloc(arg);
break;
case 'm': /* --mx-host */ case 'm': /* --mx-host */
{ {
...@@ -2152,6 +2159,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma ...@@ -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)); memset(newlist, 0, sizeof(struct server));
} }
if (servers_only && option == 'S')
newlist->flags |= SERV_FROM_FILE;
if (option == 'A') if (option == 'A')
{ {
newlist->flags |= SERV_LITERAL_ADDRESS; newlist->flags |= SERV_LITERAL_ADDRESS;
...@@ -2223,7 +2233,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma ...@@ -2223,7 +2233,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if (string) if (string)
ret_err(string); ret_err(string);
if (servers_only)
serv->flags |= SERV_FROM_FILE;
break; break;
} }
...@@ -3801,12 +3814,13 @@ static void read_file(char *file, FILE *f, int hard_opt) ...@@ -3801,12 +3814,13 @@ static void read_file(char *file, FILE *f, int hard_opt)
while (fgets(buff, MAXDNAME, f)) 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; char *errmess, *p, *arg = NULL, *start;
size_t len; size_t len;
/* Memory allocation failure longjmps here if mem_recover == 1 */ /* Memory allocation failure longjmps here if mem_recover == 1 */
if (option != 0) if (option != 0 || hard_opt == LOPT_REV_SERV)
{ {
if (setjmp(mem_jmp)) if (setjmp(mem_jmp))
continue; continue;
...@@ -3907,13 +3921,15 @@ static void read_file(char *file, FILE *f, int hard_opt) ...@@ -3907,13 +3921,15 @@ static void read_file(char *file, FILE *f, int hard_opt)
errmess = _("extraneous parameter"); errmess = _("extraneous parameter");
else if (opts[i].has_arg == 1 && !arg) else if (opts[i].has_arg == 1 && !arg)
errmess = _("missing parameter"); errmess = _("missing parameter");
else if (hard_opt == LOPT_REV_SERV && option != 'S' && option != LOPT_REV_SERV)
errmess = _("illegal option");
} }
oops: oops:
if (errmess) if (errmess)
strcpy(daemon->namebuff, 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); sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
if (hard_opt != 0) if (hard_opt != 0)
...@@ -4095,6 +4111,22 @@ struct hostsfile *expand_filelist(struct hostsfile *list) ...@@ -4095,6 +4111,22 @@ struct hostsfile *expand_filelist(struct hostsfile *list)
return 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 #ifdef HAVE_DHCP
void reread_dhcp(void) void reread_dhcp(void)
...@@ -4288,9 +4320,9 @@ void read_opts(int argc, char **argv, char *compile_opts) ...@@ -4288,9 +4320,9 @@ void read_opts(int argc, char **argv, char *compile_opts)
else else
{ {
#ifdef HAVE_GETOPT_LONG #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 #else
if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1)) if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1, 0))
#endif #endif
die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF); die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment