summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app/config/config.c15
-rw-r--r--src/app/config/statefile.c2
-rw-r--r--src/app/main/subsystem_list.c43
-rw-r--r--src/core/include.am2
-rw-r--r--src/core/or/circuitbuild.c2
-rw-r--r--src/core/or/circuitstats.c2
-rw-r--r--src/feature/client/entrynodes.c5
-rw-r--r--src/feature/control/control_cmd.c2
-rw-r--r--src/feature/dirauth/keypin.h18
-rw-r--r--src/feature/dirauth/process_descs.h81
-rw-r--r--src/feature/dirauth/reachability.h31
-rw-r--r--src/feature/dirauth/shared_random.c2
-rw-r--r--src/feature/dirauth/shared_random_state.c2
-rw-r--r--src/feature/hs/hs_dos.c2
-rw-r--r--src/lib/conf/confmacros.h2
-rw-r--r--src/lib/conf/conftypes.h58
-rw-r--r--src/lib/confmgt/.may_include2
-rw-r--r--src/lib/confmgt/confparse.c (renamed from src/app/config/confparse.c)126
-rw-r--r--src/lib/confmgt/confparse.h (renamed from src/app/config/confparse.h)5
-rw-r--r--src/lib/confmgt/include.am2
-rw-r--r--src/lib/confmgt/structvar.c23
-rw-r--r--src/lib/confmgt/structvar.h5
-rw-r--r--src/lib/confmgt/type_defs.c22
-rw-r--r--src/lib/confmgt/typedvar.c29
-rw-r--r--src/lib/confmgt/typedvar.h4
-rw-r--r--src/lib/confmgt/var_type_def_st.h16
-rw-r--r--src/lib/err/backtrace.c2
-rw-r--r--src/lib/err/torerr.c64
-rw-r--r--src/lib/err/torerr.h7
-rw-r--r--src/lib/err/torerr_sys.c10
-rw-r--r--src/lib/log/log.c85
-rw-r--r--src/lib/log/log.h1
-rw-r--r--src/lib/log/log_sys.c2
-rw-r--r--src/lib/log/util_bug.c11
-rw-r--r--src/lib/malloc/map_anon.c36
-rw-r--r--src/lib/meminfo/meminfo.c7
-rw-r--r--src/lib/net/network_sys.c4
-rw-r--r--src/lib/process/winprocess_sys.c2
-rw-r--r--src/lib/thread/compat_threads.c2
-rw-r--r--src/lib/time/time_sys.c4
-rw-r--r--src/lib/wallclock/approx_time.c4
-rw-r--r--src/test/conf_examples/badnick_1/error1
-rw-r--r--src/test/conf_examples/badnick_1/torrc2
-rw-r--r--src/test/conf_examples/badnick_2/error1
-rw-r--r--src/test/conf_examples/badnick_2/torrc2
-rw-r--r--src/test/conf_examples/contactinfo_notutf8/error1
-rw-r--r--src/test/conf_examples/contactinfo_notutf8/torrc1
-rw-r--r--src/test/conf_examples/example_1/expected2
-rw-r--r--src/test/conf_examples/example_1/torrc5
-rw-r--r--src/test/conf_examples/example_2/error1
-rw-r--r--src/test/conf_examples/example_2/torrc1
-rw-r--r--src/test/conf_examples/example_3/cmdline1
-rw-r--r--src/test/conf_examples/example_3/expected1
-rw-r--r--src/test/conf_examples/example_3/torrc0
-rw-r--r--src/test/conf_examples/include_1/expected3
-rw-r--r--src/test/conf_examples/include_1/included.inc4
-rw-r--r--src/test/conf_examples/include_1/nested.inc2
-rw-r--r--src/test/conf_examples/include_1/torrc4
-rw-r--r--src/test/conf_examples/large_1/expected159
-rw-r--r--src/test/conf_examples/large_1/torrc167
-rw-r--r--src/test/conf_examples/ops_1/cmdline1
-rw-r--r--src/test/conf_examples/ops_1/expected2
-rw-r--r--src/test/conf_examples/ops_1/torrc3
-rw-r--r--src/test/conf_examples/ops_2/cmdline1
-rw-r--r--src/test/conf_examples/ops_2/expected0
-rw-r--r--src/test/conf_examples/ops_2/torrc3
-rw-r--r--src/test/conf_examples/ops_3/cmdline1
-rw-r--r--src/test/conf_examples/ops_3/expected3
-rw-r--r--src/test/conf_examples/ops_3/torrc3
-rw-r--r--src/test/conf_examples/ops_4/expected2
-rw-r--r--src/test/conf_examples/ops_4/torrc3
-rw-r--r--src/test/conf_examples/ops_4/torrc.defaults1
-rw-r--r--src/test/conf_examples/ops_5/expected3
-rw-r--r--src/test/conf_examples/ops_5/torrc3
-rw-r--r--src/test/conf_examples/ops_5/torrc.defaults1
-rw-r--r--src/test/conf_examples/ops_6/expected0
-rw-r--r--src/test/conf_examples/ops_6/torrc3
-rw-r--r--src/test/conf_examples/ops_6/torrc.defaults1
-rw-r--r--src/test/conf_examples/relpath_rad/error1
-rw-r--r--src/test/conf_examples/relpath_rad/torrc4
-rw-r--r--src/test/include.am8
-rw-r--r--src/test/test_addr.c66
-rw-r--r--src/test/test_btrack.c2
-rwxr-xr-xsrc/test/test_cmdline.sh48
-rw-r--r--src/test/test_config.c28
-rw-r--r--src/test/test_confmgr.c2
-rw-r--r--src/test/test_confparse.c2
-rw-r--r--src/test/test_dir.c2
-rw-r--r--src/test/test_entryconn.c2
-rw-r--r--src/test/test_entrynodes.c5
-rw-r--r--src/test/test_helpers.c2
-rw-r--r--src/test/test_options.c2
-rwxr-xr-xsrc/test/test_parseconf.sh190
-rw-r--r--src/test/test_pt.c2
-rw-r--r--src/trunnel/trunnel-local.h1
95 files changed, 1259 insertions, 244 deletions
diff --git a/src/app/config/config.c b/src/app/config/config.c
index 1babb0d4f8..bdfa547fd7 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -61,7 +61,7 @@
#define CONFIG_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "app/config/statefile.h"
#include "app/main/main.h"
#include "app/main/subsysmgr.h"
@@ -267,10 +267,10 @@ DUMMY_TYPECHECK_INSTANCE(or_options_t);
#define VAR_NODUMP(varname,conftype,member,initvalue) \
CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \
- CVFLAG_NODUMP, initvalue)
+ CFLG_NODUMP, initvalue)
#define VAR_INVIS(varname,conftype,member,initvalue) \
CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \
- CVFLAG_NODUMP|CVFLAG_INVISIBLE, initvalue)
+ CFLG_NODUMP | CFLG_NOSET | CFLG_NOLIST, initvalue)
#define V(member,conftype,initvalue) \
VAR(#member, conftype, member, initvalue)
@@ -2671,6 +2671,9 @@ list_torrc_options(void)
{
smartlist_t *vars = config_mgr_list_vars(get_options_mgr());
SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) {
+ /* Possibly this should check listable, rather than (or in addition to)
+ * settable. See ticket 31654.
+ */
if (! config_var_is_settable(var)) {
/* This variable cannot be set, or cannot be set by this name. */
continue;
@@ -2685,6 +2688,8 @@ static void
list_deprecated_options(void)
{
smartlist_t *deps = config_mgr_list_deprecated_vars(get_options_mgr());
+ /* Possibly this should check whether the variables are listable,
+ * but currently it does not. See ticket 31654. */
SMARTLIST_FOREACH(deps, const char *, name,
printf("%s\n", name));
smartlist_free(deps);
@@ -8133,7 +8138,7 @@ getinfo_helper_config(control_connection_t *conn,
smartlist_t *vars = config_mgr_list_vars(get_options_mgr());
SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) {
/* don't tell controller about invisible options */
- if (config_var_is_invisible(var))
+ if (! config_var_is_listable(var))
continue;
const char *type = struct_var_get_typename(&var->member);
if (!type)
@@ -8147,6 +8152,8 @@ getinfo_helper_config(control_connection_t *conn,
} else if (!strcmp(question, "config/defaults")) {
smartlist_t *sl = smartlist_new();
int dirauth_lines_seen = 0, fallback_lines_seen = 0;
+ /* Possibly this should check whether the variables are listable,
+ * but currently it does not. See ticket 31654. */
smartlist_t *vars = config_mgr_list_vars(get_options_mgr());
SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) {
if (var->initvalue != NULL) {
diff --git a/src/app/config/statefile.c b/src/app/config/statefile.c
index bcc06809b3..552bd2c443 100644
--- a/src/app/config/statefile.c
+++ b/src/app/config/statefile.c
@@ -32,7 +32,7 @@
#include "core/or/or.h"
#include "core/or/circuitstats.h"
#include "app/config/config.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "core/mainloop/mainloop.h"
#include "core/mainloop/netstatus.h"
#include "core/mainloop/connection.h"
diff --git a/src/app/main/subsystem_list.c b/src/app/main/subsystem_list.c
index 95d96f78d2..1af9340c1a 100644
--- a/src/app/main/subsystem_list.c
+++ b/src/app/main/subsystem_list.c
@@ -33,33 +33,38 @@
/**
* Global list of the subsystems in Tor, in the order of their initialization.
+ * Want to know the exact level numbers?
+ * We'll implement a level dump command in #31614.
**/
const subsys_fns_t *tor_subsystems[] = {
- &sys_winprocess, /* -100 */
- &sys_torerr, /* -100 */
- &sys_wallclock, /* -99 */
- &sys_threads, /* -95 */
- &sys_logging, /* -90 */
- &sys_time, /* -90 */
- &sys_network, /* -90 */
- &sys_compress, /* -70 */
- &sys_crypto, /* -60 */
- &sys_tortls, /* -50 */
- &sys_process, /* -35 */
+ &sys_winprocess,
+ &sys_torerr,
- &sys_orconn_event, /* -33 */
- &sys_ocirc_event, /* -32 */
- &sys_btrack, /* -30 */
+ &sys_wallclock,
+ &sys_threads,
+ &sys_logging,
- &sys_evloop, /* -20 */
+ &sys_time,
+ &sys_network,
- &sys_mainloop, /* 5 */
- &sys_or, /* 20 */
+ &sys_compress,
+ &sys_crypto,
+ &sys_tortls,
+ &sys_process,
- &sys_relay, /* 50 */
+ &sys_orconn_event,
+ &sys_ocirc_event,
+ &sys_btrack,
+
+ &sys_evloop,
+
+ &sys_mainloop,
+ &sys_or,
+
+ &sys_relay,
#ifdef HAVE_MODULE_DIRAUTH
- &sys_dirauth, /* 70 */
+ &sys_dirauth,
#endif
};
diff --git a/src/core/include.am b/src/core/include.am
index 914c370ec1..9b4b251c81 100644
--- a/src/core/include.am
+++ b/src/core/include.am
@@ -9,7 +9,6 @@ endif
# ADD_C_FILE: INSERT SOURCES HERE.
LIBTOR_APP_A_SOURCES = \
src/app/config/config.c \
- src/app/config/confparse.c \
src/app/config/statefile.c \
src/app/main/main.c \
src/app/main/shutdown.c \
@@ -214,7 +213,6 @@ src_core_libtor_app_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
# ADD_C_FILE: INSERT HEADERS HERE.
noinst_HEADERS += \
src/app/config/config.h \
- src/app/config/confparse.h \
src/app/config/or_options_st.h \
src/app/config/or_state_st.h \
src/app/config/statefile.h \
diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c
index ff809c01cf..1daf468715 100644
--- a/src/core/or/circuitbuild.c
+++ b/src/core/or/circuitbuild.c
@@ -30,7 +30,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "core/crypto/hs_ntor.h"
#include "core/crypto/onion_crypto.h"
#include "core/crypto/onion_fast.h"
diff --git a/src/core/or/circuitstats.c b/src/core/or/circuitstats.c
index 03eea1d779..7a7f3ca600 100644
--- a/src/core/or/circuitstats.c
+++ b/src/core/or/circuitstats.c
@@ -29,7 +29,7 @@
#include "core/or/circuitbuild.h"
#include "core/or/circuitstats.h"
#include "app/config/config.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "feature/control/control_events.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "core/mainloop/mainloop.h"
diff --git a/src/feature/client/entrynodes.c b/src/feature/client/entrynodes.c
index 54a9238d8f..36b575ef20 100644
--- a/src/feature/client/entrynodes.c
+++ b/src/feature/client/entrynodes.c
@@ -114,7 +114,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "app/config/statefile.h"
#include "core/mainloop/connection.h"
#include "core/mainloop/mainloop.h"
@@ -3765,7 +3765,8 @@ guard_selection_get_err_str_if_dir_info_missing(guard_selection_t *gs,
/* otherwise return a helpful error string */
tor_asprintf(&ret_str, "We're missing descriptors for %d/%d of our "
- "primary entry guards (total %sdescriptors: %d/%d).",
+ "primary entry guards (total %sdescriptors: %d/%d). "
+ "That's ok. We will try to fetch missing descriptors soon.",
n_missing_descriptors, num_primary_to_check,
using_mds?"micro":"", num_present, num_usable);
diff --git a/src/feature/control/control_cmd.c b/src/feature/control/control_cmd.c
index ad4a4ef0af..a1d7f825db 100644
--- a/src/feature/control/control_cmd.c
+++ b/src/feature/control/control_cmd.c
@@ -13,7 +13,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "app/main/main.h"
#include "core/mainloop/connection.h"
#include "core/or/circuitbuild.h"
diff --git a/src/feature/dirauth/keypin.h b/src/feature/dirauth/keypin.h
index 722b6ca5fc..ab2362b3f8 100644
--- a/src/feature/dirauth/keypin.h
+++ b/src/feature/dirauth/keypin.h
@@ -11,10 +11,25 @@ int keypin_check_and_add(const uint8_t *rsa_id_digest,
const int replace_existing_entry);
int keypin_check(const uint8_t *rsa_id_digest,
const uint8_t *ed25519_id_key);
+int keypin_close_journal(void);
+#ifdef HAVE_MODULE_DIRAUTH
int keypin_open_journal(const char *fname);
-int keypin_close_journal(void);
int keypin_load_journal(const char *fname);
+#else
+static inline int
+keypin_open_journal(const char *fname)
+{
+ (void)fname;
+ return 0;
+}
+static inline int
+keypin_load_journal(const char *fname)
+{
+ (void)fname;
+ return 0;
+}
+#endif
void keypin_clear(void);
int keypin_check_lone_rsa(const uint8_t *rsa_id_digest);
@@ -44,4 +59,3 @@ MOCK_DECL(STATIC void, keypin_add_entry_to_map, (keypin_ent_t *ent));
#endif /* defined(KEYPIN_PRIVATE) */
#endif /* !defined(TOR_KEYPIN_H) */
-
diff --git a/src/feature/dirauth/process_descs.h b/src/feature/dirauth/process_descs.h
index 1d4085b091..184caa18b8 100644
--- a/src/feature/dirauth/process_descs.h
+++ b/src/feature/dirauth/process_descs.h
@@ -12,10 +12,13 @@
#ifndef TOR_RECV_UPLOADS_H
#define TOR_RECV_UPLOADS_H
-int dirserv_load_fingerprint_file(void);
+// for was_router_added_t.
+#include "feature/nodelist/routerlist.h"
+
void dirserv_free_fingerprint_list(void);
-int dirserv_add_own_fingerprint(crypto_pk_t *pk);
+#ifdef HAVE_MODULE_DIRAUTH
+int dirserv_load_fingerprint_file(void);
enum was_router_added_t dirserv_add_multiple_descriptors(
const char *desc, size_t desclen,
uint8_t purpose,
@@ -25,16 +28,86 @@ enum was_router_added_t dirserv_add_descriptor(routerinfo_t *ri,
const char **msg,
const char *source);
+int dirserv_would_reject_router(const routerstatus_t *rs);
int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
int complain,
int *valid_out);
+int dirserv_add_own_fingerprint(crypto_pk_t *pk);
uint32_t dirserv_router_get_status(const routerinfo_t *router,
const char **msg,
int severity);
void dirserv_set_node_flags_from_authoritative_status(node_t *node,
uint32_t authstatus);
-
-int dirserv_would_reject_router(const routerstatus_t *rs);
+#else
+static inline int
+dirserv_load_fingerprint_file(void)
+{
+ return 0;
+}
+static inline enum was_router_added_t
+dirserv_add_multiple_descriptors(const char *desc, size_t desclen,
+ uint8_t purpose,
+ const char *source,
+ const char **msg)
+{
+ (void)desc;
+ (void)desclen;
+ (void)purpose;
+ (void)source;
+ (void)msg;
+ return (enum was_router_added_t)0;
+}
+static inline enum was_router_added_t
+dirserv_add_descriptor(routerinfo_t *ri,
+ const char **msg,
+ const char *source)
+{
+ (void)ri;
+ (void)msg;
+ (void)source;
+ return (enum was_router_added_t)0;
+}
+static inline int
+dirserv_would_reject_router(const routerstatus_t *rs)
+{
+ (void)rs;
+ return 0;
+}
+static inline int
+authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
+ int complain,
+ int *valid_out)
+{
+ (void)ri;
+ (void)msg;
+ (void)complain;
+ (void)valid_out;
+ return 0;
+}
+static inline int
+dirserv_add_own_fingerprint(crypto_pk_t *pk)
+{
+ (void)pk;
+ return 0;
+}
+static inline uint32_t
+dirserv_router_get_status(const routerinfo_t *router,
+ const char **msg,
+ int severity)
+{
+ (void)router;
+ (void)msg;
+ (void)severity;
+ return 0;
+}
+static inline void
+dirserv_set_node_flags_from_authoritative_status(node_t *node,
+ uint32_t authstatus)
+{
+ (void)node;
+ (void)authstatus;
+}
+#endif
#ifdef TOR_UNIT_TESTS
STATIC int dirserv_router_has_valid_address(routerinfo_t *ri);
diff --git a/src/feature/dirauth/reachability.h b/src/feature/dirauth/reachability.h
index 873a3f9a23..8a83f0c493 100644
--- a/src/feature/dirauth/reachability.h
+++ b/src/feature/dirauth/reachability.h
@@ -24,13 +24,36 @@
#define REACHABILITY_TEST_CYCLE_PERIOD \
(REACHABILITY_TEST_INTERVAL*REACHABILITY_MODULO_PER_TEST)
+void dirserv_single_reachability_test(time_t now, routerinfo_t *router);
+void dirserv_test_reachability(time_t now);
+
+#ifdef HAVE_MODULE_DIRAUTH
+int dirserv_should_launch_reachability_test(const routerinfo_t *ri,
+ const routerinfo_t *ri_old);
void dirserv_orconn_tls_done(const tor_addr_t *addr,
uint16_t or_port,
const char *digest_rcvd,
const struct ed25519_public_key_t *ed_id_rcvd);
-int dirserv_should_launch_reachability_test(const routerinfo_t *ri,
- const routerinfo_t *ri_old);
-void dirserv_single_reachability_test(time_t now, routerinfo_t *router);
-void dirserv_test_reachability(time_t now);
+#else
+static inline int
+dirserv_should_launch_reachability_test(const routerinfo_t *ri,
+ const routerinfo_t *ri_old)
+{
+ (void)ri;
+ (void)ri_old;
+ return 0;
+}
+static inline void
+dirserv_orconn_tls_done(const tor_addr_t *addr,
+ uint16_t or_port,
+ const char *digest_rcvd,
+ const struct ed25519_public_key_t *ed_id_rcvd)
+{
+ (void)addr;
+ (void)or_port;
+ (void)digest_rcvd;
+ (void)ed_id_rcvd;
+}
+#endif
#endif /* !defined(TOR_REACHABILITY_H) */
diff --git a/src/feature/dirauth/shared_random.c b/src/feature/dirauth/shared_random.c
index 5ccf1a95e5..a45f0a29c3 100644
--- a/src/feature/dirauth/shared_random.c
+++ b/src/feature/dirauth/shared_random.c
@@ -90,7 +90,7 @@
#include "core/or/or.h"
#include "feature/dirauth/shared_random.h"
#include "app/config/config.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
#include "feature/nodelist/networkstatus.h"
diff --git a/src/feature/dirauth/shared_random_state.c b/src/feature/dirauth/shared_random_state.c
index f2a626c738..76befb0f5f 100644
--- a/src/feature/dirauth/shared_random_state.c
+++ b/src/feature/dirauth/shared_random_state.c
@@ -12,7 +12,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "lib/crypt_ops/crypto_util.h"
#include "feature/dirauth/dirvote.h"
#include "feature/nodelist/networkstatus.h"
diff --git a/src/feature/hs/hs_dos.c b/src/feature/hs/hs_dos.c
index 0ae36017f8..19794e09d3 100644
--- a/src/feature/hs/hs_dos.c
+++ b/src/feature/hs/hs_dos.c
@@ -29,7 +29,7 @@
#include "lib/evloop/token_bucket.h"
-#include "hs_dos.h"
+#include "feature/hs/hs_dos.h"
/* Default value of the allowed INTRODUCE2 cell rate per second. Above that
* value per second, the introduction is denied. */
diff --git a/src/lib/conf/confmacros.h b/src/lib/conf/confmacros.h
index 2a15f09aac..68121891f1 100644
--- a/src/lib/conf/confmacros.h
+++ b/src/lib/conf/confmacros.h
@@ -61,7 +61,7 @@
#define CONFIG_VAR_OBSOLETE(varname) \
{ .member = { .name = varname, .type = CONFIG_TYPE_OBSOLETE }, \
- .flags = CVFLAG_OBSOLETE \
+ .flags = CFLG_GROUP_OBSOLETE \
}
#endif /* !defined(TOR_LIB_CONF_CONFMACROS_H) */
diff --git a/src/lib/conf/conftypes.h b/src/lib/conf/conftypes.h
index 4609564b34..274065cff2 100644
--- a/src/lib/conf/conftypes.h
+++ b/src/lib/conf/conftypes.h
@@ -132,22 +132,58 @@ typedef struct struct_magic_decl_t {
} struct_magic_decl_t;
/**
- * Flag to indicate that an option is obsolete. Any attempt to set or
- * fetch this option should produce a warning.
+ * Flag to indicate that an option or type is "undumpable". An
+ * undumpable option is never saved to disk.
+ *
+ * For historical reasons its name is usually is prefixed with __.
+ **/
+#define CFLG_NODUMP (1u<<0)
+/**
+ * Flag to indicate that an option or type is "unlisted".
+ *
+ * We don't tell the controller about unlisted options when it asks for a
+ * list of them.
**/
-#define CVFLAG_OBSOLETE (1u<<0)
+#define CFLG_NOLIST (1u<<1)
/**
- * Flag to indicate that an option is undumpable. An undumpable option is
- * never saved to disk. For historical reasons it is prefixed with __ but
- * not with ___.
+ * Flag to indicate that an option or type is "unsettable".
+ *
+ * An unsettable option can never be set directly by name.
+ **/
+#define CFLG_NOSET (1u<<2)
+/**
+ * Flag to indicate that an option or type does not need to be copied when
+ * copying the structure that contains it.
+ *
+ * (Usually, if an option does not need to be copied, then either it contains
+ * no data, or the data that it does contain is completely contained within
+ * another option.)
**/
-#define CVFLAG_NODUMP (1u<<1)
+#define CFLG_NOCOPY (1u<<3)
+/**
+ * Flag to indicate that an option or type does not need to be compared
+ * when telling the controller about the differences between two
+ * configurations.
+ *
+ * (Usually, if an option does not need to be compared, then either it
+ * contains no data, or the data that it does contain is completely contained
+ * within another option.)
+ **/
+#define CFLG_NOCMP (1u<<4)
+/**
+ * Flag to indicate that an option or type should not be replaced when setting
+ * it.
+ *
+ * For most options, setting them replaces their old value. For some options,
+ * however, setting them appends to their old value.
+ */
+#define CFLG_NOREPLACE (1u<<5)
+
/**
- * Flag to indicate that an option is "invisible". An invisible option
- * is always undumpable, and we don't tell the controller about it.
- * For historical reasons it is prefixed with ___.
+ * A group of flags that should be set on all obsolete options and types.
**/
-#define CVFLAG_INVISIBLE (1u<<2)
+#define CFLG_GROUP_OBSOLETE \
+ (CFLG_NOCOPY|CFLG_NOCMP|CFLG_NODUMP|CFLG_NOSET|CFLG_NOLIST)
/** A variable allowed in the configuration file or on the command line. */
typedef struct config_var_t {
diff --git a/src/lib/confmgt/.may_include b/src/lib/confmgt/.may_include
index d85dbf6904..2564133917 100644
--- a/src/lib/confmgt/.may_include
+++ b/src/lib/confmgt/.may_include
@@ -7,3 +7,5 @@ lib/encoding/*.h
lib/log/*.h
lib/malloc/*.h
lib/string/*.h
+lib/testsupport/*.h
+ext/*.h
diff --git a/src/app/config/confparse.c b/src/lib/confmgt/confparse.c
index 0e941bab6c..08e562f654 100644
--- a/src/app/config/confparse.c
+++ b/src/lib/confmgt/confparse.c
@@ -23,7 +23,7 @@
#define CONFPARSE_PRIVATE
#include "orconfig.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "lib/confmgt/structvar.h"
#include "lib/confmgt/unitparse.h"
@@ -511,32 +511,112 @@ config_count_options(const config_mgr_t *mgr)
return smartlist_len(mgr->all_vars);
}
-bool
-config_var_is_cumulative(const config_var_t *var)
+/**
+ * Return true iff at least one bit from <b>flag</b> is set on <b>var</b>,
+ * either in <b>var</b>'s flags, or on the flags of its type.
+ **/
+static bool
+config_var_has_flag(const config_var_t *var, uint32_t flag)
{
- return struct_var_is_cumulative(&var->member);
+ uint32_t have_flags = var->flags | struct_var_get_flags(&var->member);
+
+ return (have_flags & flag) != 0;
}
+
+/**
+ * Return true if assigning a value to <b>var</b> replaces the previous
+ * value. Return false if assigning a value to <b>var</b> appends
+ * to the previous value.
+ **/
+static bool
+config_var_is_replaced_on_set(const config_var_t *var)
+{
+ return ! config_var_has_flag(var, CFLG_NOREPLACE);
+}
+
+/**
+ * Return true iff <b>var</b> may be assigned by name (e.g., via the
+ * CLI, the configuration files, or the controller API).
+ **/
bool
config_var_is_settable(const config_var_t *var)
{
- if (var->flags & CVFLAG_OBSOLETE)
- return false;
- return struct_var_is_settable(&var->member);
+ return ! config_var_has_flag(var, CFLG_NOSET);
}
-bool
-config_var_is_contained(const config_var_t *var)
+
+/**
+ * Return true iff the controller is allowed to fetch the value of
+ * <b>var</b>.
+ **/
+static bool
+config_var_is_gettable(const config_var_t *var)
{
- return struct_var_is_contained(&var->member);
+ /* Arguably, invisible or obsolete options should not be gettable. However,
+ * they have been gettable for a long time, and making them ungettable could
+ * have compatibility effects. For now, let's leave them alone.
+ */
+
+ // return ! config_var_has_flag(var, CVFLAG_OBSOLETE|CFGLAGS_INVISIBLE);
+ (void)var;
+ return true;
}
-bool
-config_var_is_invisible(const config_var_t *var)
+
+/**
+ * Return true iff we need to check <b>var</b> for changes when we are
+ * comparing config options for changes.
+ *
+ * A false result might mean that the variable is a derived variable, and that
+ * comparing the variable it derives from compares this one too-- or it might
+ * mean that there is no data to compare.
+ **/
+static bool
+config_var_should_list_changes(const config_var_t *var)
{
- return (var->flags & CVFLAG_INVISIBLE) != 0;
+ return ! config_var_has_flag(var, CFLG_NOCMP);
}
+
+/**
+ * Return true iff we need to copy the data for <b>var</b> when we are
+ * copying a config option.
+ *
+ * A false option might mean that the variable is a derived variable, and that
+ * copying the variable it derives from copies it-- or it might mean that
+ * there is no data to copy.
+ **/
+static bool
+config_var_needs_copy(const config_var_t *var)
+{
+ return ! config_var_has_flag(var, CFLG_NOCOPY);
+}
+
+/**
+ * Return true iff variable <b>var</b> should appear on list of variable
+ * names given to the controller or the CLI.
+ *
+ * (Note that this option is imperfectly obeyed. The
+ * --list-torrc-options command looks at the "settable" flag, whereas
+ * "GETINFO config/defaults" and "list_deprecated_*()" do not filter
+ * their results. It would be good for consistency to try to converge
+ * these behaviors in the future.)
+ **/
bool
+config_var_is_listable(const config_var_t *var)
+{
+ return ! config_var_has_flag(var, CFLG_NOLIST);
+}
+
+/**
+ * Return true iff variable <b>var</b> should be written out when we
+ * are writing our configuration to disk, to a controller, or via the
+ * --dump-config command.
+ *
+ * This option may be set because a variable is hidden, or because it is
+ * derived from another variable which will already be written out.
+ **/
+static bool
config_var_is_dumpable(const config_var_t *var)
{
- return (var->flags & CVFLAG_NODUMP) == 0;
+ return ! config_var_has_flag(var, CFLG_NODUMP);
}
/*
@@ -650,7 +730,8 @@ config_assign_line(const config_mgr_t *mgr, void *options,
if (!strlen(c->value)) {
/* reset or clear it, then return */
if (!clear_first) {
- if (config_var_is_cumulative(cvar) && c->command != CONFIG_LINE_CLEAR) {
+ if (! config_var_is_replaced_on_set(cvar) &&
+ c->command != CONFIG_LINE_CLEAR) {
/* We got an empty linelist from the torrc or command line.
As a special case, call this an error. Warn and ignore. */
log_warn(LD_CONFIG,
@@ -671,7 +752,7 @@ config_assign_line(const config_mgr_t *mgr, void *options,
// LCOV_EXCL_STOP
}
- if (options_seen && ! config_var_is_cumulative(cvar)) {
+ if (options_seen && config_var_is_replaced_on_set(cvar)) {
/* We're tracking which options we've seen, and this option is not
* supposed to occur more than once. */
tor_assert(var_index >= 0);
@@ -750,6 +831,11 @@ config_get_assigned_option(const config_mgr_t *mgr, const void *options,
log_warn(LD_CONFIG, "Unknown option '%s'. Failing.", key);
return NULL;
}
+ if (! config_var_is_gettable(var->cvar)) {
+ log_warn(LD_CONFIG, "Option '%s' is obsolete or unfetchable. Failing.",
+ key);
+ return NULL;
+ }
const void *object = config_mgr_get_obj(mgr, options, var->object_idx);
result = struct_var_kvencode(object, &var->cvar->member);
@@ -989,7 +1075,7 @@ config_get_changes(const config_mgr_t *mgr,
config_line_t *result = NULL;
config_line_t **next = &result;
SMARTLIST_FOREACH_BEGIN(mgr->all_vars, managed_var_t *, mv) {
- if (config_var_is_contained(mv->cvar)) {
+ if (! config_var_should_list_changes(mv->cvar)) {
/* something else will check this var, or it doesn't need checking */
continue;
}
@@ -1025,7 +1111,7 @@ config_dup(const config_mgr_t *mgr, const void *old)
newopts = config_new(mgr);
SMARTLIST_FOREACH_BEGIN(mgr->all_vars, managed_var_t *, mv) {
- if (config_var_is_contained(mv->cvar)) {
+ if (! config_var_needs_copy(mv->cvar)) {
// Something else will copy this option, or it doesn't need copying.
continue;
}
@@ -1092,10 +1178,6 @@ config_dump(const config_mgr_t *mgr, const void *default_options,
elements = smartlist_new();
SMARTLIST_FOREACH_BEGIN(mgr->all_vars, managed_var_t *, mv) {
int comment_option = 0;
- if (config_var_is_contained(mv->cvar)) {
- // Something else will dump this option, or it doesn't need dumping.
- continue;
- }
/* Don't save 'hidden' control variables. */
if (! config_var_is_dumpable(mv->cvar))
continue;
diff --git a/src/app/config/confparse.h b/src/lib/confmgt/confparse.h
index 6a7a567273..054348d8d4 100644
--- a/src/app/config/confparse.h
+++ b/src/lib/confmgt/confparse.h
@@ -189,11 +189,8 @@ const char *config_expand_abbrev(const config_mgr_t *mgr,
int command_line, int warn_obsolete);
void warn_deprecated_option(const char *what, const char *why);
-bool config_var_is_cumulative(const config_var_t *var);
bool config_var_is_settable(const config_var_t *var);
-bool config_var_is_contained(const config_var_t *var);
-bool config_var_is_invisible(const config_var_t *var);
-bool config_var_is_dumpable(const config_var_t *var);
+bool config_var_is_listable(const config_var_t *var);
/* Helper macros to compare an option across two configuration objects */
#define CFG_EQ_BOOL(a,b,opt) ((a)->opt == (b)->opt)
diff --git a/src/lib/confmgt/include.am b/src/lib/confmgt/include.am
index aa5b37fdb5..81cd868e5e 100644
--- a/src/lib/confmgt/include.am
+++ b/src/lib/confmgt/include.am
@@ -6,6 +6,7 @@ endif
# ADD_C_FILE: INSERT SOURCES HERE.
src_lib_libtor_confmgt_a_SOURCES = \
+ src/lib/confmgt/confparse.c \
src/lib/confmgt/structvar.c \
src/lib/confmgt/type_defs.c \
src/lib/confmgt/typedvar.c \
@@ -18,6 +19,7 @@ src_lib_libtor_confmgt_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
# ADD_C_FILE: INSERT HEADERS HERE.
noinst_HEADERS += \
+ src/lib/confmgt/confparse.h \
src/lib/confmgt/structvar.h \
src/lib/confmgt/type_defs.h \
src/lib/confmgt/typedvar.h \
diff --git a/src/lib/confmgt/structvar.c b/src/lib/confmgt/structvar.c
index 75edda2c38..de678d18c8 100644
--- a/src/lib/confmgt/structvar.c
+++ b/src/lib/confmgt/structvar.c
@@ -211,26 +211,11 @@ 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)
+/** Return all of the flags set for this struct member. */
+uint32_t
+struct_var_get_flags(const struct_member_t *member)
{
const var_type_def_t *def = get_type_def(member);
- return def ? def->is_contained : false;
+ return def ? def->flags : 0;
}
diff --git a/src/lib/confmgt/structvar.h b/src/lib/confmgt/structvar.h
index 9783d1ec27..bcb4b58c3f 100644
--- a/src/lib/confmgt/structvar.h
+++ b/src/lib/confmgt/structvar.h
@@ -17,6 +17,7 @@ struct struct_member_t;
struct config_line_t;
#include <stdbool.h>
+#include "lib/cc/torint.h"
void struct_set_magic(void *object,
const struct struct_magic_decl_t *decl);
@@ -41,9 +42,7 @@ void struct_var_mark_fragile(void *object,
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);
+uint32_t struct_var_get_flags(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 6b0eac7823..62c12fcddd 100644
--- a/src/lib/confmgt/type_defs.c
+++ b/src/lib/confmgt/type_defs.c
@@ -741,16 +741,22 @@ static const var_type_def_t type_definitions_table[] = {
[CONFIG_TYPE_CSV_INTERVAL] = { .name="TimeInterval",
.fns=&legacy_csv_interval_fns, },
[CONFIG_TYPE_LINELIST] = { .name="LineList", .fns=&linelist_fns,
- .is_cumulative=true},
+ .flags=CFLG_NOREPLACE },
+ /*
+ * A "linelist_s" is a derived view of a linelist_v: inspecting
+ * it gets part of a linelist_v, and setting it adds to the linelist_v.
+ */
[CONFIG_TYPE_LINELIST_S] = { .name="Dependent", .fns=&linelist_s_fns,
- .is_cumulative=true,
- .is_contained=true, },
+ .flags=CFLG_NOREPLACE|
+ /* The operations we disable here are
+ * handled by the linelist_v. */
+ CFLG_NOCOPY|CFLG_NOCMP|CFLG_NODUMP },
[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, }
+ .flags=CFLG_NOREPLACE|CFLG_NOSET },
+ [CONFIG_TYPE_OBSOLETE] = {
+ .name="Obsolete", .fns=&ignore_fns,
+ .flags=CFLG_GROUP_OBSOLETE,
+ }
};
/**
diff --git a/src/lib/confmgt/typedvar.c b/src/lib/confmgt/typedvar.c
index 43040e1e05..219a2d15bc 100644
--- a/src/lib/confmgt/typedvar.c
+++ b/src/lib/confmgt/typedvar.c
@@ -225,32 +225,3 @@ typed_var_mark_fragile(void *value, const var_type_def_t *def)
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;
-}
diff --git a/src/lib/confmgt/typedvar.h b/src/lib/confmgt/typedvar.h
index 23fd8c13e4..22f2e3c58e 100644
--- a/src/lib/confmgt/typedvar.h
+++ b/src/lib/confmgt/typedvar.h
@@ -35,8 +35,4 @@ struct config_line_t *typed_var_kvencode(const char *key, const void *value,
void typed_var_mark_fragile(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 4157cb8ff6..f1131ff116 100644
--- a/src/lib/confmgt/var_type_def_st.h
+++ b/src/lib/confmgt/var_type_def_st.h
@@ -151,17 +151,11 @@ 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;
+ /**
+ * A bitwise OR of one or more VTFLAG_* values, describing properties
+ * for all values of this type.
+ **/
+ uint32_t flags;
};
#endif /* !defined(TOR_LIB_CONFMGT_VAR_TYPE_DEF_ST_H) */
diff --git a/src/lib/err/backtrace.c b/src/lib/err/backtrace.c
index 75d5093c54..c2011285c0 100644
--- a/src/lib/err/backtrace.c
+++ b/src/lib/err/backtrace.c
@@ -172,7 +172,7 @@ crash_handler(int sig, siginfo_t *si, void *ctx_)
for (i=0; i < n_fds; ++i)
backtrace_symbols_fd(cb_buf, (int)depth, fds[i]);
- abort();
+ tor_raw_abort_();
}
/** Write a backtrace to all of the emergency-error fds. */
diff --git a/src/lib/err/torerr.c b/src/lib/err/torerr.c
index 48fcf35e06..0a4ee5d417 100644
--- a/src/lib/err/torerr.c
+++ b/src/lib/err/torerr.c
@@ -110,6 +110,14 @@ tor_log_get_sigsafe_err_fds(const int **out)
* Update the list of fds that get errors from inside a signal handler or
* other emergency condition. Ignore any beyond the first
* TOR_SIGSAFE_LOG_MAX_FDS.
+ *
+ * These fds must remain open even after the log module has shut down. (And
+ * they should remain open even while logs are being reconfigured.) Therefore,
+ * any fds closed by the log module should be dup()ed, and the duplicate fd
+ * should be given to the err module in fds. In particular, the log module
+ * closes the file log fds, but does not close the stdio log fds.
+ *
+ * If fds is NULL or n is 0, clears the list of error fds.
*/
void
tor_log_set_sigsafe_err_fds(const int *fds, int n)
@@ -118,8 +126,18 @@ tor_log_set_sigsafe_err_fds(const int *fds, int n)
n = TOR_SIGSAFE_LOG_MAX_FDS;
}
- memcpy(sigsafe_log_fds, fds, n * sizeof(int));
- n_sigsafe_log_fds = n;
+ /* Clear the entire array. This code mitigates against some race conditions,
+ * but there are still some races here:
+ * - err logs are disabled while the array is cleared, and
+ * - a thread can read the old value of n_sigsafe_log_fds, then read a
+ * partially written array.
+ * We could fix these races using atomics, but atomics use the err module. */
+ n_sigsafe_log_fds = 0;
+ memset(sigsafe_log_fds, 0, sizeof(sigsafe_log_fds));
+ if (fds && n > 0) {
+ memcpy(sigsafe_log_fds, fds, n * sizeof(int));
+ n_sigsafe_log_fds = n;
+ }
}
/**
@@ -133,6 +151,32 @@ tor_log_reset_sigsafe_err_fds(void)
}
/**
+ * Close the list of fds that get errors from inside a signal handler or
+ * other emergency condition. These fds are shared with the logging code:
+ * closing them flushes the log buffers, and prevents any further logging.
+ *
+ * This function closes stderr, so it should only be called immediately before
+ * process shutdown.
+ */
+void
+tor_log_close_sigsafe_err_fds(void)
+{
+ int n_fds, i;
+ const int *fds = NULL;
+
+ n_fds = tor_log_get_sigsafe_err_fds(&fds);
+ for (i = 0; i < n_fds; ++i) {
+ /* tor_log_close_sigsafe_err_fds_on_error() is called on error and on
+ * shutdown, so we can't log or take any useful action if close()
+ * fails. */
+ (void)close(fds[i]);
+ }
+
+ /* Don't even try logging, we've closed all the log fds. */
+ tor_log_set_sigsafe_err_fds(NULL, 0);
+}
+
+/**
* Set the granularity (in ms) to use when reporting fatal errors outside
* the logging system.
*/
@@ -171,6 +215,18 @@ tor_raw_assertion_failed_msg_(const char *file, int line, const char *expr,
tor_log_err_sigsafe_write("\n");
}
+/**
+ * Call the abort() function to kill the current process with a fatal
+ * error. But first, close the raw error file descriptors, so error messages
+ * are written before process termination.
+ **/
+void
+tor_raw_abort_(void)
+{
+ tor_log_close_sigsafe_err_fds();
+ abort();
+}
+
/* As format_{hex,dex}_number_sigsafe, but takes a <b>radix</b> argument
* in range 2..16 inclusive. */
static int
@@ -205,7 +261,7 @@ format_number_sigsafe(unsigned long x, char *buf, int buf_len,
unsigned digit = (unsigned) (x % radix);
if (cp <= buf) {
/* Not tor_assert(); see above. */
- abort();
+ tor_raw_abort_();
}
--cp;
*cp = "0123456789ABCDEF"[digit];
@@ -214,7 +270,7 @@ format_number_sigsafe(unsigned long x, char *buf, int buf_len,
/* NOT tor_assert; see above. */
if (cp != buf) {
- abort(); // LCOV_EXCL_LINE
+ tor_raw_abort_(); // LCOV_EXCL_LINE
}
return len;
diff --git a/src/lib/err/torerr.h b/src/lib/err/torerr.h
index c2da6697a9..0e839cb1ba 100644
--- a/src/lib/err/torerr.h
+++ b/src/lib/err/torerr.h
@@ -20,13 +20,13 @@
#define raw_assert(expr) STMT_BEGIN \
if (!(expr)) { \
tor_raw_assertion_failed_msg_(__FILE__, __LINE__, #expr, NULL); \
- abort(); \
+ tor_raw_abort_(); \
} \
STMT_END
#define raw_assert_unreached(expr) raw_assert(0)
#define raw_assert_unreached_msg(msg) STMT_BEGIN \
tor_raw_assertion_failed_msg_(__FILE__, __LINE__, "0", (msg)); \
- abort(); \
+ tor_raw_abort_(); \
STMT_END
void tor_raw_assertion_failed_msg_(const char *file, int line,
@@ -40,8 +40,11 @@ void tor_log_err_sigsafe(const char *m, ...);
int tor_log_get_sigsafe_err_fds(const int **out);
void tor_log_set_sigsafe_err_fds(const int *fds, int n);
void tor_log_reset_sigsafe_err_fds(void);
+void tor_log_close_sigsafe_err_fds(void);
void tor_log_sigsafe_err_set_granularity(int ms);
+void tor_raw_abort_(void) ATTR_NORETURN;
+
int format_hex_number_sigsafe(unsigned long x, char *buf, int max_len);
int format_dec_number_sigsafe(unsigned long x, char *buf, int max_len);
diff --git a/src/lib/err/torerr_sys.c b/src/lib/err/torerr_sys.c
index 3ab1b3c4e1..eb818004fb 100644
--- a/src/lib/err/torerr_sys.c
+++ b/src/lib/err/torerr_sys.c
@@ -27,13 +27,19 @@ subsys_torerr_initialize(void)
static void
subsys_torerr_shutdown(void)
{
- tor_log_reset_sigsafe_err_fds();
+ /* Stop handling signals with backtraces, then close the logs. */
clean_up_backtrace_handler();
+ /* We can't log any log messages after this point: we've closed all the log
+ * fds, including stdio. */
+ tor_log_close_sigsafe_err_fds();
}
const subsys_fns_t sys_torerr = {
.name = "err",
- .level = -100,
+ /* Low-level error handling is a diagnostic feature, we want it to init
+ * right after windows process security, and shutdown last.
+ * (Security never shuts down.) */
+ .level = -99,
.supported = true,
.initialize = subsys_torerr_initialize,
.shutdown = subsys_torerr_shutdown
diff --git a/src/lib/log/log.c b/src/lib/log/log.c
index 56f016eae4..be6f459554 100644
--- a/src/lib/log/log.c
+++ b/src/lib/log/log.c
@@ -225,6 +225,7 @@ int log_global_min_severity_ = LOG_NOTICE;
static void delete_log(logfile_t *victim);
static void close_log(logfile_t *victim);
+static void close_log_sigsafe(logfile_t *victim);
static char *domain_to_string(log_domain_mask_t domain,
char *buf, size_t buflen);
@@ -665,13 +666,24 @@ tor_log_update_sigsafe_err_fds(void)
const logfile_t *lf;
int found_real_stderr = 0;
- int fds[TOR_SIGSAFE_LOG_MAX_FDS];
+ /* log_fds and err_fds contain matching entries: log_fds are the fds used by
+ * the log module, and err_fds are the fds used by the err module.
+ * For stdio logs, the log_fd and err_fd values are identical,
+ * and the err module closes the fd on shutdown.
+ * For file logs, the err_fd is a dup() of the log_fd,
+ * and the log and err modules both close their respective fds on shutdown.
+ * (Once all fds representing a file are closed, the underlying file is
+ * closed.)
+ */
+ int log_fds[TOR_SIGSAFE_LOG_MAX_FDS];
+ int err_fds[TOR_SIGSAFE_LOG_MAX_FDS];
int n_fds;
LOCK_LOGS();
/* Reserve the first one for stderr. This is safe because when we daemonize,
- * we dup2 /dev/null to stderr, */
- fds[0] = STDERR_FILENO;
+ * we dup2 /dev/null to stderr.
+ * For stderr, log_fds and err_fds are the same. */
+ log_fds[0] = err_fds[0] = STDERR_FILENO;
n_fds = 1;
for (lf = logfiles; lf; lf = lf->next) {
@@ -685,25 +697,39 @@ tor_log_update_sigsafe_err_fds(void)
(LD_BUG|LD_GENERAL)) {
if (lf->fd == STDERR_FILENO)
found_real_stderr = 1;
- /* Avoid duplicates */
- if (int_array_contains(fds, n_fds, lf->fd))
+ /* Avoid duplicates by checking the log module fd against log_fds */
+ if (int_array_contains(log_fds, n_fds, lf->fd))
continue;
- fds[n_fds++] = lf->fd;
+ /* Update log_fds using the log module's fd */
+ log_fds[n_fds] = lf->fd;
+ if (lf->needs_close) {
+ /* File log fds are duplicated, because close_log() closes the log
+ * module's fd, and tor_log_close_sigsafe_err_fds() closes the err
+ * module's fd. Both refer to the same file. */
+ err_fds[n_fds] = dup(lf->fd);
+ } else {
+ /* stdio log fds are not closed by the log module.
+ * tor_log_close_sigsafe_err_fds() closes stdio logs. */
+ err_fds[n_fds] = lf->fd;
+ }
+ n_fds++;
if (n_fds == TOR_SIGSAFE_LOG_MAX_FDS)
break;
}
}
if (!found_real_stderr &&
- int_array_contains(fds, n_fds, STDOUT_FILENO)) {
+ int_array_contains(log_fds, n_fds, STDOUT_FILENO)) {
/* Don't use a virtual stderr when we're also logging to stdout. */
raw_assert(n_fds >= 2); /* Don't tor_assert inside log fns */
- fds[0] = fds[--n_fds];
+ --n_fds;
+ log_fds[0] = log_fds[n_fds];
+ err_fds[0] = err_fds[n_fds];
}
UNLOCK_LOGS();
- tor_log_set_sigsafe_err_fds(fds, n_fds);
+ tor_log_set_sigsafe_err_fds(err_fds, n_fds);
}
/** Add to <b>out</b> a copy of every currently configured log file name. Used
@@ -809,6 +835,30 @@ logs_free_all(void)
* that happened between here and the end of execution. */
}
+/** Close signal-safe log files.
+ * Closing the log files makes the process and OS flush log buffers.
+ *
+ * This function is safe to call from a signal handler. It should only be
+ * called when shutting down the log or err modules. It is currenly called
+ * by the err module, when terminating the process on an abnormal condition.
+ */
+void
+logs_close_sigsafe(void)
+{
+ logfile_t *victim, *next;
+ /* We can't LOCK_LOGS() in a signal handler, because it may call
+ * signal-unsafe functions. And we can't deallocate memory, either. */
+ next = logfiles;
+ logfiles = NULL;
+ while (next) {
+ victim = next;
+ next = next->next;
+ if (victim->needs_close) {
+ close_log_sigsafe(victim);
+ }
+ }
+}
+
/** Remove and free the log entry <b>victim</b> from the linked-list
* logfiles (it is probably present, but it might not be due to thread
* racing issues). After this function is called, the caller shouldn't
@@ -835,13 +885,26 @@ delete_log(logfile_t *victim)
}
/** Helper: release system resources (but not memory) held by a single
- * logfile_t. */
+ * signal-safe logfile_t. If the log's resources can not be released in
+ * a signal handler, does nothing. */
static void
-close_log(logfile_t *victim)
+close_log_sigsafe(logfile_t *victim)
{
if (victim->needs_close && victim->fd >= 0) {
+ /* We can't do anything useful here if close() fails: we're shutting
+ * down logging, and the err module only does fatal errors. */
close(victim->fd);
victim->fd = -1;
+ }
+}
+
+/** Helper: release system resources (but not memory) held by a single
+ * logfile_t. */
+static void
+close_log(logfile_t *victim)
+{
+ if (victim->needs_close) {
+ close_log_sigsafe(victim);
} else if (victim->is_syslog) {
#ifdef HAVE_SYSLOG_H
if (--syslog_count == 0) {
diff --git a/src/lib/log/log.h b/src/lib/log/log.h
index c4a27782c3..4291418eb6 100644
--- a/src/lib/log/log.h
+++ b/src/lib/log/log.h
@@ -173,6 +173,7 @@ void logs_set_domain_logging(int enabled);
int get_min_log_level(void);
void switch_logs_debug(void);
void logs_free_all(void);
+void logs_close_sigsafe(void);
void add_temp_log(int min_severity);
void close_temp_logs(void);
void rollback_log_changes(void);
diff --git a/src/lib/log/log_sys.c b/src/lib/log/log_sys.c
index d1080f2264..826358546a 100644
--- a/src/lib/log/log_sys.c
+++ b/src/lib/log/log_sys.c
@@ -29,6 +29,8 @@ subsys_logging_shutdown(void)
const subsys_fns_t sys_logging = {
.name = "log",
.supported = true,
+ /* Logging depends on threads, approx time, raw logging, and security.
+ * Most other lib modules depend on logging. */
.level = -90,
.initialize = subsys_logging_initialize,
.shutdown = subsys_logging_shutdown,
diff --git a/src/lib/log/util_bug.c b/src/lib/log/util_bug.c
index 76b97c1a08..0e99be35a4 100644
--- a/src/lib/log/util_bug.c
+++ b/src/lib/log/util_bug.c
@@ -11,6 +11,7 @@
#include "lib/log/util_bug.h"
#include "lib/log/log.h"
#include "lib/err/backtrace.h"
+#include "lib/err/torerr.h"
#ifdef TOR_UNIT_TESTS
#include "lib/smartlist_core/smartlist_core.h"
#include "lib/smartlist_core/smartlist_foreach.h"
@@ -161,16 +162,18 @@ tor_bug_occurred_(const char *fname, unsigned int line,
}
/**
- * Call the abort() function to kill the current process with a fatal
- * error.
+ * Call the tor_raw_abort_() function to close raw logs, then kill the current
+ * process with a fatal error. But first, close the file-based log file
+ * descriptors, so error messages are written before process termination.
*
* (This is a separate function so that we declare it in util_bug.h without
- * including stdlib in all the users of util_bug.h)
+ * including torerr.h in all the users of util_bug.h)
**/
void
tor_abort_(void)
{
- abort();
+ logs_close_sigsafe();
+ tor_raw_abort_();
}
#ifdef _WIN32
diff --git a/src/lib/malloc/map_anon.c b/src/lib/malloc/map_anon.c
index 0f6a4150c7..ae4edff769 100644
--- a/src/lib/malloc/map_anon.c
+++ b/src/lib/malloc/map_anon.c
@@ -27,6 +27,9 @@
#include <windows.h>
#endif
+#include <string.h>
+#include <errno.h>
+
/**
* Macro to get the high bytes of a size_t, if there are high bytes.
* Windows needs this; other operating systems define a size_t that does
@@ -108,7 +111,17 @@ static int
nodump_mem(void *mem, size_t sz)
{
#if defined(MADV_DONTDUMP)
- return madvise(mem, sz, MADV_DONTDUMP);
+ int rv = madvise(mem, sz, MADV_DONTDUMP);
+ if (rv == 0) {
+ return 0;
+ } else if (errno == ENOSYS || errno == EINVAL) {
+ return 0; // syscall not supported, or flag not supported.
+ } else {
+ tor_log_err_sigsafe("Unexpected error from madvise: ",
+ strerror(errno),
+ NULL);
+ return -1;
+ }
#else
(void) mem;
(void) sz;
@@ -136,18 +149,33 @@ noinherit_mem(void *mem, size_t sz, inherit_res_t *inherit_result_out)
return 0;
}
#endif /* defined(FLAG_ZERO) */
+
#ifdef FLAG_NOINHERIT
int r2 = MINHERIT(mem, sz, FLAG_NOINHERIT);
if (r2 == 0) {
*inherit_result_out = INHERIT_RES_DROP;
+ return 0;
}
- return r2;
-#else /* !(defined(FLAG_NOINHERIT)) */
+#endif /* defined(FLAG_NOINHERIT) */
+
+#if defined(FLAG_ZERO) || defined(FLAG_NOINHERIT)
+ /* At least one operation was tried, and neither succeeded. */
+
+ if (errno == ENOSYS || errno == EINVAL) {
+ /* Syscall not supported, or flag not supported. */
+ return 0;
+ } else {
+ tor_log_err_sigsafe("Unexpected error from minherit: ",
+ strerror(errno),
+ NULL);
+ return -1;
+ }
+#else
(void)inherit_result_out;
(void)mem;
(void)sz;
return 0;
-#endif /* defined(FLAG_NOINHERIT) */
+#endif
}
/**
diff --git a/src/lib/meminfo/meminfo.c b/src/lib/meminfo/meminfo.c
index f233188897..f4fa45167e 100644
--- a/src/lib/meminfo/meminfo.c
+++ b/src/lib/meminfo/meminfo.c
@@ -18,9 +18,6 @@
#include "lib/log/log.h"
#include "lib/malloc/malloc.h"
-#ifdef HAVE_SYS_SYSCTL_H
-#include <sys/sysctl.h>
-#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
@@ -36,6 +33,10 @@
#endif
#include <string.h>
+#if defined(HAVE_SYS_SYSCTL_H) && !defined(_WIN32) && !defined(__linux__)
+#include <sys/sysctl.h>
+#endif
+
DISABLE_GCC_WARNING(aggregate-return)
/** Call the platform malloc info function, and dump the results to the log at
* level <b>severity</b>. If no such function exists, do nothing. */
diff --git a/src/lib/net/network_sys.c b/src/lib/net/network_sys.c
index 9dfdb2b45a..e0a2625d73 100644
--- a/src/lib/net/network_sys.c
+++ b/src/lib/net/network_sys.c
@@ -37,7 +37,9 @@ subsys_network_shutdown(void)
const subsys_fns_t sys_network = {
.name = "network",
- .level = -90,
+ /* Network depends on logging, and a lot of other modules depend on network.
+ */
+ .level = -80,
.supported = true,
.initialize = subsys_network_initialize,
.shutdown = subsys_network_shutdown,
diff --git a/src/lib/process/winprocess_sys.c b/src/lib/process/winprocess_sys.c
index 48c0888658..ff9bc1ba04 100644
--- a/src/lib/process/winprocess_sys.c
+++ b/src/lib/process/winprocess_sys.c
@@ -58,6 +58,8 @@ subsys_winprocess_initialize(void)
const subsys_fns_t sys_winprocess = {
.name = "winprocess",
+ /* HeapEnableTerminationOnCorruption and setdeppolicy() are security
+ * features, we want them to run first. */
.level = -100,
.supported = WINPROCESS_SYS_ENABLED,
.initialize = subsys_winprocess_initialize,
diff --git a/src/lib/thread/compat_threads.c b/src/lib/thread/compat_threads.c
index 35cfeba64c..1c4a5c4e3f 100644
--- a/src/lib/thread/compat_threads.c
+++ b/src/lib/thread/compat_threads.c
@@ -122,6 +122,8 @@ subsys_threads_initialize(void)
const subsys_fns_t sys_threads = {
.name = "threads",
.supported = true,
+ /* Threads is used by logging, which is a diagnostic feature, we want it to
+ * init right after low-level error handling and approx time. */
.level = -95,
.initialize = subsys_threads_initialize,
};
diff --git a/src/lib/time/time_sys.c b/src/lib/time/time_sys.c
index b3feb7b46a..8b9aa2856c 100644
--- a/src/lib/time/time_sys.c
+++ b/src/lib/time/time_sys.c
@@ -20,7 +20,9 @@ subsys_time_initialize(void)
const subsys_fns_t sys_time = {
.name = "time",
- .level = -90,
+ /* Monotonic time depends on logging, and a lot of other modules depend on
+ * monotonic time. */
+ .level = -80,
.supported = true,
.initialize = subsys_time_initialize,
};
diff --git a/src/lib/wallclock/approx_time.c b/src/lib/wallclock/approx_time.c
index 7b32804026..77eeddaf56 100644
--- a/src/lib/wallclock/approx_time.c
+++ b/src/lib/wallclock/approx_time.c
@@ -54,6 +54,8 @@ subsys_wallclock_initialize(void)
const subsys_fns_t sys_wallclock = {
.name = "wallclock",
.supported = true,
- .level = -99,
+ /* Approximate time is a diagnostic feature, we want it to init right after
+ * low-level error handling. */
+ .level = -98,
.initialize = subsys_wallclock_initialize,
};
diff --git a/src/test/conf_examples/badnick_1/error b/src/test/conf_examples/badnick_1/error
new file mode 100644
index 0000000000..3e92ddc832
--- /dev/null
+++ b/src/test/conf_examples/badnick_1/error
@@ -0,0 +1 @@
+nicknames must be between 1 and 19 characters inclusive
diff --git a/src/test/conf_examples/badnick_1/torrc b/src/test/conf_examples/badnick_1/torrc
new file mode 100644
index 0000000000..41ee4894f1
--- /dev/null
+++ b/src/test/conf_examples/badnick_1/torrc
@@ -0,0 +1,2 @@
+# This nickname is too long; we won't accept it.
+Nickname TooManyCharactersInThisNickname
diff --git a/src/test/conf_examples/badnick_2/error b/src/test/conf_examples/badnick_2/error
new file mode 100644
index 0000000000..ceac99f012
--- /dev/null
+++ b/src/test/conf_examples/badnick_2/error
@@ -0,0 +1 @@
+must contain only the characters \[a-zA-Z0-9\]
diff --git a/src/test/conf_examples/badnick_2/torrc b/src/test/conf_examples/badnick_2/torrc
new file mode 100644
index 0000000000..07acc61698
--- /dev/null
+++ b/src/test/conf_examples/badnick_2/torrc
@@ -0,0 +1,2 @@
+# this nickname has spaces in it and won't work.
+Nickname has a space
diff --git a/src/test/conf_examples/contactinfo_notutf8/error b/src/test/conf_examples/contactinfo_notutf8/error
new file mode 100644
index 0000000000..6d165152ce
--- /dev/null
+++ b/src/test/conf_examples/contactinfo_notutf8/error
@@ -0,0 +1 @@
+ContactInfo config option must be UTF-8
diff --git a/src/test/conf_examples/contactinfo_notutf8/torrc b/src/test/conf_examples/contactinfo_notutf8/torrc
new file mode 100644
index 0000000000..2ee4d093c5
--- /dev/null
+++ b/src/test/conf_examples/contactinfo_notutf8/torrc
@@ -0,0 +1 @@
+ContactInfo ÄëÄëÄë@example.com
diff --git a/src/test/conf_examples/example_1/expected b/src/test/conf_examples/example_1/expected
new file mode 100644
index 0000000000..9d6688a565
--- /dev/null
+++ b/src/test/conf_examples/example_1/expected
@@ -0,0 +1,2 @@
+ContactInfo tor_tellini@example.com
+SocksPort 80
diff --git a/src/test/conf_examples/example_1/torrc b/src/test/conf_examples/example_1/torrc
new file mode 100644
index 0000000000..bff7fa0aa2
--- /dev/null
+++ b/src/test/conf_examples/example_1/torrc
@@ -0,0 +1,5 @@
+
+# Here is a simple example torrc.
+ SocksPort 80
+
+ContactInfo "tor_tellini@example.com"
diff --git a/src/test/conf_examples/example_2/error b/src/test/conf_examples/example_2/error
new file mode 100644
index 0000000000..ce18b68db4
--- /dev/null
+++ b/src/test/conf_examples/example_2/error
@@ -0,0 +1 @@
+Unknown option 'JumpingJellyjars'
diff --git a/src/test/conf_examples/example_2/torrc b/src/test/conf_examples/example_2/torrc
new file mode 100644
index 0000000000..8ec8133b24
--- /dev/null
+++ b/src/test/conf_examples/example_2/torrc
@@ -0,0 +1 @@
+JumpingJellyjars 1
diff --git a/src/test/conf_examples/example_3/cmdline b/src/test/conf_examples/example_3/cmdline
new file mode 100644
index 0000000000..5b2fadcebb
--- /dev/null
+++ b/src/test/conf_examples/example_3/cmdline
@@ -0,0 +1 @@
+--socksport 99
diff --git a/src/test/conf_examples/example_3/expected b/src/test/conf_examples/example_3/expected
new file mode 100644
index 0000000000..867fb8bcc8
--- /dev/null
+++ b/src/test/conf_examples/example_3/expected
@@ -0,0 +1 @@
+SocksPort 99
diff --git a/src/test/conf_examples/example_3/torrc b/src/test/conf_examples/example_3/torrc
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/example_3/torrc
diff --git a/src/test/conf_examples/include_1/expected b/src/test/conf_examples/include_1/expected
new file mode 100644
index 0000000000..4bbf52ce9f
--- /dev/null
+++ b/src/test/conf_examples/include_1/expected
@@ -0,0 +1,3 @@
+ContactInfo includefile@example.com
+Nickname nested
+ORPort 8008
diff --git a/src/test/conf_examples/include_1/included.inc b/src/test/conf_examples/include_1/included.inc
new file mode 100644
index 0000000000..8d1834345d
--- /dev/null
+++ b/src/test/conf_examples/include_1/included.inc
@@ -0,0 +1,4 @@
+
+ContactInfo includefile@example.com
+
+%include "nested.inc" \ No newline at end of file
diff --git a/src/test/conf_examples/include_1/nested.inc b/src/test/conf_examples/include_1/nested.inc
new file mode 100644
index 0000000000..789b044a2b
--- /dev/null
+++ b/src/test/conf_examples/include_1/nested.inc
@@ -0,0 +1,2 @@
+
+Nickname nested \ No newline at end of file
diff --git a/src/test/conf_examples/include_1/torrc b/src/test/conf_examples/include_1/torrc
new file mode 100644
index 0000000000..2ed4074f6e
--- /dev/null
+++ b/src/test/conf_examples/include_1/torrc
@@ -0,0 +1,4 @@
+
+%include "included.inc"
+
+ORPort 8008
diff --git a/src/test/conf_examples/large_1/expected b/src/test/conf_examples/large_1/expected
new file mode 100644
index 0000000000..5866f5823e
--- /dev/null
+++ b/src/test/conf_examples/large_1/expected
@@ -0,0 +1,159 @@
+AccountingMax 10737418240
+AccountingRule sum
+AccountingStart day 05:15
+Address 128.66.8.8
+AllowNonRFC953Hostnames 1
+AndroidIdentityTag droidy
+AutomapHostsOnResolve 1
+AutomapHostsSuffixes .onions
+AvoidDiskWrites 1
+BandwidthBurst 2147483647
+BandwidthRate 1610612736
+Bridge 128.66.1.10:80
+CacheDirectory /this-is-a-cache
+CellStatistics 1
+CircuitBuildTimeout 200
+CircuitsAvailableTimeout 10
+CircuitStreamTimeout 20
+ClientAutoIPv6ORPort 1
+ClientOnly 1
+ClientPreferIPv6DirPort 1
+ClientPreferIPv6ORPort 1
+ClientRejectInternalAddresses 0
+ClientUseIPv4 0
+ClientUseIPv6 1
+ConnDirectionStatistics 1
+ConnectionPadding 1
+ConnLimit 64
+ConsensusParams wombat=7
+ConstrainedSockets 1
+ConstrainedSockSize 10240
+ContactInfo long_config@example.com
+ControlPortFileGroupReadable 1
+ControlPort 9058
+CookieAuthentication 1
+CookieAuthFile /control/cookie
+CookieAuthFileGroupReadable 1
+CountPrivateBandwidth 1
+DataDirectory /data/dir
+DirAllowPrivateAddresses 1
+DirPolicy reject 128.66.1.1/32, accept *:*
+DirPortFrontPage /dirport/frontpage
+DirPort 99
+DirReqStatistics 0
+DisableDebuggerAttachment 0
+DisableNetwork 1
+DisableOOSCheck 0
+DNSPort 53535
+DormantCanceledByStartup 1
+DormantClientTimeout 1260
+DormantOnFirstStartup 1
+DormantTimeoutDisabledByIdleStreams 0
+DoSCircuitCreationBurst 1000
+DoSCircuitCreationDefenseTimePeriod 300
+DoSCircuitCreationDefenseType 2
+DoSCircuitCreationEnabled 1
+DoSCircuitCreationMinConnections 10
+DoSCircuitCreationRate 100
+DoSConnectionDefenseType 2
+DoSConnectionEnabled 1
+DoSConnectionMaxConcurrentCount 6
+DoSRefuseSingleHopClientRendezvous 0
+DownloadExtraInfo 1
+EnforceDistinctSubnets 0
+EntryNodes potrzebie,triffid,cromulent
+EntryStatistics 1
+ExcludeExitNodes blaznort,kriffid,zeppelin
+ExcludeNodes 128.66.7.6
+ExitNodes 128.66.7.7,128.66.128.0/17,exitexit
+ExitPolicy accept *:80,reject *:*
+ExitPolicyRejectLocalInterfaces 1
+ExitPolicyRejectPrivate 0
+ExitPortStatistics 1
+ExitRelay 1
+ExtendAllowPrivateAddresses 1
+ExtendByEd25519ID 1
+ExtORPortCookieAuthFile /foobar
+ExtORPort 99
+FascistFirewall 1
+FetchDirInfoEarly 1
+FetchDirInfoExtraEarly 1
+FetchUselessDescriptors 1
+FirewallPorts 80,443,999
+GeoIPExcludeUnknown 1
+GeoIPFile /geoip
+GuardfractionFile /gff
+GuardLifetime 691200
+HeartbeatPeriod 2700
+IPv6Exit 1
+KeepalivePeriod 540
+KeyDirectory /keyz
+KISTSchedRunInterval 1
+Log notice file /logfile
+Log info file /logfile-verbose
+LogTimeGranularity 60000
+LongLivedPorts 9090
+MainloopStats 1
+MapAddress www.example.com:10.0.0.6
+MaxAdvertisedBandwidth 100
+MaxCircuitDirtiness 3600
+MaxClientCircuitsPending 127
+MaxConsensusAgeForDiffs 2629728
+MaxMemInQueues 314572800
+MaxOnionQueueDelay 60000
+MaxUnparseableDescSizeToLog 1048576
+MiddleNodes grommit,truffle,parcheesi
+MyFamily $ffffffffffffffffffffffffffffffffffffffff
+NewCircuitPeriod 7200
+Nickname nickname
+NodeFamily $ffffffffffffffffffffffffffffffffffffffff,$dddddddddddddddddddddddddddddddddddddddd
+NumCPUs 3
+NumDirectoryGuards 4
+NumEntryGuards 5
+NumPrimaryGuards 8
+OfflineMasterKey 1
+OptimisticData 1
+ORPort 2222
+OutboundBindAddress 10.0.0.7
+OutboundBindAddressExit 10.0.0.8
+OutboundBindAddressOR 10.0.0.9
+PerConnBWBurst 10485760
+PerConnBWRate 102400
+PidFile /piddy
+ProtocolWarnings 1
+PublishHidServDescriptors 0
+PublishServerDescriptor 0
+ReachableAddresses 0.0.0.0, *:*
+ReachableDirAddresses 128.0.0.0/1
+ReachableORAddresses 128.0.0.0/8
+RejectPlaintextPorts 23
+RelayBandwidthBurst 10000
+RelayBandwidthRate 1000
+RendPostPeriod 600
+RephistTrackTime 600
+SafeLogging 0
+Schedulers Vanilla,KISTLite,Kist
+ShutdownWaitLength 10
+SigningKeyLifetime 4838400
+Socks5Proxy 128.66.99.99:99
+Socks5ProxyPassword flynn
+Socks5ProxyUsername spaceparanoids
+SocksPolicy accept 127.0.0.0/24, reject *:*
+SocksPort 9099
+SocksTimeout 600
+SSLKeyLifetime 86400
+StrictNodes 1
+SyslogIdentityTag tortor
+TestSocks 1
+TokenBucketRefillInterval 1000
+TrackHostExits www.example.com
+TrackHostExitsExpire 3600
+TruncateLogFile 1
+UnixSocksGroupWritable 1
+UpdateBridgesFromAuthority 1
+UseDefaultFallbackDirs 0
+UseGuardFraction 1
+UseMicrodescriptors 0
+VirtualAddrNetworkIPv4 18.66.0.0/16
+VirtualAddrNetworkIPv6 [ff00::]/16
+WarnPlaintextPorts 7,11,23,1001
diff --git a/src/test/conf_examples/large_1/torrc b/src/test/conf_examples/large_1/torrc
new file mode 100644
index 0000000000..e99acd9fb7
--- /dev/null
+++ b/src/test/conf_examples/large_1/torrc
@@ -0,0 +1,167 @@
+AccountingMax 10 GB
+AccountingRule sum
+AccountingStart day 05:15
+Address 128.66.8.8
+AllowNonRFC953Hostnames 1
+AndroidIdentityTag droidy
+AutomapHostsOnResolve 1
+AutomapHostsSuffixes .onions
+AvoidDiskWrites 1
+BandwidthBurst 2 GB
+BandwidthRate 1.5 GB
+Bridge 128.66.1.10:80
+CacheDirectory /this-is-a-cache
+CellStatistics 1
+CircuitBuildTimeout 200
+CircuitPadding 1
+CircuitsAvailableTimeout 10
+CircuitStreamTimeout 20
+ClientAutoIPv6ORPort 1
+ClientOnly 1
+ClientPreferIPv6DirPort 1
+ClientPreferIPv6ORPort 1
+ClientRejectInternalAddresses 0
+ClientUseIPv4 0
+ClientUseIPv6 1
+ConnDirectionStatistics 1
+ConnectionPadding 1
+ConnLimit 64
+ConsensusParams wombat=7
+ConstrainedSockets 1
+ConstrainedSockSize 10240
+ContactInfo long_config@example.com
+ControlPortFileGroupReadable 1
+ControlPort 9058
+CookieAuthentication 1
+CookieAuthFile /control/cookie
+CookieAuthFileGroupReadable 1
+CountPrivateBandwidth 1
+DataDirectory /data/dir
+DirAllowPrivateAddresses 1
+DirPolicy reject 128.66.1.1/32, accept *:*
+DirReqStatistics 0
+DirPort 99
+DirPortFrontPage /dirport/frontpage
+DisableDebuggerAttachment 0
+DisableNetwork 1
+DisableOOSCheck 0
+DNSPort 53535
+DormantCanceledByStartup 1
+DormantClientTimeout 21 minutes
+DormantOnFirstStartup 1
+DormantTimeoutDisabledByIdleStreams 0
+DoSCircuitCreationBurst 1000
+DoSCircuitCreationDefenseTimePeriod 5 minutes
+DoSCircuitCreationDefenseType 2
+DoSCircuitCreationEnabled 1
+DoSCircuitCreationMinConnections 10
+DoSCircuitCreationRate 100
+DoSConnectionDefenseType 2
+DoSConnectionEnabled 1
+DoSConnectionMaxConcurrentCount 6
+DoSRefuseSingleHopClientRendezvous 0
+DownloadExtraInfo 1
+EnforceDistinctSubnets 0
+EntryNodes potrzebie,triffid,cromulent
+EntryStatistics 1
+ExcludeExitNodes blaznort,kriffid,zeppelin
+ExcludeNodes 128.66.7.6
+ExitNodes 128.66.7.7,128.66.128.0/17,exitexit
+ExitPolicy accept *:80,reject *:*
+ExitPolicyRejectLocalInterfaces 1
+ExitPolicyRejectPrivate 0
+ExitPortStatistics 1
+ExitRelay 1
+ExtendAllowPrivateAddresses 1
+ExtendByEd25519ID 1
+ExtORPort 99
+ExtORPortCookieAuthFile /foobar
+ExtraInfoStatistics 1
+FascistFirewall 1
+FetchDirInfoEarly 1
+FetchDirInfoExtraEarly 1
+FetchHidServDescriptors 1
+FetchServerDescriptors 1
+FetchUselessDescriptors 1
+FirewallPorts 80,443,999
+GeoIPExcludeUnknown 1
+GeoIPFile /geoip
+GuardfractionFile /gff
+GuardLifetime 8 days
+HeartbeatPeriod 45 minutes
+IPv6Exit 1
+KeepalivePeriod 9 minutes
+KeyDirectory /keyz
+KISTSchedRunInterval 1 msec
+LearnCircuitBuildTimeout 1
+Log notice file /logfile
+Log info file /logfile-verbose
+LogTimeGranularity 1 minute
+LongLivedPorts 9090
+MainloopStats 1
+MapAddress www.example.com:10.0.0.6
+MaxAdvertisedBandwidth 100
+MaxCircuitDirtiness 1 hour
+MaxClientCircuitsPending 127
+MaxConsensusAgeForDiffs 1 month
+MaxMemInQueues 300 MB
+MaxOnionQueueDelay 60 seconds
+MaxUnparseableDescSizeToLog 1 MB
+MiddleNodes grommit, truffle, parcheesi
+MyFamily $ffffffffffffffffffffffffffffffffffffffff
+NewCircuitPeriod 2 hours
+Nickname nickname
+NodeFamily $ffffffffffffffffffffffffffffffffffffffff,$dddddddddddddddddddddddddddddddddddddddd
+NumCPUs 3
+NumDirectoryGuards 4
+NumEntryGuards 5
+NumPrimaryGuards 8
+OfflineMasterKey 1
+OptimisticData 1
+ORPort 2222
+OutboundBindAddress 10.0.0.7
+OutboundBindAddressExit 10.0.0.8
+OutboundBindAddressOR 10.0.0.9
+PaddingStatistics 1
+PerConnBWBurst 10 MB
+PerConnBWRate 100 kb
+PidFile /piddy
+ProtocolWarnings 1
+PublishHidServDescriptors 0
+PublishServerDescriptor 0
+ReachableAddresses 0.0.0.0, *:*
+ReachableDirAddresses 128.0.0.0/1
+ReachableORAddresses 128.0.0.0/8
+RejectPlaintextPorts 23
+RelayBandwidthBurst 10000
+RelayBandwidthRate 1000
+RendPostPeriod 10 minutes
+RephistTrackTime 10 minutes
+SafeLogging 0
+SafeSocks 0
+Schedulers Vanilla,KISTLite,Kist
+ShutdownWaitLength 10 seconds
+SigningKeyLifetime 8 weeks
+Socks5Proxy 128.66.99.99:99
+Socks5ProxyPassword flynn
+Socks5ProxyUsername spaceparanoids
+SocksPolicy accept 127.0.0.0/24, reject *:*
+SocksPort 9099
+SocksTimeout 10 minutes
+SSLKeyLifetime 1 day
+StrictNodes 1
+SyslogIdentityTag tortor
+TestSocks 1
+TokenBucketRefillInterval 1 second
+TrackHostExits www.example.com
+TrackHostExitsExpire 1 hour
+TruncateLogFile 1
+UnixSocksGroupWritable 1
+UpdateBridgesFromAuthority 1
+UseDefaultFallbackDirs 0
+UseEntryGuards 1
+UseGuardFraction 1
+UseMicrodescriptors 0
+VirtualAddrNetworkIPv4 18.66.0.0/16
+VirtualAddrNetworkIPv6 [ff00::]/16
+WarnPlaintextPorts 7,11,23,1001
diff --git a/src/test/conf_examples/ops_1/cmdline b/src/test/conf_examples/ops_1/cmdline
new file mode 100644
index 0000000000..2bb9bfa132
--- /dev/null
+++ b/src/test/conf_examples/ops_1/cmdline
@@ -0,0 +1 @@
+ORPort 1000
diff --git a/src/test/conf_examples/ops_1/expected b/src/test/conf_examples/ops_1/expected
new file mode 100644
index 0000000000..84be6a70e2
--- /dev/null
+++ b/src/test/conf_examples/ops_1/expected
@@ -0,0 +1,2 @@
+Nickname Unnamed
+ORPort 1000
diff --git a/src/test/conf_examples/ops_1/torrc b/src/test/conf_examples/ops_1/torrc
new file mode 100644
index 0000000000..daf8ae60fe
--- /dev/null
+++ b/src/test/conf_examples/ops_1/torrc
@@ -0,0 +1,3 @@
+# We'll replace this option on the command line.
+
+ORPort 9999
diff --git a/src/test/conf_examples/ops_2/cmdline b/src/test/conf_examples/ops_2/cmdline
new file mode 100644
index 0000000000..fdd48a045c
--- /dev/null
+++ b/src/test/conf_examples/ops_2/cmdline
@@ -0,0 +1 @@
+/ORPort
diff --git a/src/test/conf_examples/ops_2/expected b/src/test/conf_examples/ops_2/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/ops_2/expected
diff --git a/src/test/conf_examples/ops_2/torrc b/src/test/conf_examples/ops_2/torrc
new file mode 100644
index 0000000000..21fcc93f9a
--- /dev/null
+++ b/src/test/conf_examples/ops_2/torrc
@@ -0,0 +1,3 @@
+# We'll remove this option on the command line, and not replace it.
+
+ORPort 9999
diff --git a/src/test/conf_examples/ops_3/cmdline b/src/test/conf_examples/ops_3/cmdline
new file mode 100644
index 0000000000..e4965d26f8
--- /dev/null
+++ b/src/test/conf_examples/ops_3/cmdline
@@ -0,0 +1 @@
++ORPort 1000
diff --git a/src/test/conf_examples/ops_3/expected b/src/test/conf_examples/ops_3/expected
new file mode 100644
index 0000000000..569d26b577
--- /dev/null
+++ b/src/test/conf_examples/ops_3/expected
@@ -0,0 +1,3 @@
+Nickname Unnamed
+ORPort 9999
+ORPort 1000
diff --git a/src/test/conf_examples/ops_3/torrc b/src/test/conf_examples/ops_3/torrc
new file mode 100644
index 0000000000..14adf87d7f
--- /dev/null
+++ b/src/test/conf_examples/ops_3/torrc
@@ -0,0 +1,3 @@
+# We will extend this option on the command line
+
+ORPort 9999
diff --git a/src/test/conf_examples/ops_4/expected b/src/test/conf_examples/ops_4/expected
new file mode 100644
index 0000000000..bf52f6a330
--- /dev/null
+++ b/src/test/conf_examples/ops_4/expected
@@ -0,0 +1,2 @@
+Nickname Unnamed
+ORPort 9099
diff --git a/src/test/conf_examples/ops_4/torrc b/src/test/conf_examples/ops_4/torrc
new file mode 100644
index 0000000000..dcec2aa95d
--- /dev/null
+++ b/src/test/conf_examples/ops_4/torrc
@@ -0,0 +1,3 @@
+# This value is unadorned, so replaces the one from defaults.torrc.
+
+ORPort 9099
diff --git a/src/test/conf_examples/ops_4/torrc.defaults b/src/test/conf_examples/ops_4/torrc.defaults
new file mode 100644
index 0000000000..04cd0393c6
--- /dev/null
+++ b/src/test/conf_examples/ops_4/torrc.defaults
@@ -0,0 +1 @@
+ORPort 9000
diff --git a/src/test/conf_examples/ops_5/expected b/src/test/conf_examples/ops_5/expected
new file mode 100644
index 0000000000..288721da53
--- /dev/null
+++ b/src/test/conf_examples/ops_5/expected
@@ -0,0 +1,3 @@
+Nickname Unnamed
+ORPort 9000
+ORPort 9099
diff --git a/src/test/conf_examples/ops_5/torrc b/src/test/conf_examples/ops_5/torrc
new file mode 100644
index 0000000000..3284fc1c55
--- /dev/null
+++ b/src/test/conf_examples/ops_5/torrc
@@ -0,0 +1,3 @@
+# This value has a plus, and so extends the one from defaults.torrc.
+
++ORPort 9099
diff --git a/src/test/conf_examples/ops_5/torrc.defaults b/src/test/conf_examples/ops_5/torrc.defaults
new file mode 100644
index 0000000000..04cd0393c6
--- /dev/null
+++ b/src/test/conf_examples/ops_5/torrc.defaults
@@ -0,0 +1 @@
+ORPort 9000
diff --git a/src/test/conf_examples/ops_6/expected b/src/test/conf_examples/ops_6/expected
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/src/test/conf_examples/ops_6/expected
diff --git a/src/test/conf_examples/ops_6/torrc b/src/test/conf_examples/ops_6/torrc
new file mode 100644
index 0000000000..4d51caaff7
--- /dev/null
+++ b/src/test/conf_examples/ops_6/torrc
@@ -0,0 +1,3 @@
+# This value has a slash, and so clears the one from defaults.torrc.
+
+/ORPort
diff --git a/src/test/conf_examples/ops_6/torrc.defaults b/src/test/conf_examples/ops_6/torrc.defaults
new file mode 100644
index 0000000000..04cd0393c6
--- /dev/null
+++ b/src/test/conf_examples/ops_6/torrc.defaults
@@ -0,0 +1 @@
+ORPort 9000
diff --git a/src/test/conf_examples/relpath_rad/error b/src/test/conf_examples/relpath_rad/error
new file mode 100644
index 0000000000..e131744475
--- /dev/null
+++ b/src/test/conf_examples/relpath_rad/error
@@ -0,0 +1 @@
+RunAsDaemon is not compatible with relative paths.
diff --git a/src/test/conf_examples/relpath_rad/torrc b/src/test/conf_examples/relpath_rad/torrc
new file mode 100644
index 0000000000..fe02441c3f
--- /dev/null
+++ b/src/test/conf_examples/relpath_rad/torrc
@@ -0,0 +1,4 @@
+
+# Relative-path data directories are incompatible with RunAsDaemon
+DataDirectory ./datadir
+RunAsDaemon 1
diff --git a/src/test/include.am b/src/test/include.am
index 1ec54a286f..2dd4d8c583 100644
--- a/src/test/include.am
+++ b/src/test/include.am
@@ -23,7 +23,9 @@ TESTSCRIPTS = \
src/test/test_workqueue_pipe.sh \
src/test/test_workqueue_pipe2.sh \
src/test/test_workqueue_socketpair.sh \
- src/test/test_switch_id.sh
+ src/test/test_switch_id.sh \
+ src/test/test_cmdline.sh \
+ src/test/test_parseconf.sh
if USE_RUST
TESTSCRIPTS += \
@@ -412,7 +414,9 @@ EXTRA_DIST += \
src/test/test_workqueue_efd2.sh \
src/test/test_workqueue_pipe.sh \
src/test/test_workqueue_pipe2.sh \
- src/test/test_workqueue_socketpair.sh
+ src/test/test_workqueue_socketpair.sh \
+ src/test/test_cmdline.sh \
+ src/test/test_parseconf.sh
test-rust:
$(TESTS_ENVIRONMENT) "$(abs_top_srcdir)/src/test/test_rust.sh"
diff --git a/src/test/test_addr.c b/src/test/test_addr.c
index 0f50a43615..f99e3be8f5 100644
--- a/src/test/test_addr.c
+++ b/src/test/test_addr.c
@@ -731,10 +731,6 @@ test_addr_ip6_helpers(void *arg)
#define TEST_ADDR_PARSE_FMT(addr_str, expect_family, fmt_decorated, \
expect_str) \
STMT_BEGIN \
- int r; \
- tor_addr_t addr; \
- char buf[TOR_ADDR_BUF_LEN]; \
- const char *sv; \
r = tor_addr_parse(&addr, addr_str); \
tt_int_op(r, OP_EQ, expect_family); \
sv = tor_addr_to_str(buf, &addr, sizeof(buf), fmt_decorated); \
@@ -747,8 +743,6 @@ test_addr_ip6_helpers(void *arg)
*/
#define TEST_ADDR_PARSE_XFAIL(addr_str) \
STMT_BEGIN \
- int r; \
- tor_addr_t addr; \
r = tor_addr_parse(&addr, addr_str); \
tt_int_op(r, OP_EQ, -1); \
tt_assert(tor_addr_is_null(&addr)); \
@@ -762,11 +756,6 @@ test_addr_ip6_helpers(void *arg)
#define TEST_ADDR_PORT_PARSE_FMT(addr_port_str, default_port, expect_family, \
fmt_decorated, expect_str, expect_port) \
STMT_BEGIN \
- int r; \
- tor_addr_t addr; \
- uint16_t port; \
- char buf[TOR_ADDR_BUF_LEN]; \
- const char *sv; \
r = tor_addr_port_parse(LOG_DEBUG, addr_port_str, &addr, &port, \
default_port); \
tt_int_op(r, OP_EQ, 0); \
@@ -783,9 +772,6 @@ test_addr_ip6_helpers(void *arg)
*/
#define TEST_ADDR_PORT_PARSE_XFAIL(addr_port_str, default_port) \
STMT_BEGIN \
- int r; \
- tor_addr_t addr; \
- uint16_t port; \
r = tor_addr_port_parse(LOG_DEBUG, addr_port_str, &addr, &port, \
default_port); \
tt_int_op(r, OP_EQ, -1); \
@@ -799,8 +785,6 @@ test_addr_ip6_helpers(void *arg)
*/
#define TEST_ADDR_V4_LOOKUP_HOSTNAME(addr_str, expect_str) \
STMT_BEGIN \
- int r; \
- uint32_t addr32h; \
r = tor_lookup_hostname(addr_str, &addr32h); \
tt_int_op(r, OP_EQ, 0); \
tt_str_op(fmt_addr32(addr32h), OP_EQ, expect_str); \
@@ -812,8 +796,6 @@ test_addr_ip6_helpers(void *arg)
*/
#define TEST_ADDR_V4_LOOKUP_XFAIL(bad_str) \
STMT_BEGIN \
- int r; \
- uint32_t addr32h; \
r = tor_lookup_hostname(bad_str, &addr32h); \
tt_int_op(r, OP_EQ, -1); \
tt_int_op(addr32h, OP_EQ, 0); \
@@ -828,8 +810,6 @@ test_addr_ip6_helpers(void *arg)
*/
#define TEST_HOST_V4_LOOKUP(host_str) \
STMT_BEGIN \
- int r; \
- uint32_t addr32h; \
r = tor_lookup_hostname(host_str, &addr32h); \
tt_int_op(r, OP_GE, -1); \
tt_int_op(r, OP_LE, 1); \
@@ -845,10 +825,6 @@ test_addr_ip6_helpers(void *arg)
#define TEST_ADDR_LOOKUP_FMT(addr_str, require_family, expect_family, \
fmt_decorated, expect_str) \
STMT_BEGIN \
- int r; \
- tor_addr_t addr; \
- char buf[TOR_ADDR_BUF_LEN]; \
- const char *sv; \
r = tor_addr_lookup(addr_str, require_family, &addr); \
tt_int_op(r, OP_EQ, 0); \
tt_int_op(tor_addr_family(&addr), OP_EQ, expect_family); \
@@ -863,8 +839,6 @@ test_addr_ip6_helpers(void *arg)
*/
#define TEST_ADDR_LOOKUP_XFAIL(bad_str, require_family) \
STMT_BEGIN \
- int r; \
- tor_addr_t addr; \
r = tor_addr_lookup(bad_str, require_family, &addr); \
tt_int_op(r, OP_EQ, -1); \
tt_assert(tor_addr_is_null(&addr)); \
@@ -879,8 +853,6 @@ test_addr_ip6_helpers(void *arg)
*/
#define TEST_HOST_LOOKUP(host_str, require_family) \
STMT_BEGIN \
- int r; \
- tor_addr_t addr; \
r = tor_addr_lookup(host_str, require_family, &addr); \
tt_int_op(r, OP_GE, -1); \
tt_int_op(r, OP_LE, 1); \
@@ -897,11 +869,6 @@ test_addr_ip6_helpers(void *arg)
#define TEST_ADDR_PORT_LOOKUP_FMT(addr_port_str, expect_family, \
fmt_decorated, expect_str, expect_port) \
STMT_BEGIN \
- int r; \
- tor_addr_t addr; \
- uint16_t port; \
- char buf[TOR_ADDR_BUF_LEN]; \
- const char *sv; \
r = tor_addr_port_lookup(addr_port_str, &addr, &port); \
tt_int_op(r, OP_EQ, 0); \
tt_int_op(tor_addr_family(&addr), OP_EQ, expect_family); \
@@ -918,9 +885,6 @@ test_addr_ip6_helpers(void *arg)
*/
#define TEST_ADDR_PORT_LOOKUP_XFAIL(bad_str) \
STMT_BEGIN \
- int r; \
- tor_addr_t addr; \
- uint16_t port; \
r = tor_addr_port_lookup(bad_str, &addr, &port); \
tt_int_op(r, OP_EQ, -1); \
tt_assert(tor_addr_is_null(&addr)); \
@@ -939,9 +903,6 @@ test_addr_ip6_helpers(void *arg)
*/
#define TEST_HOST_PORT_LOOKUP(host_port_str, expect_success_port) \
STMT_BEGIN \
- int r; \
- tor_addr_t addr; \
- uint16_t port; \
r = tor_addr_port_lookup(host_port_str, &addr, &port); \
tt_int_op(r, OP_GE, -1); \
tt_int_op(r, OP_LE, 0); \
@@ -1162,10 +1123,16 @@ test_addr_ip6_helpers(void *arg)
TEST_ADDR_LOOKUP_XFAIL(host_port_str, AF_INET6); \
STMT_END
-/** Test tor_addr_parse() and tor_addr_port_parse(). */
static void
-test_addr_parse(void *arg)
+test_addr_parse_canonical(void *arg)
{
+ int r;
+ tor_addr_t addr;
+ uint16_t port;
+ const char *sv;
+ uint32_t addr32h;
+ char buf[TOR_ADDR_BUF_LEN];
+
(void)arg;
/* Correct calls. */
@@ -1185,6 +1152,22 @@ test_addr_parse(void *arg)
TEST_ADDR_V6_PARSE_CANONICAL("::", 0);
TEST_ADDR_V6_PARSE_CANONICAL("2::", 0);
TEST_ADDR_V6_PARSE_CANONICAL("11:22:33:44:55:66:77:88", 0);
+ done:
+ ;
+}
+
+/** Test tor_addr_parse() and tor_addr_port_parse(). */
+static void
+test_addr_parse(void *arg)
+{
+ int r;
+ tor_addr_t addr;
+ uint16_t port;
+ const char *sv;
+ uint32_t addr32h;
+ char buf[TOR_ADDR_BUF_LEN];
+
+ (void)arg;
/* IPv6-mapped IPv4 addresses. Tor doesn't really use these. */
TEST_ADDR_V6_PARSE("11:22:33:44:55:66:1.2.3.4", 0,
@@ -1669,6 +1652,7 @@ struct testcase_t addr_tests[] = {
ADDR_LEGACY(basic),
ADDR_LEGACY(ip6_helpers),
ADDR_LEGACY(parse),
+ ADDR_LEGACY(parse_canonical),
{ "virtaddr", test_virtaddrmap, 0, NULL, NULL },
{ "virtaddr_persist", test_virtaddrmap_persist, TT_FORK, NULL, NULL },
{ "localname", test_addr_localname, 0, NULL, NULL },
diff --git a/src/test/test_btrack.c b/src/test/test_btrack.c
index 21e88a57b6..80da7829ae 100644
--- a/src/test/test_btrack.c
+++ b/src/test/test_btrack.c
@@ -4,7 +4,7 @@
#include "core/or/or.h"
#include "test/test.h"
-#include "test_helpers.h"
+#include "test/test_helpers.h"
#include "test/log_test_helpers.h"
#define OCIRC_EVENT_PRIVATE
diff --git a/src/test/test_cmdline.sh b/src/test/test_cmdline.sh
new file mode 100755
index 0000000000..cf758c3851
--- /dev/null
+++ b/src/test/test_cmdline.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+umask 077
+set -e
+
+if [ $# -ge 1 ]; then
+ TOR_BINARY="${1}"
+ shift
+else
+ TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}"
+fi
+
+echo "TOR BINARY IS ${TOR_BINARY}"
+
+die() { echo "$1" >&2 ; exit 5; }
+
+echo "A"
+
+DATA_DIR=$(mktemp -d -t tor_cmdline_tests.XXXXXX)
+trap 'rm -rf "$DATA_DIR"' 0
+
+# 1. Test list-torrc-options.
+OUT="${DATA_DIR}/output"
+
+echo "B"
+"${TOR_BINARY}" --list-torrc-options > "$OUT"
+
+echo "C"
+
+# regular options are given.
+grep -i "SocksPort" "$OUT" >/dev/null || die "Did not find SocksPort"
+
+
+echo "D"
+
+# unlisted options are given, since they do not have the NOSET flag.
+grep -i "__SocksPort" "$OUT" > /dev/null || die "Did not find __SocksPort"
+
+echo "E"
+
+# unsettable options are not given.
+if grep -i "DisableIOCP" "$OUT" /dev/null; then
+ die "Found DisableIOCP"
+fi
+if grep -i "HiddenServiceOptions" "$OUT" /dev/null ; then
+ die "Found HiddenServiceOptions"
+fi
+echo "OK"
diff --git a/src/test/test_config.c b/src/test/test_config.c
index 58e05e5094..78f9ae9c3f 100644
--- a/src/test/test_config.c
+++ b/src/test/test_config.c
@@ -16,7 +16,7 @@
#include "core/or/circuitmux_ewma.h"
#include "core/or/circuitbuild.h"
#include "app/config/config.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "test/test.h"
@@ -5983,6 +5983,31 @@ test_config_kvline_parse(void *arg)
tor_free(enc);
}
+static void
+test_config_getinfo_config_names(void *arg)
+{
+ (void)arg;
+ char *answer = NULL;
+ const char *error = NULL;
+ int rv;
+
+ rv = getinfo_helper_config(NULL, "config/names", &answer, &error);
+ tt_int_op(rv, OP_EQ, 0);
+ tt_ptr_op(error, OP_EQ, NULL);
+
+ // ContactInfo should be listed.
+ tt_assert(strstr(answer, "\nContactInfo String\n"));
+
+ // V1AuthoritativeDirectory should not be listed, since it is obsolete.
+ tt_assert(! strstr(answer, "V1AuthoritativeDirectory"));
+
+ // ___UsingTestNetworkDefaults should not be listed, since it is invisible.
+ tt_assert(! strstr(answer, "UsingTestNetworkDefaults"));
+
+ done:
+ tor_free(answer);
+}
+
#define CONFIG_TEST(name, flags) \
{ #name, test_config_ ## name, flags, NULL, NULL }
@@ -6035,5 +6060,6 @@ struct testcase_t config_tests[] = {
CONFIG_TEST(compute_max_mem_in_queues, 0),
CONFIG_TEST(extended_fmt, 0),
CONFIG_TEST(kvline_parse, 0),
+ CONFIG_TEST(getinfo_config_names, 0),
END_OF_TESTCASES
};
diff --git a/src/test/test_confmgr.c b/src/test/test_confmgr.c
index 5f73d9754b..d5c73b48e4 100644
--- a/src/test/test_confmgr.c
+++ b/src/test/test_confmgr.c
@@ -13,7 +13,7 @@
#include "core/or/or.h"
#include "lib/encoding/confline.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "test/test.h"
#include "test/log_test_helpers.h"
diff --git a/src/test/test_confparse.c b/src/test/test_confparse.c
index f04853af72..5f29a22c10 100644
--- a/src/test/test_confparse.c
+++ b/src/test/test_confparse.c
@@ -14,7 +14,7 @@
#include "core/or/or.h"
#include "lib/encoding/confline.h"
#include "feature/nodelist/routerset.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "test/test.h"
#include "test/log_test_helpers.h"
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 17d6db1e4d..6329ff7750 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -26,7 +26,7 @@
#include "core/or/or.h"
#include "app/config/config.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "core/mainloop/connection.h"
#include "core/or/relay.h"
#include "core/or/versions.h"
diff --git a/src/test/test_entryconn.c b/src/test/test_entryconn.c
index fc7c5d5800..8f2d507743 100644
--- a/src/test/test_entryconn.c
+++ b/src/test/test_entryconn.c
@@ -11,7 +11,7 @@
#include "feature/client/addressmap.h"
#include "app/config/config.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "core/mainloop/connection.h"
#include "core/or/connection_edge.h"
#include "feature/nodelist/nodelist.h"
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index c8dd4b03ea..d59b1c7153 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -18,7 +18,7 @@
#include "core/or/circuitlist.h"
#include "core/or/circuitbuild.h"
#include "app/config/config.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "feature/dircommon/directory.h"
#include "feature/dirclient/dirclient.h"
@@ -1734,7 +1734,8 @@ test_entry_guard_manage_primary(void *arg)
dir_info_str =guard_selection_get_err_str_if_dir_info_missing(gs, 1, 2, 3);
tt_str_op(dir_info_str, OP_EQ,
"We're missing descriptors for 1/2 of our primary entry guards "
- "(total microdescriptors: 2/3).");
+ "(total microdescriptors: 2/3). That's ok. We will try to fetch "
+ "missing descriptors soon.");
tor_free(dir_info_str);
}
diff --git a/src/test/test_helpers.c b/src/test/test_helpers.c
index 31a6540efc..8eb3c2c928 100644
--- a/src/test/test_helpers.c
+++ b/src/test/test_helpers.c
@@ -16,7 +16,7 @@
#include "lib/buf/buffers.h"
#include "app/config/config.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "app/main/subsysmgr.h"
#include "core/mainloop/connection.h"
#include "lib/crypt_ops/crypto_rand.h"
diff --git a/src/test/test_options.c b/src/test/test_options.c
index a6bccdc524..0747a2e062 100644
--- a/src/test/test_options.c
+++ b/src/test/test_options.c
@@ -5,7 +5,7 @@
#define CONFIG_PRIVATE
#include "core/or/or.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "app/config/config.h"
#include "test/test.h"
#include "lib/geoip/geoip.h"
diff --git a/src/test/test_parseconf.sh b/src/test/test_parseconf.sh
new file mode 100755
index 0000000000..2175db48ac
--- /dev/null
+++ b/src/test/test_parseconf.sh
@@ -0,0 +1,190 @@
+#!/bin/sh
+# Copyright 2019, The Tor Project, Inc.
+# See LICENSE for licensing information
+
+# Integration test script for verifying that Tor configurations are parsed as
+# we expect.
+#
+# Valid configurations are tested with --dump-config, which parses and
+# validates the configuration before writing it out. We then make sure that
+# the result is what we expect, before parsing and dumping it again to make
+# sure that there is no change.
+#
+# Invalid configurations are tested with --verify-config, which parses
+# and validates the configuration. We capture its output and make sure that
+# it contains the error message we expect.
+
+# This script looks for its test cases as individual directories in
+# src/test/conf_examples/. Each test may have these files:
+#
+# torrc -- Usually needed. This file is passed to Tor on the command line
+# with the "-f" flag. (If you omit it, you'll test Tor's behavior when
+# it receives a nonexistent configuration file.)
+#
+# torrc.defaults -- Optional. If present, it is passed to Tor on the command
+# line with the --defaults-torrc option. If this file is absent, an empty
+# file is passed instead to prevent Tor from reading the system defaults.
+#
+# cmdline -- Optional. If present, it contains command-line arguments that
+# will be passed to Tor.
+#
+# expected -- If this file is present, then it should be the expected result
+# of "--dump-config short" for this test case. Exactly one of
+# "expected" or "error" must be present, or the test will fail.
+#
+# error -- If this file is present, then it contains a regex that must be
+# matched by some line in the output of "--verify-config", which must
+# fail. Exactly one of "expected" or "error" must be present, or the
+# test will fail.
+
+umask 077
+set -e
+die() { echo "$1" >&2 ; exit 5; }
+
+# emulate realpath(), in case coreutils or equivalent is not installed.
+abspath() {
+ f=$@
+ if [ -d "$f" ]; then
+ dir="$f"
+ base=""
+ else
+ dir="$(dirname "$f")"
+ base="/$(basename "$f")"
+ fi
+ dir="$(cd "$dir" && pwd)"
+ echo "$dir$base"
+}
+
+# find the tor binary
+if [ $# -ge 1 ]; then
+ TOR_BINARY="${1}"
+ shift
+else
+ TOR_BINARY="${TESTING_TOR_BINARY:-./src/app/tor}"
+fi
+
+TOR_BINARY="$(abspath "$TOR_BINARY")"
+
+# make a safe space for temporary files
+DATA_DIR=$(mktemp -d -t tor_parseconf_tests.XXXXXX)
+trap 'rm -rf "$DATA_DIR"' 0
+touch "${DATA_DIR}/EMPTY" || die "Couldn't create empty file."
+
+# This is where we look for examples
+EXAMPLEDIR="$(dirname "$0")"/conf_examples
+
+case "$(uname -s)" in
+ CYGWIN*) WINDOWS=1;;
+ MINGW*) WINDOWS=1;;
+ MSYS*) WINDOWS=1;;
+ *) WINDOWS=0;;
+esac
+
+if test "$WINDOWS" = 1; then
+ FILTER="dos2unix"
+else
+ FILTER="cat"
+fi
+
+for dir in "${EXAMPLEDIR}"/*; do
+ if ! test -d "${dir}"; then
+ # Only count directories.
+ continue
+ fi
+
+ testname="$(basename "${dir}")"
+ # We use printf since "echo -n" is not standard
+ printf "%s: " "$testname"
+
+ PREV_DIR="$(pwd)"
+ cd "${dir}"
+
+ if test -f "./torrc.defaults"; then
+ DEFAULTS="./torrc.defaults"
+ else
+ DEFAULTS="${DATA_DIR}/EMPTY"
+ fi
+
+ if test -f "./cmdline"; then
+ CMDLINE="$(cat ./cmdline)"
+ else
+ CMDLINE=""
+ fi
+
+ if test -f "./expected"; then
+ if test -f "./error"; then
+ echo "FAIL: Found both ${dir}/expected and ${dir}/error."
+ echo "(Only one of these files should exist.)"
+ exit 1
+ fi
+
+ # This case should succeed: run dump-config and see if it does.
+
+ "${TOR_BINARY}" -f "./torrc" \
+ --defaults-torrc "${DEFAULTS}" \
+ --dump-config short \
+ ${CMDLINE} \
+ | "${FILTER}" > "${DATA_DIR}/output.${testname}" \
+ || die "Failure: Tor exited."
+
+ if cmp "./expected" "${DATA_DIR}/output.${testname}">/dev/null ; then
+ # Check round-trip.
+ "${TOR_BINARY}" -f "${DATA_DIR}/output.${testname}" \
+ --defaults-torrc "${DATA_DIR}/empty" \
+ --dump-config short \
+ | "${FILTER}" \
+ > "${DATA_DIR}/output_2.${testname}" \
+ || die "Failure: Tor exited on round-trip."
+
+ if ! cmp "${DATA_DIR}/output.${testname}" \
+ "${DATA_DIR}/output_2.${testname}"; then
+ echo "Failure: did not match on round-trip."
+ exit 1
+ fi
+
+ echo "OK"
+ else
+ echo "FAIL"
+ if test "$(wc -c < "${DATA_DIR}/output.${testname}")" = 0; then
+ # There was no output -- probably we failed.
+ "${TOR_BINARY}" -f "./torrc" \
+ --defaults-torrc "${DEFAULTS}" \
+ --verify-config \
+ ${CMDLINE} || true
+ fi
+ diff -u "./expected" "${DATA_DIR}/output.${testname}"
+ exit 1
+ fi
+
+ elif test -f "./error"; then
+ # This case should fail: run verify-config and see if it does.
+
+ "${TOR_BINARY}" --verify-config \
+ -f ./torrc \
+ --defaults-torrc "${DEFAULTS}" \
+ ${CMDLINE} \
+ > "${DATA_DIR}/output.${testname}" \
+ && die "Failure: Tor did not report an error."
+
+ expect_err="$(cat ./error)"
+ if grep "${expect_err}" "${DATA_DIR}/output.${testname}" >/dev/null; then
+ echo "OK"
+ else
+ echo "FAIL"
+ echo "Expected error: ${expect_err}"
+ echo "Tor said:"
+ cat "${DATA_DIR}/output.${testname}"
+ exit 1
+ fi
+
+ else
+ # This case is not actually configured with a success or a failure.
+ # call that an error.
+
+ echo "FAIL: Did not find ${dir}/expected or ${dir}/error."
+ exit 1
+ fi
+
+ cd "${PREV_DIR}"
+
+done
diff --git a/src/test/test_pt.c b/src/test/test_pt.c
index 362c6664db..8f3ce03c42 100644
--- a/src/test/test_pt.c
+++ b/src/test/test_pt.c
@@ -11,7 +11,7 @@
#define PROCESS_PRIVATE
#include "core/or/or.h"
#include "app/config/config.h"
-#include "app/config/confparse.h"
+#include "lib/confmgt/confparse.h"
#include "feature/control/control.h"
#include "feature/control/control_events.h"
#include "feature/client/transports.h"
diff --git a/src/trunnel/trunnel-local.h b/src/trunnel/trunnel-local.h
index c4118fce4c..80da371560 100644
--- a/src/trunnel/trunnel-local.h
+++ b/src/trunnel/trunnel-local.h
@@ -14,5 +14,6 @@
#define trunnel_reallocarray tor_reallocarray
#define trunnel_assert tor_assert
#define trunnel_memwipe(mem, len) memwipe((mem), 0, (len))
+#define trunnel_abort tor_abort_
#endif