[Git][NTPsec/ntpsec][master] 2 commits: Genericize lex_open - first step towards config directory.
Eric S. Raymond
gitlab at mg.gitlab.com
Fri Mar 24 11:30:46 UTC 2017
Eric S. Raymond pushed to branch master at NTPsec / ntpsec
Commits:
aa6ada8a by Eric S. Raymond at 2017-03-24T07:30:15-04:00
Genericize lex_open - first step towards config directory.
- - - - -
edc696bd by Eric S. Raymond at 2017-03-24T07:30:15-04:00
Address GitLab issue #204: Support /etc/ntp.d
Implementation ad documentation.
- - - - -
9 changed files:
- devel/TODO
- devel/hacking.txt
- docs/includes/ntpd-body.txt
- docs/ntpsec.txt
- include/ntp_config.h
- ntpd/ntp_config.c
- ntpd/ntp_parser.y
- ntpd/ntp_scanner.c
- ntpd/ntp_scanner.h
Changes:
=====================================
devel/TODO
=====================================
--- a/devel/TODO
+++ b/devel/TODO
@@ -4,8 +4,6 @@
* Units as an option in ntpq/ntpmon.
-* Easier assembly of config file snippets - ntpconf.d.
-
* Package metadata for Debian, Ubuntu, Raspbian, Red Hat, Gentoo, and SuSe.
* Add .tar.xz tarball.
=====================================
devel/hacking.txt
=====================================
--- a/devel/hacking.txt
+++ b/devel/hacking.txt
@@ -84,7 +84,10 @@ cause buffer overruns and (all too often) exploitable security holes:
* gets: Use fgets instead.
* gmtime(), localtime(), asctime(), ctime(): use the reentrant *_r variants.
* tmpnam() - use mkstemp() or tmpfile() instead.
-* dirname() - the Linux version is re-entrant but this property is not portable.
+
+Do not rely on dirname() being re-entrant, and assume it will modify
+(truncate) its argument. The Linux version is re-entrant, but this
+property is not portable.
In general, avoid functions that are non-reentrant. When in doubt, see
http://www.unix.org/whitepapers/reentrant.html[Thread-safety and POSIX.1]
@@ -120,8 +123,8 @@ continuity; you should, too.
A discussion about using uncrustify to mass convert all the C sources
to a more modern indentation and format style is ongoing. As it will
result in a coordinated flag day in ongoing development, it will be
-carefully announced in the mailto:devel at ntpsec.org mailing list before being merged and
-pushed.
+carefully announced in the mailto:devel at ntpsec.org mailing list before
+being merged and pushed.
=== Conventions for #ifdef guard names ===
=====================================
docs/includes/ntpd-body.txt
=====================================
--- a/docs/includes/ntpd-body.txt
+++ b/docs/includes/ntpd-body.txt
@@ -502,17 +502,38 @@ as described in {ntpdconfman}.
[options="header"]
|===================================================================
-|File |Default |Option |Option
-|configuration file |+/etc/{ntpconf}+ |+-c+ |+conffile+
-|frequency file |none |+-f+ |+driftfile+
-|leapseconds file |none | |+leapfile+
-|process ID file |none |+-p+ |+pidfile+
-|log file |system log |+-l+ |+logfile+
-|include file |none |none |+includefile+
-|statistics path |+/var/NTP+ |+-s+ |+statsdir+
-|keys file |none |+-k+ |+keys+
+|File |Default |Option |Option
+|configuration file |+/etc/{ntpconf}+ |+-c+ |+conffile+
+|configuration directory |+/etc/ntp.d+ |+-c+ |+conffile+
+|frequency file |none |+-f+ |+driftfile+
+|leapseconds file |none | |+leapfile+
+|process ID file |none |+-p+ |+pidfile+
+|log file |system log |+-l+ |+logfile+
+|include file |none |none |+includefile+
+|statistics path |+/var/NTP+ |+-s+ |+statsdir+
+|keys file |none |+-k+ |+keys+
|===================================================================
+Configuration files are parsed according to the following rules:
+
+. The plain config file (normally +/etc/{ntpconf}+ but the path can be
+ overridden by the -c option) is read first if it exists.
+
+. Then the configuration directory, if it exists, is scanned. Normally
+ this directory is /etc/ntp.d, but if the -c option is specified the
+ /etc will be specified by the directory name of the -c argument.
+
+. Each file beneath the configuration directory with either the
+ extension ".ntpd" or ".refclockd" is interpreted. Files are
+ interpreted in ASCII sort order of their pathnames. Files with
+ other extensions or no extensions are ignored.
+
+It is best practice to put refclock and clockstats declarations in a
+".refclockd" file and all other declarations in an ".ntpd" file. This
+anticipates a future direction of the architecture - it is intended
+that someday the refclock handling will be broken out of the main
+daemon into a separate executable with its own configuration parser.
+
[[signals]]
== SIGNALS ==
=====================================
docs/ntpsec.txt
=====================================
--- a/docs/ntpsec.txt
+++ b/docs/ntpsec.txt
@@ -214,6 +214,13 @@ codebase has been outright removed, with less than 5% new code added.
in /etc/ntp.conf finding /etc/foo rather than looking for foo in
your current directory.
+* If there is an /etc/ntp.d directory, its subfiles are scanned
+ for more configuration declarations. Only files with the extensions
+ ".ntpd" and ".refclockd" are interpreted; others are ignored. This
+ feature is intended to make assembling configuration easier for
+ administration and package-configuration scripts. See {ntpdman}
+ for details.
+
* It is now possible to set the peer maximum dispersion with "tos
maxdisp". See RFC 5905 for discussion of this synchronization
parameter.
=====================================
include/ntp_config.h
=====================================
--- a/include/ntp_config.h
+++ b/include/ntp_config.h
@@ -20,6 +20,7 @@
#ifndef CONFIG_FILE
# define CONFIG_FILE "/etc/ntp.conf"
#endif /* not CONFIG_FILE */
+#define CONFIG_DIR "ntp.d"
/* Limits */
#define MAXLINE 1024
=====================================
ntpd/ntp_config.c
=====================================
--- a/ntpd/ntp_config.c
+++ b/ntpd/ntp_config.c
@@ -3265,6 +3265,7 @@ getconfig(const char *explicit_config)
void readconfig(const char *config_file)
{
char line[256];
+ char dirpath[PATH_MAX];
/*
* install a non default variable with this daemon version
*/
@@ -3279,7 +3280,7 @@ void readconfig(const char *config_file)
&& check_netinfo && !(config_netinfo = get_netinfo_config())
#endif /* HAVE_NETINFO_NI_H */
) {
- msyslog(LOG_INFO, "getconfig: Couldn't open <%s>: %m", config_file);
+ msyslog(LOG_INFO, "readconfig: Couldn't open <%s>: %m", config_file);
io_open_sockets();
return;
@@ -3292,7 +3293,15 @@ void readconfig(const char *config_file)
#ifdef DEBUG
yydebug = !!(debug >= 5);
#endif
+
+ /* parse the plain config file if it exists */
yyparse();
+
+ /* parse configs in parallel subdirectory if that exists */
+ reparent(dirpath, sizeof(dirpath), config_file, CONFIG_DIR);
+ if (is_directory(dirpath) && lex_push_file(dirpath))
+ yyparse();
+
lex_drop_stack();
DPRINTF(1, ("Finished Parsing!!\n"));
=====================================
ntpd/ntp_parser.y
=====================================
--- a/ntpd/ntp_parser.y
+++ b/ntpd/ntp_parser.y
@@ -1135,7 +1135,7 @@ miscellaneous_command
msyslog(LOG_ERR, "getconfig: Maximum include file level exceeded.");
} else {
const char * path = $2;
- if (!lex_push_file(path, "r")) {
+ if (!lex_push_file(path)) {
fprintf(stderr, "getconfig: Couldn't open <%s>\n", path);
msyslog(LOG_ERR, "getconfig: Couldn't open <%s>", path);
}
=====================================
ntpd/ntp_scanner.c
=====================================
--- a/ntpd/ntp_scanner.c
+++ b/ntpd/ntp_scanner.c
@@ -20,6 +20,9 @@
#include <string.h>
#include <limits.h>
#include <libgen.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include "ntpd.h"
#include "ntp_config.h"
@@ -43,9 +46,10 @@ static struct FILE_INFO * lex_stack = NULL;
-/* CONSTANTS
- * ---------
+/* CONSTANTS AND MACROS
+ * --------------------
*/
+#define CONF_ENABLE(s) strcmp(s + strlen(s) - 5, ".ntpd") == 0
/* SCANNER GLOBAL VARIABLES
@@ -299,6 +303,7 @@ lex_init_stack(
if (NULL != lex_stack || NULL == path)
return false;
+ //fprintf(stderr, "lex_init_stack(%s)\n", path);
lex_stack = lex_open(path, mode);
return (NULL != lex_stack);
}
@@ -338,11 +343,45 @@ lex_flush_stack()
return retv;
}
+/* Reversed string comparison - we want to LIFO directory subfiles so they
+ * actually get evaluated in sort order.
+ */
+static int rcmpstring(const void *p1, const void *p2)
+{
+ return strcmp(*(const char **)p1, *(const char **)p2);
+}
+
+bool is_directory(const char *path)
+{
+ struct stat sb;
+ return stat(path, &sb) == 0 && S_ISDIR(sb.st_mode);
+}
+
+void reparent(char *fullpath, size_t fullpathsize,
+ const char *dir, const char *base)
+{
+ fullpath[0] = '\0';
+ if (base[0] != DIR_SEP) {
+ char *dirpart = strdup(dir);
+ char *end;
+ strlcpy(fullpath, dirname(dirpart), fullpathsize-2);
+ end = fullpath + strlen(fullpath);
+ *end++ = DIR_SEP;
+ *end++ = '\0';
+ free(dirpart);
+ }
+ strlcat(fullpath, base, fullpathsize);
+}
+
/* Push another file on the parsing stack. If the mode is NULL, create a
* FILE_INFO suitable for in-memory parsing; otherwise, create a
* FILE_INFO that is bound to a local/disc file. Note that 'path' must
* not be NULL, or the function will fail.
*
+ * If the pathname is a directory, push all subfiles and
+ * subdirectories with paths satisying the predicate CONF_ENABLE(),
+ * recursively depth first to be interpreted in ASCII sort order.
+ *
* Relative pathnames are interpreted relative to the directory
* of the previous entry on the stack, not the current directory.
* This is so "include foo" from within /etc/conf will reliably
@@ -351,29 +390,59 @@ lex_flush_stack()
* Returns true if a new info record was pushed onto the stack.
*/
bool lex_push_file(
- const char * path,
- const char * mode
+ const char * path
)
{
struct FILE_INFO * next = NULL;
if (NULL != path) {
char fullpath[PATH_MAX];
- fullpath[0] = '\0';
- if (path[0] != DIR_SEP && lex_stack != NULL) {
- char *end;
- strlcpy(fullpath,
- dirname(lex_stack->fname),sizeof(fullpath)-2);
- end = fullpath + strlen(fullpath);
- *end++ = DIR_SEP;
- *end++ = '\0';
- }
- strlcat(fullpath, path, sizeof(fullpath));
- fprintf(stderr, "Opening %s\n", fullpath);
- next = lex_open(fullpath, mode);
- if (NULL != next) {
- next->st_next = lex_stack;
- lex_stack = next;
+ if (lex_stack != NULL)
+ reparent(fullpath, sizeof(fullpath), lex_stack->fname, path);
+ else
+ strlcpy(fullpath, path, sizeof(fullpath));
+ //fprintf(stderr, "lex_push_file(%s)\n", fullpath);
+ if (is_directory(fullpath)) {
+ /* directory scanning */
+ DIR *dfd;
+ struct dirent *dp;
+ char **baselist = (char **)malloc(sizeof(char *));
+ int basecount = 0;
+ if ((dfd = opendir(fullpath)) == NULL)
+ return false;
+ while ((dp = readdir(dfd)) != NULL)
+ {
+ if (!CONF_ENABLE(dp->d_name))
+ continue;
+ baselist[basecount++] = strdup(dp->d_name);
+ baselist = realloc(baselist,
+ (basecount+1) * sizeof(char *));
+ }
+ qsort(baselist, basecount, sizeof(char *), rcmpstring);
+ for (int i = 0; i < basecount; i++) {
+ char subpath[PATH_MAX];
+ strlcpy(subpath, fullpath, PATH_MAX);
+ if (strlen(subpath) < PATH_MAX - 1) {
+ char *ep = subpath + strlen(subpath);
+ *ep++ = DIR_SEP;
+ *ep = '\0';
+ }
+ strlcat(subpath, baselist[i], PATH_MAX);
+ /* This should barf safely if the complete
+ * filename was too long to fit in the buffer.
+ */
+ lex_push_file(subpath);
+ }
+ for (int i = 0; i < basecount; i++)
+ free(baselist[basecount]);
+ free(baselist);
+ return basecount > 0;
+ } else {
+ next = lex_open(fullpath, "r");
+ if (NULL != next) {
+ next->st_next = lex_stack;
+ lex_stack = next;
+ }
}
}
return (NULL != next);
=====================================
ntpd/ntp_scanner.h
=====================================
--- a/ntpd/ntp_scanner.h
+++ b/ntpd/ntp_scanner.h
@@ -132,8 +132,12 @@ extern bool lex_init_stack(const char * path, const char * mode);
extern void lex_drop_stack(void);
extern bool lex_flush_stack(void);
+/* path management for config directories */
+extern void reparent(char *, size_t, const char *, const char *);
+extern bool is_directory(const char *);
+
/* add/remove a nested input source */
-extern bool lex_push_file(const char * path, const char * mode);
+extern bool lex_push_file(const char * path);
extern bool lex_pop_file(void);
/* input stack state query functions */
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/e2132683825779f4ec7cfe393a3b790894e3e544...edc696bd5f8adda8ea2a7d3599e6967c4ff399bb
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ntpsec.org/pipermail/vc/attachments/20170324/4df45919/attachment.html>
More information about the vc
mailing list