aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2019-08-22 17:25:35 -0400
committerNick Mathewson <nickm@torproject.org>2019-08-22 17:25:35 -0400
commit2780cbb9cb9905a7194364d791da4d94ac419998 (patch)
tree76a29e21d60d9cbe83dfa16a64fadbe3fefbc679 /src/lib
parentd475d7c2fb3c0ed5120c50011b187f6957a4f52c (diff)
parentc32d485942e766eeea70cab468cc7c727a5be270 (diff)
downloadtor-2780cbb9cb9905a7194364d791da4d94ac419998.tar.gz
tor-2780cbb9cb9905a7194364d791da4d94ac419998.zip
Merge branch 'ticket30935' into ticket30935_merged
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/conf/.may_include1
-rw-r--r--src/lib/conf/confmacros.h67
-rw-r--r--src/lib/conf/conftesting.h86
-rw-r--r--src/lib/conf/conftypes.h63
-rw-r--r--src/lib/conf/include.am4
-rw-r--r--src/lib/confmgt/structvar.c37
-rw-r--r--src/lib/confmgt/structvar.h5
-rw-r--r--src/lib/confmgt/type_defs.c65
-rw-r--r--src/lib/confmgt/typedvar.c45
-rw-r--r--src/lib/confmgt/typedvar.h6
-rw-r--r--src/lib/confmgt/var_type_def_st.h20
11 files changed, 346 insertions, 53 deletions
diff --git a/src/lib/conf/.may_include b/src/lib/conf/.may_include
index 4285c3dcb8..629e2f897d 100644
--- a/src/lib/conf/.may_include
+++ b/src/lib/conf/.may_include
@@ -1,2 +1,3 @@
orconfig.h
lib/cc/*.h
+lib/conf/*.h
diff --git a/src/lib/conf/confmacros.h b/src/lib/conf/confmacros.h
new file mode 100644
index 0000000000..aa89965e69
--- /dev/null
+++ b/src/lib/conf/confmacros.h
@@ -0,0 +1,67 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file confmacros.h
+ * @brief Macro definitions for declaring configuration variables
+ **/
+
+#ifndef TOR_LIB_CONF_CONFMACROS_H
+#define TOR_LIB_CONF_CONFMACROS_H
+
+#include "orconfig.h"
+#include "lib/conf/conftesting.h"
+
+/**
+ * Used to indicate the end of an array of configuration variables.
+ **/
+#define END_OF_CONFIG_VARS \
+ { .member = { .name = NULL } DUMMY_CONF_TEST_MEMBERS }
+
+/**
+ * Declare a config_var_t as a member named <b>membername</b> of the structure
+ * <b>structtype</b>, whose user-visible name is <b>varname</b>, whose
+ * type corresponds to the config_type_t member CONFIG_TYPE_<b>vartype</b>,
+ * and whose initial value is <b>intval</b>.
+ *
+ * Most modules that use this macro should wrap it in a local macro that
+ * sets structtype to the local configuration type.
+ **/
+#define CONFIG_VAR_ETYPE(structtype, varname, vartype, membername, \
+ varflags, initval) \
+ { .member = \
+ { .name = varname, \
+ .type = CONFIG_TYPE_ ## vartype, \
+ .offset = offsetof(structtype, membername), \
+ }, \
+ .flags = varflags, \
+ .initvalue = initval \
+ CONF_TEST_MEMBERS(structtype, vartype, membername) \
+ }
+
+/**
+ * As CONFIG_VAR_XTYPE, but declares a value using an extension type whose
+ * type definition is <b>vartype</b>_type_defn.
+ **/
+#define CONFIG_VAR_DEFN(structtype, varname, vartype, membername, \
+ varflags, initval) \
+ { .member = \
+ { .name = varname, \
+ .type = CONFIG_TYPE_EXTENDED, \
+ .type_def = &vartype ## _type_defn, \
+ .offset = offsetof(structtype, membername), \
+ }, \
+ .flags = varflags, \
+ .initvalue = initval \
+ CONF_TEST_MEMBERS(structtype, vartype, membername) \
+ }
+
+#define CONFIG_VAR_OBSOLETE(varname) \
+ { .member = { .name = varname, .type = CONFIG_TYPE_OBSOLETE }, \
+ .flags = CVFLAG_OBSOLETE \
+ }
+
+#endif /* !defined(TOR_LIB_CONF_CONFMACROS_H) */
diff --git a/src/lib/conf/conftesting.h b/src/lib/conf/conftesting.h
new file mode 100644
index 0000000000..a40c9bc97c
--- /dev/null
+++ b/src/lib/conf/conftesting.h
@@ -0,0 +1,86 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file conftesting.h
+ * @brief Macro and type declarations for testing
+ **/
+
+#ifndef TOR_LIB_CONF_CONFTESTING_H
+#define TOR_LIB_CONF_CONFTESTING_H
+
+#ifdef TOR_UNIT_TESTS
+/**
+ * Union used when building in test mode typechecking the members of a type
+ * used with confparse.c. See CONF_CHECK_VAR_TYPE for a description of how
+ * it is used. */
+typedef union {
+ char **STRING;
+ char **FILENAME;
+ int *POSINT; /* yes, this is really an int, and not an unsigned int. For
+ * historical reasons, many configuration values are restricted
+ * to the range [0,INT_MAX], and stored in signed ints.
+ */
+ uint64_t *UINT64;
+ int *INT;
+ int *INTERVAL;
+ int *MSEC_INTERVAL;
+ uint64_t *MEMUNIT;
+ double *DOUBLE;
+ int *BOOL;
+ int *AUTOBOOL;
+ time_t *ISOTIME;
+ struct smartlist_t **CSV;
+ int *CSV_INTERVAL;
+ struct config_line_t **LINELIST;
+ struct config_line_t **LINELIST_S;
+ struct config_line_t **LINELIST_V;
+ // XXXX this doesn't belong at this level of abstraction.
+ struct routerset_t **ROUTERSET;
+} confparse_dummy_values_t;
+#endif /* defined(TOR_UNIT_TESTS) */
+
+/* Macros to define extra members inside config_var_t fields, and at the
+ * end of a list of them.
+ */
+#ifdef TOR_UNIT_TESTS
+/* This is a somewhat magic type-checking macro for users of confparse.c.
+ * It initializes a union member "confparse_dummy_values_t.conftype" with
+ * the address of a static member "tp_dummy.member". This
+ * will give a compiler warning unless the member field is of the correct
+ * type.
+ *
+ * (This warning is mandatory, because a type mismatch here violates the type
+ * compatibility constraint for simple assignment, and requires a diagnostic,
+ * according to the C spec.)
+ *
+ * For example, suppose you say:
+ * "CONF_CHECK_VAR_TYPE(or_options_t, STRING, Address)".
+ * Then this macro will evaluate to:
+ * { .STRING = &or_options_t_dummy.Address }
+ * And since confparse_dummy_values_t.STRING has type "char **", that
+ * expression will create a warning unless or_options_t.Address also
+ * has type "char *".
+ */
+#define CONF_CHECK_VAR_TYPE(tp, conftype, member) \
+ { . conftype = &tp ## _dummy . member }
+#define CONF_TEST_MEMBERS(tp, conftype, member) \
+ , .var_ptr_dummy=CONF_CHECK_VAR_TYPE(tp, conftype, member)
+#define DUMMY_CONF_TEST_MEMBERS , .var_ptr_dummy={ .INT=NULL }
+#define DUMMY_TYPECHECK_INSTANCE(tp) \
+ static tp tp ## _dummy
+
+#else /* !(defined(TOR_UNIT_TESTS)) */
+
+#define CONF_TEST_MEMBERS(tp, conftype, member)
+/* Repeatedly declarable incomplete struct to absorb redundant semicolons */
+#define DUMMY_TYPECHECK_INSTANCE(tp) \
+ struct tor_semicolon_eater
+#define DUMMY_CONF_TEST_MEMBERS
+
+#endif /* defined(TOR_UNIT_TESTS) */
+
+#endif /* !defined(TOR_LIB_CONF_CONFTESTING_H) */
diff --git a/src/lib/conf/conftypes.h b/src/lib/conf/conftypes.h
index cddfeff2fd..3b754e07be 100644
--- a/src/lib/conf/conftypes.h
+++ b/src/lib/conf/conftypes.h
@@ -29,6 +29,9 @@
#define TOR_SRC_LIB_CONF_CONFTYPES_H
#include "lib/cc/torint.h"
+#ifdef TOR_UNIT_TESTS
+#include "lib/conf/conftesting.h"
+#endif
/** Enumeration of types which option values can take */
typedef enum config_type_t {
@@ -59,9 +62,6 @@ typedef enum config_type_t {
CONFIG_TYPE_LINELIST_V, /**< Catch-all "virtual" option to summarize
* context-sensitive config lines when fetching.
*/
- // XXXX this doesn't belong at this level of abstraction.
- CONFIG_TYPE_ROUTERSET, /**< A list of router names, addrs, and fps,
- * parsed into a routerset_t. */
CONFIG_TYPE_OBSOLETE, /**< Obsolete (ignored) option. */
CONFIG_TYPE_EXTENDED, /**< Extended type; definition will appear in
* pointer. */
@@ -105,35 +105,34 @@ typedef struct struct_magic_decl_t {
int magic_offset;
} struct_magic_decl_t;
-#ifdef TOR_UNIT_TESTS
/**
- * Union used when building in test mode typechecking the members of a type
- * used with confparse.c. See CONF_CHECK_VAR_TYPE for a description of how
- * it is used. */
-typedef union {
- char **STRING;
- char **FILENAME;
- int *POSINT; /* yes, this is really an int, and not an unsigned int. For
- * historical reasons, many configuration values are restricted
- * to the range [0,INT_MAX], and stored in signed ints.
- */
- uint64_t *UINT64;
- int *INT;
- int *INTERVAL;
- int *MSEC_INTERVAL;
- uint64_t *MEMUNIT;
- double *DOUBLE;
- int *BOOL;
- int *AUTOBOOL;
- time_t *ISOTIME;
- struct smartlist_t **CSV;
- int *CSV_INTERVAL;
- struct config_line_t **LINELIST;
- struct config_line_t **LINELIST_S;
- struct config_line_t **LINELIST_V;
- // XXXX this doesn't belong at this level of abstraction.
- struct routerset_t **ROUTERSET;
-} confparse_dummy_values_t;
-#endif /* defined(TOR_UNIT_TESTS) */
+ * Flag to indicate that an option is obsolete. Any attempt to set or
+ * fetch this option should produce a warning.
+ **/
+#define CVFLAG_OBSOLETE (1u<<0)
+/**
+ * Flag to indicate that an option is undumpable. An undumpable option is
+ * never saved to disk, and is prefixed with __.
+ **/
+#define CVFLAG_NODUMP (1u<<1)
+/**
+ * Flag to indicate that an option is "invisible". An invisible option
+ * is always undumpable, and we don't tell the controller about it.
+ **/
+#define CVFLAG_INVISIBLE (1u<<2)
+
+/** A variable allowed in the configuration file or on the command line. */
+typedef struct config_var_t {
+ struct_member_t member; /** A struct member corresponding to this
+ * variable. */
+ const char *initvalue; /**< String (or null) describing initial value. */
+ uint32_t flags; /**< One or more flags describing special handling for this
+ * variable */
+#ifdef TOR_UNIT_TESTS
+ /** Used for compiler-magic to typecheck the corresponding field in the
+ * corresponding struct. Only used in unit test mode, at compile-time. */
+ confparse_dummy_values_t var_ptr_dummy;
+#endif
+} config_var_t;
#endif /* !defined(TOR_SRC_LIB_CONF_CONFTYPES_H) */
diff --git a/src/lib/conf/include.am b/src/lib/conf/include.am
index 25355697d2..cb7126184d 100644
--- a/src/lib/conf/include.am
+++ b/src/lib/conf/include.am
@@ -1,4 +1,6 @@
# ADD_C_FILE: INSERT HEADERS HERE.
noinst_HEADERS += \
- src/lib/conf/conftypes.h
+ src/lib/conf/conftesting.h \
+ src/lib/conf/conftypes.h \
+ src/lib/conf/confmacros.h
diff --git a/src/lib/confmgt/structvar.c b/src/lib/confmgt/structvar.c
index 38f8e5dd7a..97a8fb3633 100644
--- a/src/lib/confmgt/structvar.c
+++ b/src/lib/confmgt/structvar.c
@@ -202,6 +202,19 @@ struct_var_kvencode(const void *object, const struct_member_t *member)
}
/**
+ * Mark the field in <b>object</b> determined by <b>member</b> -- a variable
+ * that ordinarily would be extended by assignment -- as "fragile", so that it
+ * will get replaced by the next assignment instead.
+ */
+void
+struct_var_mark_fragile(void *object, const struct_member_t *member)
+{
+ void *p = struct_get_mptr(object, member);
+ const var_type_def_t *def = get_type_def(member);
+ return typed_var_mark_fragile_ex(p, def);
+}
+
+/**
* Return the official name of this struct member.
**/
const char *
@@ -224,3 +237,27 @@ struct_var_get_typename(const struct_member_t *member)
return def ? def->name : NULL;
}
+
+bool
+struct_var_is_cumulative(const struct_member_t *member)
+{
+ const var_type_def_t *def = get_type_def(member);
+
+ return def ? def->is_cumulative : false;
+}
+
+bool
+struct_var_is_settable(const struct_member_t *member)
+{
+ const var_type_def_t *def = get_type_def(member);
+
+ return def ? !def->is_unsettable : true;
+}
+
+bool
+struct_var_is_contained(const struct_member_t *member)
+{
+ const var_type_def_t *def = get_type_def(member);
+
+ return def ? def->is_contained : false;
+}
diff --git a/src/lib/confmgt/structvar.h b/src/lib/confmgt/structvar.h
index 92b9b6fc71..e6dbc6d6ec 100644
--- a/src/lib/confmgt/structvar.h
+++ b/src/lib/confmgt/structvar.h
@@ -40,9 +40,14 @@ bool struct_var_eq(const void *a, const void *b,
const struct struct_member_t *member);
bool struct_var_ok(const void *object,
const struct struct_member_t *member);
+void struct_var_mark_fragile(void *object,
+ const struct struct_member_t *member);
const char *struct_var_get_name(const struct struct_member_t *member);
const char *struct_var_get_typename(const struct struct_member_t *member);
+bool struct_var_is_cumulative(const struct struct_member_t *member);
+bool struct_var_is_settable(const struct struct_member_t *member);
+bool struct_var_is_contained(const struct struct_member_t *member);
int struct_var_kvassign(void *object, const struct config_line_t *line,
char **errmsg,
diff --git a/src/lib/confmgt/type_defs.c b/src/lib/confmgt/type_defs.c
index 62b4c1019d..f8b2681aa0 100644
--- a/src/lib/confmgt/type_defs.c
+++ b/src/lib/confmgt/type_defs.c
@@ -620,12 +620,22 @@ linelist_copy(void *target, const void *value, const void *params)
return 0;
}
+static void
+linelist_mark_fragile(void *target, const void *params)
+{
+ (void)params;
+ config_line_t **ptr = (config_line_t **)target;
+ if (*ptr)
+ (*ptr)->fragile = 1;
+}
+
static const var_type_fns_t linelist_fns = {
.kv_parse = linelist_kv_parse,
.kv_encode = linelist_kv_encode,
.clear = linelist_clear,
.eq = linelist_eq,
.copy = linelist_copy,
+ .mark_fragile = linelist_mark_fragile,
};
static const var_type_fns_t linelist_v_fns = {
@@ -634,6 +644,7 @@ static const var_type_fns_t linelist_v_fns = {
.clear = linelist_clear,
.eq = linelist_eq,
.copy = linelist_copy,
+ .mark_fragile = linelist_mark_fragile,
};
static const var_type_fns_t linelist_s_fns = {
@@ -690,26 +701,40 @@ static const var_type_fns_t ignore_fns = {
* Table mapping conf_type_t values to var_type_def_t objects.
**/
static const var_type_def_t type_definitions_table[] = {
- [CONFIG_TYPE_STRING] = { "String", &string_fns, NULL },
- [CONFIG_TYPE_FILENAME] = { "Filename", &string_fns, NULL },
- [CONFIG_TYPE_INT] = { "SignedInteger", &int_fns, &INT_PARSE_UNRESTRICTED },
- [CONFIG_TYPE_POSINT] = { "Integer", &int_fns, &INT_PARSE_POSINT },
- [CONFIG_TYPE_UINT64] = { "Integer", &uint64_fns, NULL, },
- [CONFIG_TYPE_MEMUNIT] = { "DataSize", &memunit_fns, &memory_units },
- [CONFIG_TYPE_INTERVAL] = { "TimeInterval", &interval_fns, &time_units },
- [CONFIG_TYPE_MSEC_INTERVAL] = { "TimeMsecInterval", &interval_fns,
- &time_msec_units },
- [CONFIG_TYPE_DOUBLE] = { "Float", &double_fns, NULL },
- [CONFIG_TYPE_BOOL] = { "Boolean", &enum_fns, &enum_table_bool },
- [CONFIG_TYPE_AUTOBOOL] = { "Boolean+Auto", &enum_fns, &enum_table_autobool },
- [CONFIG_TYPE_ISOTIME] = { "Time", &time_fns, NULL },
- [CONFIG_TYPE_CSV] = { "CommaList", &csv_fns, NULL },
- [CONFIG_TYPE_CSV_INTERVAL] = { "TimeInterval", &legacy_csv_interval_fns,
- NULL },
- [CONFIG_TYPE_LINELIST] = { "LineList", &linelist_fns, NULL },
- [CONFIG_TYPE_LINELIST_S] = { "Dependent", &linelist_s_fns, NULL },
- [CONFIG_TYPE_LINELIST_V] = { "Virtual", &linelist_v_fns, NULL },
- [CONFIG_TYPE_OBSOLETE] = { "Obsolete", &ignore_fns, NULL }
+ [CONFIG_TYPE_STRING] = { .name="String", .fns=&string_fns },
+ [CONFIG_TYPE_FILENAME] = { .name="Filename", .fns=&string_fns },
+ [CONFIG_TYPE_INT] = { .name="SignedInteger", .fns=&int_fns,
+ .params=&INT_PARSE_UNRESTRICTED },
+ [CONFIG_TYPE_POSINT] = { .name="Integer", .fns=&int_fns,
+ .params=&INT_PARSE_POSINT },
+ [CONFIG_TYPE_UINT64] = { .name="Integer", .fns=&uint64_fns, },
+ [CONFIG_TYPE_MEMUNIT] = { .name="DataSize", .fns=&memunit_fns,
+ .params=&memory_units },
+ [CONFIG_TYPE_INTERVAL] = { .name="TimeInterval", .fns=&interval_fns,
+ .params=&time_units },
+ [CONFIG_TYPE_MSEC_INTERVAL] = { .name="TimeMsecInterval",
+ .fns=&interval_fns,
+ .params=&time_msec_units },
+ [CONFIG_TYPE_DOUBLE] = { .name="Float", .fns=&double_fns, },
+ [CONFIG_TYPE_BOOL] = { .name="Boolean", .fns=&enum_fns,
+ .params=&enum_table_bool },
+ [CONFIG_TYPE_AUTOBOOL] = { .name="Boolean+Auto", .fns=&enum_fns,
+ .params=&enum_table_autobool },
+ [CONFIG_TYPE_ISOTIME] = { .name="Time", .fns=&time_fns, },
+ [CONFIG_TYPE_CSV] = { .name="CommaList", .fns=&csv_fns, },
+ [CONFIG_TYPE_CSV_INTERVAL] = { .name="TimeInterval",
+ .fns=&legacy_csv_interval_fns, },
+ [CONFIG_TYPE_LINELIST] = { .name="LineList", .fns=&linelist_fns,
+ .is_cumulative=true},
+ [CONFIG_TYPE_LINELIST_S] = { .name="Dependent", .fns=&linelist_s_fns,
+ .is_cumulative=true,
+ .is_contained=true, },
+ [CONFIG_TYPE_LINELIST_V] = { .name="Virtual", .fns=&linelist_v_fns,
+ .is_cumulative=true,
+ .is_unsettable=true },
+ [CONFIG_TYPE_OBSOLETE] = { .name="Obsolete", .fns=&ignore_fns,
+ .is_unsettable=true,
+ .is_contained=true, }
};
/**
diff --git a/src/lib/confmgt/typedvar.c b/src/lib/confmgt/typedvar.c
index c2b9b45725..3cba075390 100644
--- a/src/lib/confmgt/typedvar.c
+++ b/src/lib/confmgt/typedvar.c
@@ -210,6 +210,51 @@ typed_var_ok_ex(const void *value, const var_type_def_t *def)
return true;
}
+/**
+ * Mark <b>value</b> -- a variable that ordinarily would be extended by
+ * assignment -- as "fragile", so that it will get replaced by the next
+ * assignment instead.
+ **/
+void
+typed_var_mark_fragile_ex(void *value, const var_type_def_t *def)
+{
+ if (BUG(!def)) {
+ return; // LCOV_EXCL_LINE
+ }
+
+ if (def->fns->mark_fragile)
+ def->fns->mark_fragile(value, def->params);
+}
+
+/**
+ * Return true iff multiple assignments to a variable will extend its
+ * value, rather than replacing it.
+ **/
+bool
+var_type_is_cumulative(const var_type_def_t *def)
+{
+ return def->is_cumulative;
+}
+
+/**
+ * Return true iff this variable type is always contained in another variable,
+ * and as such doesn't need to be dumped or copied independently.
+ **/
+bool
+var_type_is_contained(const var_type_def_t *def)
+{
+ return def->is_contained;
+}
+
+/**
+ * Return true iff this type can not be assigned directly by the user.
+ **/
+bool
+var_type_is_settable(const var_type_def_t *def)
+{
+ return ! def->is_unsettable;
+}
+
/* =====
* The functions below take a config_type_t instead of a var_type_def_t.
* I'd like to deprecate them eventually and use var_type_def_t everywhere,
diff --git a/src/lib/confmgt/typedvar.h b/src/lib/confmgt/typedvar.h
index 720ad54fc6..2e36f9d673 100644
--- a/src/lib/confmgt/typedvar.h
+++ b/src/lib/confmgt/typedvar.h
@@ -46,4 +46,10 @@ int typed_var_kvassign_ex(void *target, const struct config_line_t *line,
struct config_line_t *typed_var_kvencode_ex(const char *key, const void *value,
const var_type_def_t *def);
+void typed_var_mark_fragile_ex(void *value, const var_type_def_t *def);
+
+bool var_type_is_cumulative(const var_type_def_t *def);
+bool var_type_is_contained(const var_type_def_t *def);
+bool var_type_is_settable(const var_type_def_t *def);
+
#endif /* !defined(TOR_LIB_CONFMGT_TYPEDVAR_H) */
diff --git a/src/lib/confmgt/var_type_def_st.h b/src/lib/confmgt/var_type_def_st.h
index d142ee1104..4157cb8ff6 100644
--- a/src/lib/confmgt/var_type_def_st.h
+++ b/src/lib/confmgt/var_type_def_st.h
@@ -122,6 +122,15 @@ struct var_type_fns_t {
* values are valid.
**/
bool (*ok)(const void *value, const void *params);
+ /**
+ * Mark a value of this variable as "fragile", so that future attempts to
+ * assign to this variable will replace rather than extending it.
+ *
+ * The default implementation for this function does nothing.
+ *
+ * Only meaningful for types with is_cumulative set.
+ **/
+ void (*mark_fragile)(void *value, const void *params);
};
/**
@@ -142,6 +151,17 @@ struct var_type_def_t {
* calling the functions in this type's function table.
*/
const void *params;
+
+ /** True iff a variable of this type can never be set directly by name. */
+ bool is_unsettable;
+ /** True iff a variable of this type is always contained in another
+ * variable, and as such doesn't need to be dumped or copied
+ * independently. */
+ bool is_contained;
+ /** True iff a variable of this type can be set more than once without
+ * destroying older values. Such variables should implement "mark_fragile".
+ */
+ bool is_cumulative;
};
#endif /* !defined(TOR_LIB_CONFMGT_VAR_TYPE_DEF_ST_H) */