Alin Nastac
2015-12-02 13:50:39 UTC
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];
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
1.7.12.4