Add --servers-file option.
diff --git a/CHANGELOG b/CHANGELOG
index c2e1866..806fc8e 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -63,6 +63,9 @@
 	    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 @@
 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 @@
     {
       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 @@
 {
   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 @@
       {
       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 @@
 #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 @@
   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 @@
 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 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 @@
 		       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 @@
 	      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 @@
 	      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 @@
 #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 @@
     { "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 @@
   { '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 @@
     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 @@
 	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 @@
 	    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 @@
 	
 	if (string)
 	  ret_err(string);
-
+	
+	if (servers_only)
+	  serv->flags |= SERV_FROM_FILE;
+	
 	break;
       }
 
@@ -3801,12 +3814,13 @@
   
   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 @@
 	    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 @@
   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 @@
       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);
 	}