[Dnsmasq-discuss] [PATCH] Flush dynamic configuration on reload and discard DHCPv6 options on SIGHUP

Alin Nastac alin.nastac at gmail.com
Wed Dec 2 13:50:39 GMT 2015


Reload configuration from dynamic configuration files when they're
modified, but not before flushing old configuration loaded from the
same place.This behavioral change affects options --dhcp-hostsdir,
--dhcp-optsdir and --hostsdir.

Discard DHCPv6 options on SIGHUP before reloading them from --dhcp-optsfile.
---
 src/cache.c   |  36 ++++++++++-
 src/dhcp.c    |   1 +
 src/dnsmasq.h |   9 ++-
 src/inotify.c | 189 +++++++++++++++++++++++++++++++++++++++++++++----------
 src/option.c  | 199 +++++++++++++++++++++++++++++++++++++++++++++++++---------
 src/rfc2131.c |   1 +
 6 files changed, 367 insertions(+), 68 deletions(-)

diff --git a/src/cache.c b/src/cache.c
index 1b76b67..757265c 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -1029,6 +1029,31 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size, struct cr
   return name_count;
 }
 	    
+void flush_hostsfile(char *filename, unsigned int index)
+{
+  struct crec *crecp, **up;
+  int i;
+  int addr_count = 0;
+
+  for (i = 0; i < hash_size; i++)
+    for (crecp = hash_table[i], up = &hash_table[i];
+	 crecp;
+	 crecp = crecp->hash_next)
+      if ((crecp->flags & F_HOSTS) &&
+	  (crecp->flags & (F_IPV4 | F_IPV6)) &&
+	  crecp->uid == index)
+	{
+	  addr_count++;
+	  *up = crecp->hash_next;
+	  cache_unlink(crecp);
+	  cache_free(crecp);
+	}
+      else
+	up = &crecp->hash_next;
+
+  my_syslog(LOG_INFO, _("flush hosts read from %s - %d addresses"), filename, addr_count);
+}
+
 void cache_reload(void)
 {
   struct crec *cache, **up, *tmp;
@@ -1543,11 +1568,18 @@ char *record_source(unsigned int index)
     if (ah->index == index)
       return ah->fname;
 
-#ifdef HAVE_INOTIFY
+  for (ah = daemon->dhcp_hosts_file; ah; ah = ah->next)
+    if (ah->index == index)
+      return ah->fname;
+  for (ah = daemon->dhcp_opts_file; ah; ah = ah->next)
+    if (ah->index == index)
+      return ah->fname;
   for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
      if (ah->index == index)
        return ah->fname;
-#endif
+  for (ah = daemon->dynamic_files; ah; ah = ah->next)
+     if (ah->index == index)
+       return ah->fname;
 
   return "<unknown>";
 }
