[tor-commits] [tor/master] Add a config_validate() function to invoke verify callbacks.

nickm at torproject.org nickm at torproject.org
Fri Oct 25 12:15:41 UTC 2019


commit 0cb42385378d539185a20ce8899cdc16cf46145c
Author: Nick Mathewson <nickm at torproject.org>
Date:   Wed Oct 23 15:12:19 2019 -0400

    Add a config_validate() function to invoke verify callbacks.
    
    As we turn our monolithic configuration objects into suites of
    smaller module-specific configuration objects, we will want each one
    to be able to provide its own verification callbacks.  That means
    that instead of invoking these verification callbacks directly, we will
    want to call them via the configuration manager object.
---
 src/lib/confmgt/confparse.c | 73 +++++++++++++++++++++++++++++++++++++++++++++
 src/lib/confmgt/confparse.h |  3 ++
 2 files changed, 76 insertions(+)

diff --git a/src/lib/confmgt/confparse.c b/src/lib/confmgt/confparse.c
index 96eba610b..6d272ed04 100644
--- a/src/lib/confmgt/confparse.c
+++ b/src/lib/confmgt/confparse.c
@@ -1142,6 +1142,79 @@ config_init(const config_mgr_t *mgr, void *options)
   } SMARTLIST_FOREACH_END(mv);
 }
 
+/**
+ * Normalize and validate a single object `options` within a configuration
+ * suite, according to its format.  `options` may be modified as appropriate
+ * in order to set ancillary data.  If `old_options` is provided, make sure
+ * that the transition from `old_options` to `options` is permitted.
+ *
+ * On success return 0; on failure set *msg_out to a newly allocated string
+ * explaining what is wrong, and return -1.
+ **/
+static int
+config_validate_single(const config_format_t *fmt,
+                       const void *old_options, void *options,
+                       char **msg_out)
+{
+  tor_assert(fmt);
+  tor_assert(options);
+
+  if (fmt->legacy_validate_fn) {
+    if (fmt->legacy_validate_fn(old_options, options, msg_out) < 0) {
+      return -1;
+    }
+  }
+
+  return 0;
+}
+
+/**
+ * Normalize and validate all the options in configuration object `options`
+ * and its sub-objects. `options` may be modified as appropriate in order to
+ * set ancillary data.  If `old_options` is provided, make sure that the
+ * transition from `old_options` to `options` is permitted.
+ *
+ * On success return 0; on failure set *msg_out to a newly allocated string
+ * explaining what is wrong, and return -1.
+ **/
+int
+config_validate(const config_mgr_t *mgr,
+                const void *old_options, void *options,
+                char **msg_out)
+{
+  int rv;
+  CONFIG_CHECK(mgr, options);
+  if (old_options) {
+    CONFIG_CHECK(mgr, old_options);
+  }
+
+  config_suite_t **suitep_new = config_mgr_get_suite_ptr(mgr, options);
+  config_suite_t **suitep_old = NULL;
+  if (old_options)
+    suitep_old = config_mgr_get_suite_ptr(mgr, (void*) old_options);
+
+  /* Validate the sub-objects */
+  if (suitep_new) {
+    SMARTLIST_FOREACH_BEGIN(mgr->subconfigs, const config_format_t *, fmt) {
+      void *obj = smartlist_get((*suitep_new)->configs, fmt_sl_idx);
+      const void *obj_old=NULL;
+      if (suitep_old)
+        obj_old = smartlist_get((*suitep_old)->configs, fmt_sl_idx);
+
+      rv = config_validate_single(fmt, obj_old, obj, msg_out);
+      if (rv < 0)
+        return rv;
+    } SMARTLIST_FOREACH_END(fmt);
+  }
+
+  /* Validate the top-level object. */
+  rv = config_validate_single(mgr->toplevel, old_options, options, msg_out);
+  if (rv < 0)
+    return rv;
+
+  return 0;
+}
+
 /** Allocate and return a new string holding the written-out values of the vars
  * in 'options'.  If 'minimal', do not write out any default-valued vars.
  * Else, if comment_defaults, write default values as comments.
diff --git a/src/lib/confmgt/confparse.h b/src/lib/confmgt/confparse.h
index d50d6d814..fea80f916 100644
--- a/src/lib/confmgt/confparse.h
+++ b/src/lib/confmgt/confparse.h
@@ -169,6 +169,9 @@ int config_is_same(const config_mgr_t *fmt,
 struct config_line_t *config_get_changes(const config_mgr_t *mgr,
                                   const void *options1, const void *options2);
 void config_init(const config_mgr_t *mgr, void *options);
+int config_validate(const config_mgr_t *mgr,
+                    const void *old_options, void *options,
+                    char **msg_out);
 void *config_dup(const config_mgr_t *mgr, const void *old);
 char *config_dump(const config_mgr_t *mgr, const void *default_options,
                   const void *options, int minimal,





More information about the tor-commits mailing list