Discussion:
[Dnsmasq-discuss] [PATCH] Flush dynamic configuration on reload and discard DHCPv6 options on SIGHUP
Alin Nastac
2015-12-02 13:50:39 UTC
Permalink
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
Simon Kelley
2015-12-15 23:20:15 UTC
Permalink
Apologies for ignoring this 'till now. I'm in heavy coding mode now,
and plan to take a look at this in the next day or two.


Cheers,

Simon.
Post by Alin Nastac
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
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,
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
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
struct hwaddr_config { };
struct dhcp_config { + unsigned int src_index; unsigned int
flags; int clid_len; /* length of client identifier */
dhcp_config { #define CONFIG_WILDCARD 8192
struct dhcp_opt { + unsigned int src_index; int opt, len, flags;
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,
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);
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
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
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); +
hostsfile *ah; + struct hostsfile *df, **dfup;
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
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
*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 =
int flags) int is6 = 0; int option_ok = 0;
+ new->src_index = src_index; new->len = 0; new->flags = flags;
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 *arg, char *errstr, char *gen_err, int comma char *file =
opt_string_alloc(arg); if (file) { - one_file(file, 0); +
char *gen_err, int comma /* only reg files allowed. */ if
(S_ISREG(buf.st_mode)) - one_file(path, 0); +
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 =
*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;
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 ==
*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 =
*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
*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;
*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)
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 |
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 |
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"),
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 +++
*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];
Loading...