diff --git a/src/dhcp.c b/src/dhcp.c
index 1c85e42..18ccab9 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -882,6 +882,7 @@ void dhcp_read_ethers(void)
 	    {
 	      if (!(config = whine_malloc(sizeof(struct dhcp_config))))
 		continue;
+	      config->src_index = SRC_CONFIG;
 	      config->flags = CONFIG_FROM_ETHERS;
 	      config->hwaddr = NULL;
 	      config->domain = NULL;
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index f42acdb..ca5b7ac 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -716,6 +716,7 @@ struct hwaddr_config {
 };
 
 struct dhcp_config {
+  unsigned int src_index;
   unsigned int flags;
   int clid_len;          /* length of client identifier */
   unsigned char *clid;   /* clientid */
@@ -747,6 +748,7 @@ struct dhcp_config {
 #define CONFIG_WILDCARD       8192
 
 struct dhcp_opt {
+  unsigned int src_index;
   int opt, len, flags;
   union {
     int encap;
@@ -982,7 +984,7 @@ extern struct daemon {
   int doing_ra, doing_dhcp6;
   struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names; 
   struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
-  struct hostsfile *dhcp_hosts_file, *dhcp_opts_file, *dynamic_dirs;
+  struct hostsfile *dhcp_hosts_file, *dhcp_opts_file, *dynamic_dirs, *dynamic_files;
   int dhcp_max, tftp_max;
   int dhcp_server_port, dhcp_client_port;
   int start_tftp_port, end_tftp_port; 
@@ -1092,6 +1094,7 @@ char *cache_get_cname_target(struct crec *crecp);
 struct crec *cache_enumerate(int init);
 int read_hostsfile(char *filename, unsigned int index, int cache_size, 
 		   struct crec **rhash, int hashsz);
+void flush_hostsfile(char *filename, unsigned int index);
 
 /* blockdata.c */
 #ifdef HAVE_DNSSEC
@@ -1222,10 +1225,12 @@ void reread_dhcp(void);
 void read_servers_file(void);
 void set_option_bool(unsigned int opt);
 void reset_option_bool(unsigned int opt);
+unsigned int max_source_index();
 struct hostsfile *expand_filelist(struct hostsfile *list);
 char *parse_server(char *arg, union mysockaddr *addr, 
 		   union mysockaddr *source_addr, char *interface, int *flags);
-int option_read_dynfile(char *file, int flags);
+int option_read_dynfile(struct hostsfile *df);
+void option_flush_dynfile(struct hostsfile *df);
 
 /* forward.c */
 void reply_query(int fd, int family, time_t now);
diff --git a/src/inotify.c b/src/inotify.c
index ef05c58..9f3a31d 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -135,7 +135,25 @@ void inotify_dnsmasq_init()
 void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz)
 {
   struct hostsfile *ah;
+  unsigned int index = max_source_index();
   
+  /* discard dynamic files loaded before */
+  while ((ah = daemon->dynamic_files))
+    {
+      if (ah->flags & AH_HOSTS)
+	flush_hostsfile(ah->fname, ah->index);
+#ifdef HAVE_DHCP
+      else if (ah->flags & (AH_DHCP_HST | AH_DHCP_OPT))
+	option_flush_dynfile(ah);
+#endif
+
+      daemon->dynamic_files = ah->next;
+
+      free(ah->fname);
+      free(ah);
+    }
+
+  /* (re)set inotify and load existing dynamic files */
   for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
     {
       DIR *dir_stream = NULL;
@@ -154,7 +172,7 @@ void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revh
       
        if (!(ah->flags & AH_WD_DONE))
 	 {
-	   ah->wd = inotify_add_watch(daemon->inotifyfd, ah->fname, IN_CLOSE_WRITE | IN_MOVED_TO);
+	   ah->wd = inotify_add_watch(daemon->inotifyfd, ah->fname, IN_CLOSE_WRITE | IN_MOVED_TO | IN_DELETE | IN_MOVED_FROM);
 	   ah->flags |= AH_WD_DONE;
 	 }
 
@@ -171,7 +189,7 @@ void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revh
 	 {
 	   size_t lendir = strlen(ah->fname);
 	   size_t lenfile = strlen(ent->d_name);
-	   char *path;
+	   struct hostsfile *new;
 	   
 	   /* ignore emacs backups and dotfiles */
 	   if (lenfile == 0 || 
@@ -180,25 +198,41 @@ void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revh
 	       ent->d_name[0] == '.')
 	     continue;
 	   
-	   if ((path = whine_malloc(lendir + lenfile + 2)))
+	   if (!(new = whine_malloc(sizeof(struct hostsfile))))
+	     continue;
+
+	   if ((new->fname = whine_malloc(lendir + lenfile + 2)))
 	     {
-	       strcpy(path, ah->fname);
-	       strcat(path, "/");
-	       strcat(path, ent->d_name);
+	       sprintf(new->fname, "%s/%s", ah->fname, ent->d_name);
+	       new->index = ++index;
+	       new->wd    = -1;
+	       new->flags = (ah->flags & (AH_HOSTS
+#ifdef HAVE_DHCP
+		                          | AH_DHCP_HST | AH_DHCP_OPT
+#endif
+		             ));
 	       
 	       /* ignore non-regular files */
-	       if (stat(path, &buf) != -1 && S_ISREG(buf.st_mode))
+	       if (new->flags != 0 && stat(new->fname, &buf) != -1 && S_ISREG(buf.st_mode))
 		 {
-		   if (ah->flags & AH_HOSTS)
-		     total_size = read_hostsfile(path, ah->index, total_size, rhash, revhashsz);
+		   new->next = daemon->dynamic_files;
+		   daemon->dynamic_files = new;
+
+		   if (new->flags & AH_HOSTS)
+		     total_size = read_hostsfile(new->fname, new->index, total_size, rhash, revhashsz);
 #ifdef HAVE_DHCP
-		   else if (ah->flags & (AH_DHCP_HST | AH_DHCP_OPT))
-		     option_read_dynfile(path, ah->flags);
+		   else if (new->flags & (AH_DHCP_HST | AH_DHCP_OPT))
+		     option_read_dynfile(new);
 #endif		   
 		 }
-
-	       free(path);
+	       else
+	         {
+		   free(new->fname);
+		   free(new);
+		 }
 	     }
+	   else
+	     free(new);
 	 }
     }
 }
@@ -207,6 +241,7 @@ int inotify_check(time_t now)
 {
   int hit = 0;
   struct hostsfile *ah;
+  struct hostsfile *df, **dfup;
 
   while (1)
     {
@@ -243,43 +278,129 @@ int inotify_check(time_t now)
 		
 		if ((path = whine_malloc(lendir + in->len + 2)))
 		  {
-		    strcpy(path, ah->fname);
-		    strcat(path, "/");
-		    strcat(path, in->name);
-		     
-		    my_syslog(LOG_INFO, _("inotify, new or changed file %s"), path);
+		    sprintf(path, "%s/%s", ah->fname, in->name);
+
+		    dfup = &daemon->dynamic_files;
+		    df = daemon->dynamic_files;
+		    while (df && 
+			   (strcmp(path, df->fname) != 0 ||
+			   (ah->flags & df->flags) == 0))
+		      {
+			dfup = &df->next;
+		        df = df->next;
+		      }
 
-		    if (ah->flags & AH_HOSTS)
+		    if (!(in->mask & (IN_DELETE | IN_MOVED_FROM)))
 		      {
-			read_hostsfile(path, ah->index, 0, NULL, 0);
+			if (df)
+			  {
+			    my_syslog(LOG_INFO, _("inotify, changed file %s"), path);
+			    free (path);
+
+			    /* discard dynamic content loaded before */
+			    if (df->flags & AH_HOSTS)
+			      flush_hostsfile(df->fname, df->index);
 #ifdef HAVE_DHCP
-			if (daemon->dhcp || daemon->doing_dhcp6) 
+			    else if (df->flags & (AH_DHCP_HST | AH_DHCP_OPT))
+			      option_flush_dynfile(df);
+#endif
+			  }
+			else
 			  {
-			    /* Propogate the consequences of loading a new dhcp-host */
-			    dhcp_update_configs(daemon->dhcp_conf);
-			    lease_update_from_configs(); 
-			    lease_update_file(now); 
-			    lease_update_dns(1);
+			    my_syslog(LOG_INFO, _("inotify, new file %s"), path);
+
+			    if (!(df = whine_malloc(sizeof(struct hostsfile))))
+			      {
+				free(path);
+			        continue;
+			      }
+
+			    df->fname = path;
+			    df->index = max_source_index() + 1;
+			    df->wd    = -1;
+			    df->flags = (ah->flags & (AH_HOSTS
+#ifdef HAVE_DHCP
+				  | AH_DHCP_HST | AH_DHCP_OPT
+#endif
+		             ));
+
+			    df->next = daemon->dynamic_files;
+			    daemon->dynamic_files = df;
 			  }
+
+			if (ah->flags & AH_HOSTS)
+			  {
+			    read_hostsfile(df->fname, df->index, 0, NULL, 0);
+#ifdef HAVE_DHCP
+			    if (daemon->dhcp || daemon->doing_dhcp6) 
+			      {
+				/* Propogate the consequences of loading a new dhcp-host */
+				dhcp_update_configs(daemon->dhcp_conf);
+				lease_update_from_configs(); 
+				lease_update_file(now); 
+				lease_update_dns(1);
+			      }
 #endif
-		      }
+			  }
 #ifdef HAVE_DHCP
-		    else if (ah->flags & AH_DHCP_HST)
+			else if (ah->flags & AH_DHCP_HST)
+			  {
+			    if (option_read_dynfile(df))
+			      {
+				/* Propogate the consequences of loading a new dhcp-host */
+				dhcp_update_configs(daemon->dhcp_conf);
+				lease_update_from_configs(); 
+				lease_update_file(now); 
+				lease_update_dns(1);
+			      }
+			  }
+			else if (ah->flags & AH_DHCP_OPT)
+			  option_read_dynfile(df);
+#endif
+		      }
+		    else
 		      {
-			if (option_read_dynfile(path, AH_DHCP_HST))
+			my_syslog(LOG_INFO, _("inotify, deleted file %s"), path);
+
+			free(path);
+
+			if (!df)
+			  continue;
+
+			if (df->flags & AH_HOSTS)
 			  {
+			    flush_hostsfile(df->fname, df->index);
+#ifdef HAVE_DHCP
+			    if (daemon->dhcp || daemon->doing_dhcp6) 
+			      {
+				/* Propogate the consequences of loading a new dhcp-host */
+				dhcp_update_configs(daemon->dhcp_conf);
+				lease_update_from_configs(); 
+				lease_update_file(now); 
+				lease_update_dns(1);
+			      }
+#endif
+			  }
+#ifdef HAVE_DHCP
+			else if (df->flags & AH_DHCP_HST)
+			  {
+			    option_flush_dynfile(df);
+
 			    /* Propogate the consequences of loading a new dhcp-host */
 			    dhcp_update_configs(daemon->dhcp_conf);
 			    lease_update_from_configs(); 
 			    lease_update_file(now); 
 			    lease_update_dns(1);
 			  }
-		      }
-		    else if (ah->flags & AH_DHCP_OPT)
-		      option_read_dynfile(path, AH_DHCP_OPT);
+			else if (df->flags & AH_DHCP_OPT)
+			  option_flush_dynfile(df);
 #endif
-		    
-		    free(path);
+
+			/* Remove dynamic file */
+			*dfup = df->next;
+			free(df->fname);
+			free(df);
+		      }
 		  }
 	      }
 	}
diff --git a/src/option.c b/src/option.c
index 71beb98..ce22f12 100644
--- a/src/option.c
+++ b/src/option.c
@@ -21,7 +21,7 @@
 
 static volatile int mem_recover = 0;
 static jmp_buf mem_jmp;
-static int one_file(char *file, int hard_opt);
+static int one_file(char *file, unsigned int index, int hard_opt);
 
 /* Solaris headers don't have facility names. */
 #ifdef HAVE_SOLARIS_NETWORK
@@ -897,7 +897,7 @@ static char *set_prefix(char *arg)
 }
 
 /* This is too insanely large to keep in-line in the switch */
-static int parse_dhcp_opt(char *errstr, char *arg, int flags)
+static int parse_dhcp_opt(unsigned int src_index, char *errstr, char *arg, int flags)
 {
   struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
   char lenchar = 0, *cp;
@@ -908,6 +908,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
   int is6 = 0;
   int option_ok = 0;
 
+  new->src_index = src_index;
   new->len = 0;
   new->flags = flags;
   new->netid = NULL;
@@ -1441,7 +1442,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, int servers_only)
+static int one_opt(int option, char *arg, char *errstr, char *gen_err, int command_line, int servers_only, unsigned int src_index)
 {      
   int i;
   char *comma;
@@ -1487,7 +1488,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
 	char *file = opt_string_alloc(arg);
 	if (file)
 	  {
-	    one_file(file, 0);
+	    one_file(file, SRC_CONFIG, 0);
 	    free(file);
 	  }
 	break;
@@ -1587,7 +1588,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
 	    
 	    /* only reg files allowed. */
 	    if (S_ISREG(buf.st_mode))
-	      one_file(path, 0);
+	      one_file(path, SRC_CONFIG, 0);
 	    
 	    free(path);
 	  }
@@ -1787,9 +1788,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
     case 'H':                /* --addn-hosts */
       {
 	struct hostsfile *new = opt_malloc(sizeof(struct hostsfile));
-	static unsigned int hosts_index = SRC_AH;
 	new->fname = opt_string_alloc(arg);
-	new->index = hosts_index++;
+	new->index = max_source_index() + 1;
 	new->flags = 0;
 	if (option == 'H')
 	  {
@@ -2881,6 +2881,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
 	new = opt_malloc(sizeof(struct dhcp_config));
 	
 	new->next = daemon->dhcp_conf;
+	new->src_index = src_index;
 	new->flags = (option == LOPT_BANK) ? CONFIG_BANK : 0;
 	new->hwaddr = NULL;
 	new->netid = NULL;
@@ -3135,7 +3136,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
     case LOPT_FORCE:    /* --dhcp-option-force */
     case LOPT_OPTS:
     case LOPT_MATCH:    /* --dhcp-match */
-      return parse_dhcp_opt(errstr, arg, 
+      return parse_dhcp_opt(src_index, errstr, arg, 
 			    option == LOPT_FORCE ? DHOPT_FORCE : 
 			    (option == LOPT_MATCH ? DHOPT_MATCH :
 			     (option == LOPT_OPTS ? DHOPT_BANK : 0)));
@@ -3203,6 +3204,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
 	 struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
 	 int timeout;
 
+	 new->src_index = src_index;
 	 new->netid = NULL;
 	 new->opt = 10; /* PXE_MENU_PROMPT */
 
@@ -3994,7 +3996,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
   return 1;
 }
 
-static void read_file(char *file, FILE *f, int hard_opt)	
+static void read_file(char *file, unsigned int index, FILE *f, int hard_opt)	
 {
   volatile int lineno = 0;
   char *buff = daemon->namebuff;
@@ -4116,7 +4118,7 @@ static void read_file(char *file, FILE *f, int hard_opt)
       if (errmess)
 	strcpy(daemon->namebuff, errmess);
 	  
-      if (errmess || !one_opt(option, arg, buff, _("error"), 0, hard_opt == LOPT_REV_SERV))
+      if (errmess || !one_opt(option, arg, buff, _("error"), 0, hard_opt == LOPT_REV_SERV, index))
 	{
 	  sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
 	  if (hard_opt != 0)
@@ -4131,20 +4133,116 @@ static void read_file(char *file, FILE *f, int hard_opt)
 }
 
 #ifdef HAVE_DHCP
-int option_read_dynfile(char *file, int flags)
+int option_read_dynfile(struct hostsfile *df)
 {
-  my_syslog(MS_DHCP | LOG_INFO, _("read %s"), file);
+  my_syslog(MS_DHCP | LOG_INFO, _("read %s"), df->fname);
   
-  if (flags & AH_DHCP_HST)
-    return one_file(file, LOPT_BANK);
-  else if (flags & AH_DHCP_OPT)
-    return one_file(file, LOPT_OPTS);
+  if (df->flags & AH_DHCP_HST)
+    return one_file(df->fname, df->index, LOPT_BANK);
+  else if (df->flags & AH_DHCP_OPT)
+    return one_file(df->fname, df->index, LOPT_OPTS);
   
   return 0;
 }
+
+void option_flush_dynfile(struct hostsfile *df)
+{
+  my_syslog(MS_DHCP | LOG_INFO, _("flush config read from %s"), df->fname);
+
+  if (df->flags & AH_DHCP_HST)
+    {
+      struct dhcp_config *configs, *cp, **up;
+
+      for (up = &daemon->dhcp_conf, configs = daemon->dhcp_conf; configs; configs = cp)
+	{
+	  cp = configs->next;
+
+	  if ((configs->flags & CONFIG_BANK) && configs->src_index == df->index)
+	    {
+	      struct hwaddr_config *mac, *tmp;
+	      struct dhcp_netid_list *list, *tmplist;
+
+	      for (mac = configs->hwaddr; mac; mac = tmp)
+		{
+		  tmp = mac->next;
+		  free(mac);
+		}
+
+	      if (configs->flags & CONFIG_CLID)
+		free(configs->clid);
+
+	      for (list = configs->netid; list; list = tmplist)
+		{
+		  free(list->list);
+		  tmplist = list->next;
+		  free(list);
+		}
+
+	      if (configs->flags & CONFIG_NAME)
+		free(configs->hostname);
+
+	      *up = configs->next;
+	      free(configs);
+	    }
+	  else
+	    up = &configs->next;
+	}
+    }
+  else if (df->flags & AH_DHCP_OPT)
+    {
+      struct dhcp_opt *opts, *cp, **up;
+      struct dhcp_netid *id, *next;
+
+      for (up = &daemon->dhcp_opts, opts = daemon->dhcp_opts; opts; opts = cp)
+	{
+	  cp = opts->next;
+
+	  if ((opts->flags & DHOPT_BANK) && opts->src_index == df->index)
+	    {
+	      if ((opts->flags & DHOPT_VENDOR))
+		free(opts->u.vendor_class);
+	      free(opts->val);
+	      for (id = opts->netid; id; id = next)
+		{
+		  next = id->next;
+		  free(id->net);
+		  free(id);
+		}
+	      *up = opts->next;
+	      free(opts);
+	    }
+	  else
+	    up = &opts->next;
+	}
+
+#ifdef HAVE_DHCP6
+      for (up = &daemon->dhcp_opts6, opts = daemon->dhcp_opts6; opts; opts = cp)
+	{
+	  cp = opts->next;
+
+	  if ((opts->flags & DHOPT_BANK) && opts->src_index == df->index)
+	    {
+	      if ((opts->flags & DHOPT_VENDOR))
+		free(opts->u.vendor_class);
+	      free(opts->val);
+	      for (id = opts->netid; id; id = next)
+		{
+		  next = id->next;
+		  free(id->net);
+		  free(id);
+		}
+	      *up = opts->next;
+	      free(opts);
+	    }
+	  else
+	    up = &opts->next;
+	}
+#endif
+    }
+}
 #endif
 
-static int one_file(char *file, int hard_opt)
+static int one_file(char *file, unsigned int index, int hard_opt)
 {
   FILE *f;
   int nofile_ok = 0;
@@ -4208,22 +4306,38 @@ static int one_file(char *file, int hard_opt)
 	} 
     }
   
-  read_file(file, f, hard_opt);
+  read_file(file, index, f, hard_opt);
   return 1;
 }
 
+/* find laged used index */
+unsigned int max_source_index()
+{
+  unsigned int ret = SRC_HOSTS;
+
+  if (daemon->addn_hosts && daemon->addn_hosts->index > ret)
+    ret = daemon->addn_hosts->index;
+
+  if (daemon->dhcp_hosts_file && daemon->dhcp_hosts_file->index > ret)
+    ret = daemon->dhcp_hosts_file->index;
+  if (daemon->dhcp_opts_file && daemon->dhcp_opts_file->index > ret)
+    ret = daemon->dhcp_opts_file->index;
+  if (daemon->dynamic_dirs && daemon->dynamic_dirs->index > ret)
+    ret = daemon->dynamic_dirs->index;
+  if (daemon->dynamic_files && daemon->dynamic_files->index > ret)
+    ret = daemon->dynamic_files->index;
+
+  return ret;
+}
+
 /* expand any name which is a directory */
 struct hostsfile *expand_filelist(struct hostsfile *list)
 {
-  unsigned int i;
+  unsigned int i = max_source_index() + 1;
   struct hostsfile *ah;
 
-  /* find largest used index */
-  for (i = SRC_AH, ah = list; ah; ah = ah->next)
+  for (ah = list; ah; ah = ah->next)
     {
-      if (i <= ah->index)
-	i = ah->index + 1;
-
       if (ah->flags & AH_DIR)
 	ah->flags |= AH_INACTIVE;
       else
@@ -4326,11 +4440,12 @@ void read_servers_file(void)
   mark_servers(SERV_FROM_FILE);
   cleanup_servers();
   
-  read_file(daemon->servers_file, f, LOPT_REV_SERV);
+  read_file(daemon->servers_file, SRC_CONFIG, f, LOPT_REV_SERV);
 }
  
 
 #ifdef HAVE_DHCP
+
 void reread_dhcp(void)
 {
   struct hostsfile *hf;
@@ -4379,7 +4494,7 @@ void reread_dhcp(void)
       for (hf = daemon->dhcp_hosts_file; hf; hf = hf->next)
 	 if (!(hf->flags & AH_INACTIVE))
 	   {
-	     if (one_file(hf->fname, LOPT_BANK))  
+	     if (one_file(hf->fname, hf->index, LOPT_BANK))  
 	       my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
 	   }
     }
@@ -4411,11 +4526,35 @@ void reread_dhcp(void)
 	    up = &opts->next;
 	}
       
+#ifdef HAVE_DHCP6
+      for (up = &daemon->dhcp_opts6, opts = daemon->dhcp_opts6; opts; opts = cp)
+	{
+	  cp = opts->next;
+
+	  if (opts->flags & DHOPT_BANK)
+	    {
+	      if ((opts->flags & DHOPT_VENDOR))
+		free(opts->u.vendor_class);
+	      free(opts->val);
+	      for (id = opts->netid; id; id = next)
+		{
+		  next = id->next;
+		  free(id->net);
+		  free(id);
+		}
+	      *up = opts->next;
+	      free(opts);
+	    }
+	  else
+	    up = &opts->next;
+	}
+#endif
+
       daemon->dhcp_opts_file = expand_filelist(daemon->dhcp_opts_file);
       for (hf = daemon->dhcp_opts_file; hf; hf = hf->next)
 	if (!(hf->flags & AH_INACTIVE))
 	  {
-	    if (one_file(hf->fname, LOPT_OPTS))  
+	    if (one_file(hf->fname, hf->index, LOPT_OPTS))  
 	      my_syslog(MS_DHCP | LOG_INFO, _("read %s"), hf->fname);
 	  }
     }
@@ -4532,9 +4671,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, 0))
+	  if (!one_opt(option, arg, daemon->namebuff, _("try --help"), 1, 0, SRC_CONFIG))
 #else 
-	    if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1, 0)) 
+	    if (!one_opt(option, arg, daemon->namebuff, _("try -w"), 1, 0, SRC_CONFIG)) 
 #endif  
 	    die(_("bad command line options: %s"), daemon->namebuff, EC_BADCONF);
 	}
@@ -4542,7 +4681,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
 
   if (conffile)
     {
-      one_file(conffile, conffile_opt);
+      one_file(conffile, SRC_CONFIG, conffile_opt);
       if (conffile_opt == 0)
 	free(conffile);
     }
diff --git a/src/rfc2131.c b/src/rfc2131.c
index 9f69ed5..2d57ec4 100644
--- a/src/rfc2131.c
+++ b/src/rfc2131.c
@@ -2001,6 +2001,7 @@ static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct
 
   for (i = 0; i < NUM_OPTS; i++)
     {
+      fake_opts[i].src_index = SRC_CONFIG;
       fake_opts[i].flags = DHOPT_VENDOR_MATCH;
       fake_opts[i].netid = NULL;
       fake_opts[i].next = i == (NUM_OPTS - 1) ? ret : &fake_opts[i+1];
-- 
1.7.12.4




More information about the Dnsmasq-discuss mailing list