summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominik Derigs <dl6er@dl6er.de>2022-10-16 21:08:30 +0100
committerSimon Kelley <simon@thekelleys.org.uk>2022-10-16 21:14:16 +0100
commit0ba25a05122e86e14c3b00e54fa76ea9421eeeab (patch)
tree7fb034865309b7b9362867407157aab7b86b047b
parenta176cf1bc32727b438b2c1d9f6f1e4cb868c2f6f (diff)
downloaddnsmasq-0ba25a05122e86e14c3b00e54fa76ea9421eeeab.tar.gz
Improve logging of DNS record source from --hostsdir files.
Patch author Dominik Derigs <dl6er@dl6er.de> with subsequent bugfixes and tweaks from Simon Kelley.
-rw-r--r--src/cache.c9
-rw-r--r--src/dnsmasq.h13
-rw-r--r--src/inotify.c123
-rw-r--r--src/option.c39
4 files changed, 119 insertions, 65 deletions
diff --git a/src/cache.c b/src/cache.c
index 4ca04fd..6da742c 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -1861,6 +1861,7 @@ void dump_cache(time_t now)
char *record_source(unsigned int index)
{
struct hostsfile *ah;
+ struct dyndir *dd;
if (index == SRC_CONFIG)
return "config";
@@ -1872,9 +1873,11 @@ char *record_source(unsigned int index)
return ah->fname;
#ifdef HAVE_INOTIFY
- for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
- if (ah->index == index)
- return ah->fname;
+ /* Dynamic directories contain multiple files */
+ for (dd = daemon->dynamic_dirs; dd; dd = dd->next)
+ for (ah = dd->files; ah; ah = ah->next)
+ if (ah->index == index)
+ return ah->fname;
#endif
return "<unknown>";
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 1835a11..f1dc4a9 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -687,10 +687,17 @@ struct hostsfile {
struct hostsfile *next;
int flags;
char *fname;
+ unsigned int index; /* matches to cache entries for logging */
+};
+
+struct dyndir {
+ struct dyndir *next;
+ struct hostsfile *files;
+ int flags;
+ char *dname;
#ifdef HAVE_INOTIFY
int wd; /* inotify watch descriptor */
#endif
- unsigned int index; /* matches to cache entries for logging */
};
/* packet-dump flags */
@@ -1152,6 +1159,7 @@ extern struct daemon {
u32 umbrella_org;
u32 umbrella_asset;
u8 umbrella_device[8];
+ int host_index;
struct hostsfile *addn_hosts;
struct dhcp_context *dhcp, *dhcp6;
struct ra_interface *ra_interfaces;
@@ -1172,7 +1180,8 @@ 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;
+ struct dyndir *dynamic_dirs;
int dhcp_max, tftp_max, tftp_mtu;
int dhcp_server_port, dhcp_client_port;
int start_tftp_port, end_tftp_port;
diff --git a/src/inotify.c b/src/inotify.c
index 5687e37..6e1ba18 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -133,81 +133,112 @@ void inotify_dnsmasq_init()
}
}
+static struct hostsfile *dyndir_addhosts(struct dyndir *dd, char *path)
+{
+ /* Check if this file is already known in dd->files */
+ struct hostsfile *ah = NULL;
+ for(ah = dd->files; ah; ah = ah->next)
+ if(ah && ah->fname && strcmp(path, ah->fname) == 0)
+ return ah;
+
+ /* Not known, create new hostsfile record for this dyndir */
+ struct hostsfile *newah = NULL;
+ if(!(newah = whine_malloc(sizeof(struct hostsfile))))
+ return NULL;
+
+ /* Add this file to the tip of the linked list */
+ newah->next = dd->files;
+ dd->files = newah;
+
+ /* Copy flags, set index and the full file path */
+ newah->flags = dd->flags;
+ newah->index = daemon->host_index++;
+ newah->fname = path;
+
+ return newah;
+}
+
/* initialisation for dynamic-dir. Set inotify watch for each directory, and read pre-existing files */
void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz)
{
- struct hostsfile *ah;
-
- for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
+ struct dyndir *dd;
+
+ for (dd = daemon->dynamic_dirs; dd; dd = dd->next)
{
DIR *dir_stream = NULL;
struct dirent *ent;
struct stat buf;
-
- if (!(ah->flags & flag))
+
+ if (!(dd->flags & flag))
continue;
-
- if (stat(ah->fname, &buf) == -1)
+
+ if (stat(dd->dname, &buf) == -1)
{
my_syslog(LOG_ERR, _("bad dynamic directory %s: %s"),
- ah->fname, strerror(errno));
+ dd->dname, strerror(errno));
continue;
}
if (!(S_ISDIR(buf.st_mode)))
{
my_syslog(LOG_ERR, _("bad dynamic directory %s: %s"),
- ah->fname, _("not a directory"));
+ dd->dname, _("not a directory"));
continue;
}
-
- if (!(ah->flags & AH_WD_DONE))
+
+ if (!(dd->flags & AH_WD_DONE))
{
- ah->wd = inotify_add_watch(daemon->inotifyfd, ah->fname, IN_CLOSE_WRITE | IN_MOVED_TO);
- ah->flags |= AH_WD_DONE;
+ dd->wd = inotify_add_watch(daemon->inotifyfd, dd->dname, IN_CLOSE_WRITE | IN_MOVED_TO | IN_DELETE);
+ dd->flags |= AH_WD_DONE;
}
/* Read contents of dir _after_ calling add_watch, in the hope of avoiding
a race which misses files being added as we start */
- if (ah->wd == -1 || !(dir_stream = opendir(ah->fname)))
+ if (dd->wd == -1 || !(dir_stream = opendir(dd->dname)))
{
my_syslog(LOG_ERR, _("failed to create inotify for %s: %s"),
- ah->fname, strerror(errno));
+ dd->dname, strerror(errno));
continue;
}
while ((ent = readdir(dir_stream)))
{
- size_t lendir = strlen(ah->fname);
+ size_t lendir = strlen(dd->dname);
size_t lenfile = strlen(ent->d_name);
char *path;
-
+
/* ignore emacs backups and dotfiles */
if (lenfile == 0 ||
ent->d_name[lenfile - 1] == '~' ||
(ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
ent->d_name[0] == '.')
continue;
-
+
if ((path = whine_malloc(lendir + lenfile + 2)))
{
- strcpy(path, ah->fname);
+ struct hostsfile *ah;
+
+ strcpy(path, dd->dname);
strcat(path, "/");
strcat(path, ent->d_name);
+
+ if (!(ah = dyndir_addhosts(dd, path)))
+ {
+ free(path);
+ continue;
+ }
/* ignore non-regular files */
if (stat(path, &buf) != -1 && S_ISREG(buf.st_mode))
{
- if (ah->flags & AH_HOSTS)
+ if (dd->flags & AH_HOSTS)
total_size = read_hostsfile(path, ah->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 (dd->flags & (AH_DHCP_HST | AH_DHCP_OPT))
+ option_read_dynfile(path, dd->flags);
#endif
}
-
- free(path);
}
}
@@ -218,7 +249,7 @@ void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revh
int inotify_check(time_t now)
{
int hit = 0;
- struct hostsfile *ah;
+ struct dyndir *dd;
while (1)
{
@@ -249,36 +280,41 @@ int inotify_check(time_t now)
if (res->wd == in->wd && strcmp(res->file, in->name) == 0)
hit = 1;
- for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
- if (ah->wd == in->wd)
+ for (dd = daemon->dynamic_dirs; dd; dd = dd->next)
+ if (dd->wd == in->wd)
{
- size_t lendir = strlen(ah->fname);
+ size_t lendir = strlen(dd->dname);
char *path;
-
+
if ((path = whine_malloc(lendir + in->len + 2)))
{
- strcpy(path, ah->fname);
+ struct hostsfile *ah = NULL;
+
+ strcpy(path, dd->dname);
strcat(path, "/");
strcat(path, in->name);
my_syslog(LOG_INFO, _("inotify, new or changed file %s"), path);
- if (ah->flags & AH_HOSTS)
+ if (dd->flags & AH_HOSTS)
{
- read_hostsfile(path, ah->index, 0, NULL, 0);
-#ifdef HAVE_DHCP
- if (daemon->dhcp || daemon->doing_dhcp6)
+ if ((ah = dyndir_addhosts(dd, path)))
{
- /* Propagate 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);
- }
+ read_hostsfile(path, ah->index, 0, NULL, 0);
+#ifdef HAVE_DHCP
+ if (daemon->dhcp || daemon->doing_dhcp6)
+ {
+ /* Propagate 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 (dd->flags & AH_DHCP_HST)
{
if (option_read_dynfile(path, AH_DHCP_HST))
{
@@ -289,11 +325,12 @@ int inotify_check(time_t now)
lease_update_dns(1);
}
}
- else if (ah->flags & AH_DHCP_OPT)
+ else if (dd->flags & AH_DHCP_OPT)
option_read_dynfile(path, AH_DHCP_OPT);
#endif
- free(path);
+ if (!ah)
+ free(path);
}
}
}
diff --git a/src/option.c b/src/option.c
index f2110cf..4b76dc9 100644
--- a/src/option.c
+++ b/src/option.c
@@ -2162,15 +2162,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
case LOPT_DHCP_HOST: /* --dhcp-hostsfile */
case LOPT_DHCP_OPTS: /* --dhcp-optsfile */
- case LOPT_DHCP_INOTIFY: /* --dhcp-hostsdir */
- case LOPT_DHOPT_INOTIFY: /* --dhcp-optsdir */
- case LOPT_HOST_INOTIFY: /* --hostsdir */
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 = daemon->host_index++;
new->flags = 0;
if (option == 'H')
{
@@ -2186,21 +2182,29 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
{
new->next = daemon->dhcp_opts_file;
daemon->dhcp_opts_file = new;
- }
- else
- {
- new->next = daemon->dynamic_dirs;
- daemon->dynamic_dirs = new;
- if (option == LOPT_DHCP_INOTIFY)
- new->flags |= AH_DHCP_HST;
- else if (option == LOPT_DHOPT_INOTIFY)
- new->flags |= AH_DHCP_OPT;
- else if (option == LOPT_HOST_INOTIFY)
- new->flags |= AH_HOSTS;
}
break;
}
+
+ case LOPT_DHCP_INOTIFY: /* --dhcp-hostsdir */
+ case LOPT_DHOPT_INOTIFY: /* --dhcp-optsdir */
+ case LOPT_HOST_INOTIFY: /* --hostsdir */
+ {
+ struct dyndir *new = opt_malloc(sizeof(struct dyndir));
+ new->dname = opt_string_alloc(arg);
+ new->flags = 0;
+ new->next = daemon->dynamic_dirs;
+ daemon->dynamic_dirs = new;
+ if (option == LOPT_DHCP_INOTIFY)
+ new->flags |= AH_DHCP_HST;
+ else if (option == LOPT_DHOPT_INOTIFY)
+ new->flags |= AH_DHCP_OPT;
+ else if (option == LOPT_HOST_INOTIFY)
+ new->flags |= AH_HOSTS;
+
+ break;
+ }
case LOPT_AUTHSERV: /* --auth-server */
comma = split(arg);
@@ -5532,7 +5536,8 @@ void read_opts(int argc, char **argv, char *compile_opts)
daemon->soa_retry = SOA_RETRY;
daemon->soa_expiry = SOA_EXPIRY;
daemon->randport_limit = 1;
-
+ daemon->host_index = SRC_AH;
+
#ifndef NO_ID
add_txt("version.bind", "dnsmasq-" VERSION, 0 );
add_txt("authors.bind", "Simon Kelley", 0);