aboutsummaryrefslogtreecommitdiff
path: root/src/app/config/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/config/config.c')
-rw-r--r--src/app/config/config.c639
1 files changed, 289 insertions, 350 deletions
diff --git a/src/app/config/config.c b/src/app/config/config.c
index 1d61b76310..f27fcd3108 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -61,9 +61,10 @@
#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"
#include "core/mainloop/connection.h"
#include "core/mainloop/cpuworker.h"
#include "core/mainloop/mainloop.h"
@@ -85,6 +86,8 @@
#include "feature/client/entrynodes.h"
#include "feature/client/transports.h"
#include "feature/control/control.h"
+#include "feature/control/control_auth.h"
+#include "feature/control/control_events.h"
#include "feature/dirauth/bwauth.h"
#include "feature/dirauth/guardfraction.h"
#include "feature/dircache/consdiffmgr.h"
@@ -108,13 +111,14 @@
#include "feature/stats/predict_ports.h"
#include "feature/stats/rephist.h"
#include "lib/compress/compress.h"
+#include "lib/confmgt/structvar.h"
#include "lib/crypt_ops/crypto_init.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
#include "lib/encoding/confline.h"
-#include "lib/log/git_revision.h"
#include "lib/net/resolve.h"
#include "lib/sandbox/sandbox.h"
+#include "lib/version/torversion.h"
#ifdef ENABLE_NSS
#include "lib/crypt_ops/crypto_nss_mgt.h"
@@ -144,7 +148,7 @@
#include "lib/process/pidfile.h"
#include "lib/process/restrict.h"
#include "lib/process/setuid.h"
-#include "lib/process/subprocess.h"
+#include "lib/process/process.h"
#include "lib/net/gethostname.h"
#include "lib/thread/numcpus.h"
@@ -153,6 +157,7 @@
#include "lib/evloop/procmon.h"
#include "feature/dirauth/dirvote.h"
+#include "feature/dirauth/dirauth_periodic.h"
#include "feature/dirauth/recommend_pkg.h"
#include "feature/dirauth/authmode.h"
@@ -186,7 +191,7 @@ static const char unix_q_socket_prefix[] = "unix:\"";
/** A list of abbreviations and aliases to map command-line options, obsolete
* option names, or alternative option names, to their current values. */
-static config_abbrev_t option_abbrevs_[] = {
+static const config_abbrev_t option_abbrevs_[] = {
PLURAL(AuthDirBadDirCC),
PLURAL(AuthDirBadExitCC),
PLURAL(AuthDirInvalidCC),
@@ -249,22 +254,33 @@ static config_abbrev_t option_abbrevs_[] = {
* members with CONF_CHECK_VAR_TYPE. */
DUMMY_TYPECHECK_INSTANCE(or_options_t);
-/** An entry for config_vars: "The option <b>name</b> has type
+/** An entry for config_vars: "The option <b>varname</b> has type
* CONFIG_TYPE_<b>conftype</b>, and corresponds to
* or_options_t.<b>member</b>"
*/
-#define VAR(name,conftype,member,initvalue) \
- { name, CONFIG_TYPE_ ## conftype, offsetof(or_options_t, member), \
- initvalue CONF_TEST_MEMBERS(or_options_t, conftype, member) }
-/** As VAR, but the option name and member name are the same. */
-#define V(member,conftype,initvalue) \
+#define VAR(varname,conftype,member,initvalue) \
+ CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, 0, initvalue)
+
+/* As VAR, but uses a type definition in addition to a type enum. */
+#define VAR_D(varname,conftype,member,initvalue) \
+ CONFIG_VAR_DEFN(or_options_t, varname, conftype, member, 0, initvalue)
+
+#define VAR_NODUMP(varname,conftype,member,initvalue) \
+ CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \
+ CFLG_NODUMP, initvalue)
+#define VAR_INVIS(varname,conftype,member,initvalue) \
+ CONFIG_VAR_ETYPE(or_options_t, varname, conftype, member, \
+ CFLG_NODUMP | CFLG_NOSET | CFLG_NOLIST, initvalue)
+
+#define V(member,conftype,initvalue) \
VAR(#member, conftype, member, initvalue)
-/** An entry for config_vars: "The option <b>name</b> is obsolete." */
-#ifdef TOR_UNIT_TESTS
-#define OBSOLETE(name) { name, CONFIG_TYPE_OBSOLETE, 0, NULL, {.INT=NULL} }
-#else
-#define OBSOLETE(name) { name, CONFIG_TYPE_OBSOLETE, 0, NULL }
-#endif
+
+/** As V, but uses a type definition instead of a type enum */
+#define V_D(member,type,initvalue) \
+ VAR_D(#member, type, member, initvalue)
+
+/** An entry for config_vars: "The option <b>varname</b> is obsolete." */
+#define OBSOLETE(varname) CONFIG_VAR_OBSOLETE(varname)
/**
* Macro to declare *Port options. Each one comes in three entries.
@@ -276,7 +292,7 @@ DUMMY_TYPECHECK_INSTANCE(or_options_t);
#define VPORT(member) \
VAR(#member "Lines", LINELIST_V, member ## _lines, NULL), \
VAR(#member, LINELIST_S, member ## _lines, NULL), \
- VAR("__" #member, LINELIST_S, member ## _lines, NULL)
+ VAR_NODUMP("__" #member, LINELIST_S, member ## _lines, NULL)
/** UINT64_MAX as a decimal string */
#define UINT64_MAX_STRING "18446744073709551615"
@@ -285,7 +301,7 @@ DUMMY_TYPECHECK_INSTANCE(or_options_t);
* abbreviations, order is significant, since the first matching option will
* be chosen first.
*/
-static config_var_t option_vars_[] = {
+static const config_var_t option_vars_[] = {
V(AccountingMax, MEMUNIT, "0 bytes"),
VAR("AccountingRule", STRING, AccountingRule_option, "max"),
V(AccountingStart, STRING, NULL),
@@ -313,7 +329,7 @@ static config_var_t option_vars_[] = {
OBSOLETE("AuthDirRejectUnlisted"),
OBSOLETE("AuthDirListBadDirs"),
V(AuthDirListBadExits, BOOL, "0"),
- V(AuthDirMaxServersPerAddr, UINT, "2"),
+ V(AuthDirMaxServersPerAddr, POSINT, "2"),
OBSOLETE("AuthDirMaxServersPerAuthAddr"),
V(AuthDirHasIPv6Connectivity, BOOL, "0"),
VAR("AuthoritativeDirectory", BOOL, AuthoritativeDir, "0"),
@@ -342,12 +358,13 @@ static config_var_t option_vars_[] = {
V(ClientOnly, BOOL, "0"),
V(ClientPreferIPv6ORPort, AUTOBOOL, "auto"),
V(ClientPreferIPv6DirPort, AUTOBOOL, "auto"),
+ V(ClientAutoIPv6ORPort, BOOL, "0"),
V(ClientRejectInternalAddresses, BOOL, "1"),
V(ClientTransportPlugin, LINELIST, NULL),
V(ClientUseIPv6, BOOL, "0"),
V(ClientUseIPv4, BOOL, "1"),
V(ConsensusParams, STRING, NULL),
- V(ConnLimit, UINT, "1000"),
+ V(ConnLimit, POSINT, "1000"),
V(ConnDirectionStatistics, BOOL, "0"),
V(ConstrainedSockets, BOOL, "0"),
V(ConstrainedSockSize, MEMUNIT, "8192"),
@@ -391,16 +408,20 @@ static config_var_t option_vars_[] = {
OBSOLETE("DynamicDHGroups"),
VPORT(DNSPort),
OBSOLETE("DNSListenAddress"),
+ V(DormantClientTimeout, INTERVAL, "24 hours"),
+ V(DormantTimeoutDisabledByIdleStreams, BOOL, "1"),
+ V(DormantOnFirstStartup, BOOL, "0"),
+ V(DormantCanceledByStartup, BOOL, "0"),
/* DoS circuit creation options. */
V(DoSCircuitCreationEnabled, AUTOBOOL, "auto"),
- V(DoSCircuitCreationMinConnections, UINT, "0"),
- V(DoSCircuitCreationRate, UINT, "0"),
- V(DoSCircuitCreationBurst, UINT, "0"),
+ V(DoSCircuitCreationMinConnections, POSINT, "0"),
+ V(DoSCircuitCreationRate, POSINT, "0"),
+ V(DoSCircuitCreationBurst, POSINT, "0"),
V(DoSCircuitCreationDefenseType, INT, "0"),
V(DoSCircuitCreationDefenseTimePeriod, INTERVAL, "0"),
/* DoS connection options. */
V(DoSConnectionEnabled, AUTOBOOL, "auto"),
- V(DoSConnectionMaxConcurrentCount, UINT, "0"),
+ V(DoSConnectionMaxConcurrentCount, POSINT, "0"),
V(DoSConnectionDefenseType, INT, "0"),
/* DoS single hop client options. */
V(DoSRefuseSingleHopClientRendezvous, AUTOBOOL, "auto"),
@@ -409,13 +430,17 @@ static config_var_t option_vars_[] = {
V(TestingEnableCellStatsEvent, BOOL, "0"),
OBSOLETE("TestingEnableTbEmptyEvent"),
V(EnforceDistinctSubnets, BOOL, "1"),
- V(EntryNodes, ROUTERSET, NULL),
+ V_D(EntryNodes, ROUTERSET, NULL),
V(EntryStatistics, BOOL, "0"),
V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "10 minutes"),
- V(ExcludeNodes, ROUTERSET, NULL),
- V(ExcludeExitNodes, ROUTERSET, NULL),
+ V_D(ExcludeNodes, ROUTERSET, NULL),
+ V_D(ExcludeExitNodes, ROUTERSET, NULL),
OBSOLETE("ExcludeSingleHopRelays"),
- V(ExitNodes, ROUTERSET, NULL),
+ V_D(ExitNodes, ROUTERSET, NULL),
+ /* Researchers need a way to tell their clients to use specific
+ * middles that they also control, to allow safe live-network
+ * experimentation with new padding machines. */
+ V_D(MiddleNodes, ROUTERSET, NULL),
V(ExitPolicy, LINELIST, NULL),
V(ExitPolicyRejectPrivate, BOOL, "1"),
V(ExitPolicyRejectLocalInterfaces, BOOL, "0"),
@@ -471,6 +496,11 @@ static config_var_t option_vars_[] = {
VAR("HiddenServiceMaxStreamsCloseCircuit",LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceNumIntroductionPoints", LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceExportCircuitID", LINELIST_S, RendConfigLines, NULL),
+ VAR("HiddenServiceEnableIntroDoSDefense", LINELIST_S, RendConfigLines, NULL),
+ VAR("HiddenServiceEnableIntroDoSRatePerSec",
+ LINELIST_S, RendConfigLines, NULL),
+ VAR("HiddenServiceEnableIntroDoSBurstPerSec",
+ LINELIST_S, RendConfigLines, NULL),
VAR("HiddenServiceStatistics", BOOL, HiddenServiceStatistics_option, "1"),
V(HidServAuth, LINELIST, NULL),
V(ClientOnionAuthDir, FILENAME, NULL),
@@ -494,8 +524,8 @@ static config_var_t option_vars_[] = {
V(Socks5ProxyPassword, STRING, NULL),
VAR("KeyDirectory", FILENAME, KeyDirectory_option, NULL),
V(KeyDirectoryGroupReadable, BOOL, "0"),
- VAR("HSLayer2Nodes", ROUTERSET, HSLayer2Nodes, NULL),
- VAR("HSLayer3Nodes", ROUTERSET, HSLayer3Nodes, NULL),
+ VAR_D("HSLayer2Nodes", ROUTERSET, HSLayer2Nodes, NULL),
+ VAR_D("HSLayer3Nodes", ROUTERSET, HSLayer3Nodes, NULL),
V(KeepalivePeriod, INTERVAL, "5 minutes"),
V(KeepBindCapabilities, AUTOBOOL, "auto"),
VAR("Log", LINELIST, Logs, NULL),
@@ -509,7 +539,7 @@ static config_var_t option_vars_[] = {
VAR("MapAddress", LINELIST, AddressMap, NULL),
V(MaxAdvertisedBandwidth, MEMUNIT, "1 GB"),
V(MaxCircuitDirtiness, INTERVAL, "10 minutes"),
- V(MaxClientCircuitsPending, UINT, "32"),
+ V(MaxClientCircuitsPending, POSINT, "32"),
V(MaxConsensusAgeForDiffs, INTERVAL, "0 seconds"),
VAR("MaxMemInQueues", MEMUNIT, MaxMemInQueues_raw, "0"),
OBSOLETE("MaxOnionsPending"),
@@ -526,10 +556,10 @@ static config_var_t option_vars_[] = {
OBSOLETE("WarnUnsafeSocks"),
VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
V(NoExec, BOOL, "0"),
- V(NumCPUs, UINT, "0"),
- V(NumDirectoryGuards, UINT, "0"),
- V(NumEntryGuards, UINT, "0"),
- V(NumPrimaryGuards, UINT, "0"),
+ V(NumCPUs, POSINT, "0"),
+ V(NumDirectoryGuards, POSINT, "0"),
+ V(NumEntryGuards, POSINT, "0"),
+ V(NumPrimaryGuards, POSINT, "0"),
V(OfflineMasterKey, BOOL, "0"),
OBSOLETE("ORListenAddress"),
VPORT(ORPort),
@@ -580,10 +610,12 @@ static config_var_t option_vars_[] = {
V(RecommendedVersions, LINELIST, NULL),
V(RecommendedClientVersions, LINELIST, NULL),
V(RecommendedServerVersions, LINELIST, NULL),
- V(RecommendedPackages, LINELIST, NULL),
+ OBSOLETE("RecommendedPackages"),
V(ReducedConnectionPadding, BOOL, "0"),
V(ConnectionPadding, AUTOBOOL, "auto"),
V(RefuseUnknownExits, AUTOBOOL, "auto"),
+ V(CircuitPadding, BOOL, "1"),
+ V(ReducedCircuitPadding, BOOL, "0"),
V(RejectPlaintextPorts, CSV, ""),
V(RelayBandwidthBurst, MEMUNIT, "0"),
V(RelayBandwidthRate, MEMUNIT, "0"),
@@ -639,6 +671,7 @@ static config_var_t option_vars_[] = {
OBSOLETE("UseNTorHandshake"),
V(User, STRING, NULL),
OBSOLETE("UserspaceIOCPBuffers"),
+ V(AuthDirRejectRequestsUnderLoad, BOOL, "1"),
V(AuthDirSharedRandomness, BOOL, "1"),
V(AuthDirTestEd25519LinkKeys, BOOL, "1"),
OBSOLETE("V1AuthoritativeDirectory"),
@@ -651,7 +684,7 @@ static config_var_t option_vars_[] = {
V(V3AuthVotingInterval, INTERVAL, "1 hour"),
V(V3AuthVoteDelay, INTERVAL, "5 minutes"),
V(V3AuthDistDelay, INTERVAL, "5 minutes"),
- V(V3AuthNIntervalsValid, UINT, "3"),
+ V(V3AuthNIntervalsValid, POSINT, "3"),
V(V3AuthUseLegacyKey, BOOL, "0"),
V(V3BandwidthsFile, FILENAME, NULL),
V(GuardfractionFile, FILENAME, NULL),
@@ -662,15 +695,17 @@ static config_var_t option_vars_[] = {
V(WarnPlaintextPorts, CSV, "23,109,110,143"),
OBSOLETE("UseFilteringSSLBufferevents"),
OBSOLETE("__UseFilteringSSLBufferevents"),
- VAR("__ReloadTorrcOnSIGHUP", BOOL, ReloadTorrcOnSIGHUP, "1"),
- VAR("__AllDirActionsPrivate", BOOL, AllDirActionsPrivate, "0"),
- VAR("__DisablePredictedCircuits",BOOL,DisablePredictedCircuits, "0"),
- VAR("__DisableSignalHandlers", BOOL, DisableSignalHandlers, "0"),
- VAR("__LeaveStreamsUnattached",BOOL, LeaveStreamsUnattached, "0"),
- VAR("__HashedControlSessionPassword", LINELIST, HashedControlSessionPassword,
+ VAR_NODUMP("__ReloadTorrcOnSIGHUP", BOOL, ReloadTorrcOnSIGHUP, "1"),
+ VAR_NODUMP("__AllDirActionsPrivate", BOOL, AllDirActionsPrivate, "0"),
+ VAR_NODUMP("__DisablePredictedCircuits",BOOL,DisablePredictedCircuits, "0"),
+ VAR_NODUMP("__DisableSignalHandlers", BOOL, DisableSignalHandlers, "0"),
+ VAR_NODUMP("__LeaveStreamsUnattached",BOOL, LeaveStreamsUnattached, "0"),
+ VAR_NODUMP("__HashedControlSessionPassword", LINELIST,
+ HashedControlSessionPassword,
NULL),
- VAR("__OwningControllerProcess",STRING,OwningControllerProcess, NULL),
- VAR("__OwningControllerFD", UINT64, OwningControllerFD, UINT64_MAX_STRING),
+ VAR_NODUMP("__OwningControllerProcess",STRING,OwningControllerProcess, NULL),
+ VAR_NODUMP("__OwningControllerFD", UINT64, OwningControllerFD,
+ UINT64_MAX_STRING),
V(MinUptimeHidServDirectoryV2, INTERVAL, "96 hours"),
V(TestingServerDownloadInitialDelay, CSV_INTERVAL, "0"),
V(TestingClientDownloadInitialDelay, CSV_INTERVAL, "0"),
@@ -700,7 +735,7 @@ static config_var_t option_vars_[] = {
* blocked), but we also don't want to fail if only some mirrors are
* blackholed. Clients will try 3 directories simultaneously.
* (Relays never use simultaneous connections.) */
- V(ClientBootstrapConsensusMaxInProgressTries, UINT, "3"),
+ V(ClientBootstrapConsensusMaxInProgressTries, POSINT, "3"),
/* When a client has any running bridges, check each bridge occasionally,
* whether or not that bridge is actually up. */
V(TestingBridgeDownloadInitialDelay, CSV_INTERVAL,"10800"),
@@ -717,56 +752,40 @@ static config_var_t option_vars_[] = {
OBSOLETE("TestingDescriptorMaxDownloadTries"),
OBSOLETE("TestingMicrodescMaxDownloadTries"),
OBSOLETE("TestingCertMaxDownloadTries"),
- V(TestingDirAuthVoteExit, ROUTERSET, NULL),
+ V_D(TestingDirAuthVoteExit, ROUTERSET, NULL),
V(TestingDirAuthVoteExitIsStrict, BOOL, "0"),
- V(TestingDirAuthVoteGuard, ROUTERSET, NULL),
+ V_D(TestingDirAuthVoteGuard, ROUTERSET, NULL),
V(TestingDirAuthVoteGuardIsStrict, BOOL, "0"),
- V(TestingDirAuthVoteHSDir, ROUTERSET, NULL),
+ V_D(TestingDirAuthVoteHSDir, ROUTERSET, NULL),
V(TestingDirAuthVoteHSDirIsStrict, BOOL, "0"),
- VAR("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_, "0"),
+ VAR_INVIS("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_,
+ "0"),
END_OF_CONFIG_VARS
};
+/** List of default directory authorities */
+static const char *default_authorities[] = {
+#include "auth_dirs.inc"
+ NULL
+};
+
+/** List of fallback directory authorities. The list is generated by opt-in of
+ * relays that meet certain stability criteria.
+ */
+static const char *default_fallbacks[] = {
+#include "fallback_dirs.inc"
+ NULL
+};
+
/** Override default values with these if the user sets the TestingTorNetwork
* option. */
-static const config_var_t testing_tor_network_defaults[] = {
- V(DirAllowPrivateAddresses, BOOL, "1"),
- V(EnforceDistinctSubnets, BOOL, "0"),
- V(AssumeReachable, BOOL, "1"),
- V(AuthDirMaxServersPerAddr, UINT, "0"),
- V(ClientBootstrapConsensusAuthorityDownloadInitialDelay, CSV_INTERVAL, "0"),
- V(ClientBootstrapConsensusFallbackDownloadInitialDelay, CSV_INTERVAL, "0"),
- V(ClientBootstrapConsensusAuthorityOnlyDownloadInitialDelay, CSV_INTERVAL,
- "0"),
- V(ClientDNSRejectInternalAddresses, BOOL,"0"),
- V(ClientRejectInternalAddresses, BOOL, "0"),
- V(CountPrivateBandwidth, BOOL, "1"),
- V(ExitPolicyRejectPrivate, BOOL, "0"),
- V(ExtendAllowPrivateAddresses, BOOL, "1"),
- V(V3AuthVotingInterval, INTERVAL, "5 minutes"),
- V(V3AuthVoteDelay, INTERVAL, "20 seconds"),
- V(V3AuthDistDelay, INTERVAL, "20 seconds"),
- V(TestingV3AuthInitialVotingInterval, INTERVAL, "150 seconds"),
- V(TestingV3AuthInitialVoteDelay, INTERVAL, "20 seconds"),
- V(TestingV3AuthInitialDistDelay, INTERVAL, "20 seconds"),
- V(TestingAuthDirTimeToLearnReachability, INTERVAL, "0 minutes"),
- V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "0 minutes"),
- V(MinUptimeHidServDirectoryV2, INTERVAL, "0 minutes"),
- V(TestingServerDownloadInitialDelay, CSV_INTERVAL, "0"),
- V(TestingClientDownloadInitialDelay, CSV_INTERVAL, "0"),
- V(TestingServerConsensusDownloadInitialDelay, CSV_INTERVAL, "0"),
- V(TestingClientConsensusDownloadInitialDelay, CSV_INTERVAL, "0"),
- V(TestingBridgeDownloadInitialDelay, CSV_INTERVAL, "10"),
- V(TestingBridgeBootstrapDownloadInitialDelay, CSV_INTERVAL, "0"),
- V(TestingClientMaxIntervalWithoutRequest, INTERVAL, "5 seconds"),
- V(TestingDirConnectionMaxStall, INTERVAL, "30 seconds"),
- V(TestingEnableConnBwEvent, BOOL, "1"),
- V(TestingEnableCellStatsEvent, BOOL, "1"),
- VAR("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_, "1"),
- V(RendPostPeriod, INTERVAL, "2 minutes"),
-
- END_OF_CONFIG_VARS
+static const struct {
+ const char *k;
+ const char *v;
+} testing_tor_network_defaults[] = {
+#include "testnet.inc"
+ { NULL, NULL }
};
#undef VAR
@@ -830,24 +849,28 @@ static void config_maybe_load_geoip_files_(const or_options_t *options,
static int options_validate_cb(void *old_options, void *options,
void *default_options,
int from_setconf, char **msg);
-static void options_free_cb(void *options);
static void cleanup_protocol_warning_severity_level(void);
static void set_protocol_warning_severity_level(int warning_severity);
+static void options_clear_cb(const config_mgr_t *mgr, void *opts);
/** Magic value for or_options_t. */
#define OR_OPTIONS_MAGIC 9090909
/** Configuration format for or_options_t. */
-STATIC config_format_t options_format = {
+static const config_format_t options_format = {
sizeof(or_options_t),
- OR_OPTIONS_MAGIC,
- offsetof(or_options_t, magic_),
+ {
+ "or_options_t",
+ OR_OPTIONS_MAGIC,
+ offsetof(or_options_t, magic_),
+ },
option_abbrevs_,
option_deprecation_notes_,
option_vars_,
options_validate_cb,
- options_free_cb,
- NULL
+ options_clear_cb,
+ NULL,
+ offsetof(or_options_t, subconfigs_),
};
/*
@@ -879,6 +902,20 @@ static int in_option_validation = 0;
/* True iff we've initialized libevent */
static int libevent_initialized = 0;
+/* A global configuration manager to handle all configuration objects. */
+static config_mgr_t *options_mgr = NULL;
+
+/** Return the global configuration manager object for torrc options. */
+STATIC const config_mgr_t *
+get_options_mgr(void)
+{
+ if (PREDICT_UNLIKELY(options_mgr == NULL)) {
+ options_mgr = config_mgr_new(&options_format);
+ config_mgr_freeze(options_mgr);
+ }
+ return options_mgr;
+}
+
/** Return the contents of our frontpage string, or NULL if not configured. */
MOCK_IMPL(const char*,
get_dirportfrontpage, (void))
@@ -902,6 +939,32 @@ get_options,(void))
return get_options_mutable();
}
+/**
+ * True iff we have noticed that this is a testing tor network, and we
+ * should use the corresponding defaults.
+ **/
+static bool testing_network_configured = false;
+
+/** Return a set of lines for any default options that we want to override
+ * from those set in our config_var_t values. */
+static config_line_t *
+get_options_defaults(void)
+{
+ int i;
+ config_line_t *result = NULL, **next = &result;
+
+ if (testing_network_configured) {
+ for (i = 0; testing_tor_network_defaults[i].k; ++i) {
+ config_line_append(next,
+ testing_tor_network_defaults[i].k,
+ testing_tor_network_defaults[i].v);
+ next = &(*next)->next;
+ }
+ }
+
+ return result;
+}
+
/** Change the current global options to contain <b>new_val</b> instead of
* their current value; take action based on the new value; free the old value
* as necessary. Returns 0 on success, -1 on failure.
@@ -909,9 +972,6 @@ get_options,(void))
int
set_options(or_options_t *new_val, char **msg)
{
- int i;
- smartlist_t *elements;
- config_line_t *line;
or_options_t *old_options = global_options;
global_options = new_val;
/* Note that we pass the *old* options below, for comparison. It
@@ -933,35 +993,16 @@ set_options(or_options_t *new_val, char **msg)
/* Issues a CONF_CHANGED event to notify controller of the change. If Tor is
* just starting up then the old_options will be undefined. */
if (old_options && old_options != global_options) {
- elements = smartlist_new();
- for (i=0; options_format.vars[i].name; ++i) {
- const config_var_t *var = &options_format.vars[i];
- const char *var_name = var->name;
- if (var->type == CONFIG_TYPE_LINELIST_S ||
- var->type == CONFIG_TYPE_OBSOLETE) {
- continue;
- }
- if (!config_is_same(&options_format, new_val, old_options, var_name)) {
- line = config_get_assigned_option(&options_format, new_val,
- var_name, 1);
-
- if (line) {
- config_line_t *next;
- for (; line; line = next) {
- next = line->next;
- smartlist_add(elements, line->key);
- smartlist_add(elements, line->value);
- tor_free(line);
- }
- } else {
- smartlist_add_strdup(elements, options_format.vars[i].name);
- smartlist_add(elements, NULL);
- }
- }
+ smartlist_t *elements = smartlist_new();
+ config_line_t *changes =
+ config_get_changes(get_options_mgr(), old_options, new_val);
+ for (config_line_t *line = changes; line; line = line->next) {
+ smartlist_add(elements, line->key);
+ smartlist_add(elements, line->value);
}
control_event_conf_changed(elements);
- SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
smartlist_free(elements);
+ config_free_lines(changes);
}
if (old_options != global_options) {
@@ -975,49 +1016,13 @@ set_options(or_options_t *new_val, char **msg)
return 0;
}
-/** The version of this Tor process, as parsed. */
-static char *the_tor_version = NULL;
-/** A shorter version of this Tor process's version, for export in our router
- * descriptor. (Does not include the git version, if any.) */
-static char *the_short_tor_version = NULL;
-
-/** Return the current Tor version. */
-const char *
-get_version(void)
-{
- if (the_tor_version == NULL) {
- if (strlen(tor_git_revision)) {
- tor_asprintf(&the_tor_version, "%s (git-%s)", get_short_version(),
- tor_git_revision);
- } else {
- the_tor_version = tor_strdup(get_short_version());
- }
- }
- return the_tor_version;
-}
-
-/** Return the current Tor version, without any git tag. */
-const char *
-get_short_version(void)
-{
-
- if (the_short_tor_version == NULL) {
-#ifdef TOR_BUILD_TAG
- tor_asprintf(&the_short_tor_version, "%s (%s)", VERSION, TOR_BUILD_TAG);
-#else
- the_short_tor_version = tor_strdup(VERSION);
-#endif
- }
- return the_short_tor_version;
-}
-
/** Release additional memory allocated in options
*/
-STATIC void
-or_options_free_(or_options_t *options)
+static void
+options_clear_cb(const config_mgr_t *mgr, void *opts)
{
- if (!options)
- return;
+ (void)mgr;
+ or_options_t *options = opts;
routerset_free(options->ExcludeExitNodesUnion_);
if (options->NodeFamilySets) {
@@ -1040,7 +1045,14 @@ or_options_free_(or_options_t *options)
tor_free(options->command_arg);
tor_free(options->master_key_fname);
config_free_lines(options->MyFamily);
- config_free(&options_format, options);
+}
+
+/** Release all memory allocated in options
+ */
+STATIC void
+or_options_free_(or_options_t *options)
+{
+ config_free(get_options_mgr(), options);
}
/** Release all memory and resources held by global configuration structures.
@@ -1070,13 +1082,12 @@ config_free_all(void)
tor_free(torrc_defaults_fname);
tor_free(global_dirfrontpagecontents);
- tor_free(the_short_tor_version);
- tor_free(the_tor_version);
-
cleanup_protocol_warning_severity_level();
have_parsed_cmdline = 0;
libevent_initialized = 0;
+
+ config_mgr_free(options_mgr);
}
/** Make <b>address</b> -- a piece of information related to our operation as
@@ -1187,24 +1198,13 @@ init_protocol_warning_severity_level(void)
static void
cleanup_protocol_warning_severity_level(void)
{
- atomic_counter_destroy(&protocol_warning_severity_level);
+ /* Destroying a locked mutex is undefined behaviour. This mutex may be
+ * locked, because multiple threads can access it. But we need to destroy
+ * it, otherwise re-initialisation will trigger undefined behaviour.
+ * See #31735 for details. */
+ atomic_counter_destroy(&protocol_warning_severity_level);
}
-/** List of default directory authorities */
-
-static const char *default_authorities[] = {
-#include "auth_dirs.inc"
- NULL
-};
-
-/** List of fallback directory authorities. The list is generated by opt-in of
- * relays that meet certain stability criteria.
- */
-static const char *default_fallbacks[] = {
-#include "fallback_dirs.inc"
- NULL
-};
-
/** Add the default directory authorities directly into the trusted dir list,
* but only add them insofar as they share bits with <b>type</b>.
* Each authority's bits are restricted to the bits shared with <b>type</b>.
@@ -1443,10 +1443,10 @@ options_act_reversible(const or_options_t *old_options, char **msg)
* processes. */
if (running_tor && options->RunAsDaemon) {
if (! start_daemon_has_been_called())
- crypto_prefork();
+ subsystems_prefork();
/* No need to roll back, since you can't change the value. */
if (start_daemon())
- crypto_postfork();
+ subsystems_postfork();
}
#ifdef HAVE_SYSTEMD
@@ -1460,7 +1460,7 @@ options_act_reversible(const or_options_t *old_options, char **msg)
"on this OS/with this build.");
goto rollback;
}
-#else /* !(!defined(HAVE_SYS_UN_H)) */
+#else /* defined(HAVE_SYS_UN_H) */
if (options->ControlSocketsGroupWritable && !options->ControlSocket) {
*msg = tor_strdup("Setting ControlSocketGroupWritable without setting"
"a ControlSocket makes no sense.");
@@ -1735,6 +1735,7 @@ options_need_geoip_info(const or_options_t *options, const char **reason_out)
int routerset_usage =
routerset_needs_geoip(options->EntryNodes) ||
routerset_needs_geoip(options->ExitNodes) ||
+ routerset_needs_geoip(options->MiddleNodes) ||
routerset_needs_geoip(options->ExcludeExitNodes) ||
routerset_needs_geoip(options->ExcludeNodes) ||
routerset_needs_geoip(options->HSLayer2Nodes) ||
@@ -2042,9 +2043,6 @@ options_act(const or_options_t *old_options)
finish_daemon(options->DataDirectory);
}
- /* See whether we need to enable/disable our once-a-second timer. */
- reschedule_per_second_timer();
-
/* We want to reinit keys as needed before we do much of anything else:
keys are important, and other things can depend on them. */
if (transition_affects_workers ||
@@ -2177,6 +2175,7 @@ options_act(const or_options_t *old_options)
options->HSLayer2Nodes) ||
!routerset_equal(old_options->HSLayer3Nodes,
options->HSLayer3Nodes) ||
+ !routerset_equal(old_options->MiddleNodes, options->MiddleNodes) ||
options->StrictNodes != old_options->StrictNodes) {
log_info(LD_CIRC,
"Changed to using entry guards or bridges, or changed "
@@ -2560,7 +2559,7 @@ config_parse_commandline(int argc, char **argv, int ignore_errors,
param = tor_malloc_zero(sizeof(config_line_t));
param->key = is_cmdline ? tor_strdup(argv[i]) :
- tor_strdup(config_expand_abbrev(&options_format, s, 1, 1));
+ tor_strdup(config_expand_abbrev(get_options_mgr(), s, 1, 1));
param->value = arg;
param->command = command;
param->next = NULL;
@@ -2586,8 +2585,7 @@ config_parse_commandline(int argc, char **argv, int ignore_errors,
int
option_is_recognized(const char *key)
{
- const config_var_t *var = config_find_option(&options_format, key);
- return (var != NULL);
+ return config_find_option_name(get_options_mgr(), key) != NULL;
}
/** Return the canonical name of a configuration option, or NULL
@@ -2595,8 +2593,7 @@ option_is_recognized(const char *key)
const char *
option_get_canonical_name(const char *key)
{
- const config_var_t *var = config_find_option(&options_format, key);
- return var ? var->name : NULL;
+ return config_find_option_name(get_options_mgr(), key);
}
/** Return a canonical list of the options assigned for key.
@@ -2604,7 +2601,7 @@ option_get_canonical_name(const char *key)
config_line_t *
option_get_assignment(const or_options_t *options, const char *key)
{
- return config_get_assigned_option(&options_format, options, key, 1);
+ return config_get_assigned_option(get_options_mgr(), options, key, 1);
}
/** Try assigning <b>list</b> to the global options. You do this by duping
@@ -2620,9 +2617,9 @@ setopt_err_t
options_trial_assign(config_line_t *list, unsigned flags, char **msg)
{
int r;
- or_options_t *trial_options = config_dup(&options_format, get_options());
+ or_options_t *trial_options = config_dup(get_options_mgr(), get_options());
- if ((r=config_assign(&options_format, trial_options,
+ if ((r=config_assign(get_options_mgr(), trial_options,
list, flags, msg)) < 0) {
or_options_free(trial_options);
return r;
@@ -2677,24 +2674,30 @@ print_usage(void)
static void
list_torrc_options(void)
{
- int i;
- for (i = 0; option_vars_[i].name; ++i) {
- const config_var_t *var = &option_vars_[i];
- if (var->type == CONFIG_TYPE_OBSOLETE ||
- var->type == CONFIG_TYPE_LINELIST_V)
+ 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;
- printf("%s\n", var->name);
- }
+ }
+ printf("%s\n", var->member.name);
+ } SMARTLIST_FOREACH_END(var);
+ smartlist_free(vars);
}
/** Print all deprecated but non-obsolete torrc options. */
static void
list_deprecated_options(void)
{
- const config_deprecation_t *d;
- for (d = option_deprecation_notes_; d->name; ++d) {
- printf("%s\n", d->name);
- }
+ 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);
}
/** Print all compile-time modules and their enabled/disabled status. */
@@ -3004,7 +3007,7 @@ is_local_addr, (const tor_addr_t *addr))
or_options_t *
options_new(void)
{
- return config_new(&options_format);
+ return config_new(get_options_mgr());
}
/** Set <b>options</b> to hold reasonable defaults for most options.
@@ -3012,7 +3015,17 @@ options_new(void)
void
options_init(or_options_t *options)
{
- config_init(&options_format, options);
+ config_init(get_options_mgr(), options);
+ config_line_t *dflts = get_options_defaults();
+ char *msg=NULL;
+ if (config_assign(get_options_mgr(), options, dflts,
+ CAL_WARN_DEPRECATIONS, &msg)<0) {
+ log_err(LD_BUG, "Unable to set default options: %s", msg);
+ tor_free(msg);
+ tor_assert_unreached();
+ }
+ config_free_lines(dflts);
+ tor_free(msg);
}
/** Return a string containing a possible configuration file that would give
@@ -3042,7 +3055,7 @@ options_dump(const or_options_t *options, int how_to_dump)
return NULL;
}
- return config_dump(&options_format, use_defaults, options, minimal, 0);
+ return config_dump(get_options_mgr(), use_defaults, options, minimal, 0);
}
/** Return 0 if every element of sl is a string holding a decimal
@@ -3174,13 +3187,6 @@ options_validate_cb(void *old_options, void *options, void *default_options,
return rv;
}
-/** Callback to free an or_options_t */
-static void
-options_free_cb(void *options)
-{
- or_options_free_(options);
-}
-
#define REJECT(arg) \
STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
#if defined(__GNUC__) && __GNUC__ <= 3
@@ -3446,6 +3452,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (ContactInfo && !string_is_utf8(ContactInfo, strlen(ContactInfo)))
REJECT("ContactInfo config option must be UTF-8.");
+ check_network_configuration(server_mode(options));
+
/* Special case on first boot if no Log options are given. */
if (!options->Logs && !options->RunAsDaemon && !from_setconf) {
if (quiet_level == 0)
@@ -3516,7 +3524,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("Cannot use TransProxyType without any valid TransPort.");
}
}
-#else /* !(defined(USE_TRANSPARENT)) */
+#else /* !defined(USE_TRANSPARENT) */
if (options->TransPort_set)
REJECT("TransPort is disabled in this build.");
#endif /* defined(USE_TRANSPARENT) */
@@ -3550,13 +3558,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
"features to be broken in unpredictable ways.");
}
- for (cl = options->RecommendedPackages; cl; cl = cl->next) {
- if (! validate_recommended_package_line(cl->value)) {
- log_warn(LD_CONFIG, "Invalid RecommendedPackage line %s will be ignored",
- escaped(cl->value));
- }
- }
-
if (options->AuthoritativeDir) {
if (!options->ContactInfo && !options->TestingTorNetwork)
REJECT("Authoritative directory servers must set ContactInfo");
@@ -3579,7 +3580,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
tor_free(t);
t = format_recommended_version_list(options->RecommendedServerVersions, 1);
tor_free(t);
-#endif
+#endif /* defined(HAVE_MODULE_DIRAUTH) */
if (options->UseEntryGuards) {
log_info(LD_CONFIG, "Authoritative directory servers can't set "
@@ -3595,14 +3596,17 @@ options_validate(or_options_t *old_options, or_options_t *options,
options->V3AuthoritativeDir))
REJECT("AuthoritativeDir is set, but none of "
"(Bridge/V3)AuthoritativeDir is set.");
+#ifdef HAVE_MODULE_DIRAUTH
/* If we have a v3bandwidthsfile and it's broken, complain on startup */
if (options->V3BandwidthsFile && !old_options) {
- dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL, NULL);
+ dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL, NULL,
+ NULL);
}
/* same for guardfraction file */
if (options->GuardfractionFile && !old_options) {
dirserv_read_guardfraction_file(options->GuardfractionFile, NULL);
}
+#endif /* defined(HAVE_MODULE_DIRAUTH) */
}
if (options->AuthoritativeDir && !options->DirPort_set)
@@ -3780,6 +3784,14 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("Relays cannot set ReducedConnectionPadding. ");
}
+ if (server_mode(options) && options->CircuitPadding == 0) {
+ REJECT("Relays cannot set CircuitPadding to 0. ");
+ }
+
+ if (server_mode(options) && options->ReducedCircuitPadding == 1) {
+ REJECT("Relays cannot set ReducedCircuitPadding. ");
+ }
+
if (options->BridgeDistribution) {
if (!options->BridgeRelay) {
REJECT("You set BridgeDistribution, but you didn't set BridgeRelay!");
@@ -3902,6 +3914,10 @@ options_validate(or_options_t *old_options, or_options_t *options,
"default.");
}
+ if (options->DormantClientTimeout < 10*60 && !options->TestingTorNetwork) {
+ REJECT("DormantClientTimeout is too low. It must be at least 10 minutes.");
+ }
+
if (options->PathBiasNoticeRate > 1.0) {
tor_asprintf(msg,
"PathBiasNoticeRate is too high. "
@@ -3953,7 +3969,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
if (options->HeartbeatPeriod &&
- options->HeartbeatPeriod < MIN_HEARTBEAT_PERIOD) {
+ options->HeartbeatPeriod < MIN_HEARTBEAT_PERIOD &&
+ !options->TestingTorNetwork) {
log_warn(LD_CONFIG, "HeartbeatPeriod option is too short; "
"raising to %d seconds.", MIN_HEARTBEAT_PERIOD);
options->HeartbeatPeriod = MIN_HEARTBEAT_PERIOD;
@@ -4225,6 +4242,10 @@ options_validate(or_options_t *old_options, or_options_t *options,
"You should also make sure you aren't listing this bridge's "
"fingerprint in any other MyFamily.");
}
+ if (options->MyFamily_lines && !options->ContactInfo) {
+ log_warn(LD_CONFIG, "MyFamily is set but ContactInfo is not configured. "
+ "ContactInfo should always be set when MyFamily option is too.");
+ }
if (normalize_nickname_list(&options->MyFamily,
options->MyFamily_lines, "MyFamily", msg))
return -1;
@@ -4427,7 +4448,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
STMT_BEGIN \
if (!options->TestingTorNetwork && \
!options->UsingTestNetworkDefaults_ && \
- !config_is_same(&options_format,options, \
+ !config_is_same(get_options_mgr(),options, \
default_options,#arg)) { \
REJECT(#arg " may only be changed in testing Tor " \
"networks!"); \
@@ -4613,7 +4634,7 @@ compute_real_max_mem_in_queues(const uint64_t val, int log_guess)
#else
/* On a 32-bit platform, we can't have 8GB of ram. */
#define RAM_IS_VERY_LARGE(x) (0)
-#endif
+#endif /* SIZEOF_SIZE_T > 4 */
if (RAM_IS_VERY_LARGE(ram)) {
/* If we have 8 GB, or more, RAM available, we set the MaxMemInQueues
@@ -5090,7 +5111,7 @@ find_torrc_filename(config_line_t *cmd_arg,
} else {
fname = dflt ? tor_strdup(dflt) : NULL;
}
-#else /* !(!defined(_WIN32)) */
+#else /* defined(_WIN32) */
fname = dflt ? tor_strdup(dflt) : NULL;
#endif /* !defined(_WIN32) */
}
@@ -5392,6 +5413,7 @@ options_init_from_string(const char *cf_defaults, const char *cf,
int command, const char *command_arg,
char **msg)
{
+ bool retry = false;
or_options_t *oldoptions, *newoptions, *newdefaultoptions=NULL;
config_line_t *cl;
int retval;
@@ -5402,8 +5424,7 @@ options_init_from_string(const char *cf_defaults, const char *cf,
oldoptions = global_options; /* get_options unfortunately asserts if
this is the first time we run*/
- newoptions = tor_malloc_zero(sizeof(or_options_t));
- newoptions->magic_ = OR_OPTIONS_MAGIC;
+ newoptions = options_new();
options_init(newoptions);
newoptions->command = command;
newoptions->command_arg = command_arg ? tor_strdup(command_arg) : NULL;
@@ -5422,7 +5443,7 @@ options_init_from_string(const char *cf_defaults, const char *cf,
err = SETOPT_ERR_PARSE;
goto err;
}
- retval = config_assign(&options_format, newoptions, cl,
+ retval = config_assign(get_options_mgr(), newoptions, cl,
CAL_WARN_DEPRECATIONS, msg);
config_free_lines(cl);
if (retval < 0) {
@@ -5430,15 +5451,15 @@ options_init_from_string(const char *cf_defaults, const char *cf,
goto err;
}
if (i==0)
- newdefaultoptions = config_dup(&options_format, newoptions);
+ newdefaultoptions = config_dup(get_options_mgr(), newoptions);
}
if (newdefaultoptions == NULL) {
- newdefaultoptions = config_dup(&options_format, global_default_options);
+ newdefaultoptions = config_dup(get_options_mgr(), global_default_options);
}
/* Go through command-line variables too */
- retval = config_assign(&options_format, newoptions,
+ retval = config_assign(get_options_mgr(), newoptions,
global_cmdline_options, CAL_WARN_DEPRECATIONS, msg);
if (retval < 0) {
err = SETOPT_ERR_PARSE;
@@ -5449,73 +5470,12 @@ options_init_from_string(const char *cf_defaults, const char *cf,
newoptions->FilesOpenedByIncludes = opened_files;
/* If this is a testing network configuration, change defaults
- * for a list of dependent config options, re-initialize newoptions
- * with the new defaults, and assign all options to it second time. */
- if (newoptions->TestingTorNetwork) {
- /* XXXX this is a bit of a kludge. perhaps there's a better way to do
- * this? We could, for example, make the parsing algorithm do two passes
- * over the configuration. If it finds any "suite" options like
- * TestingTorNetwork, it could change the defaults before its second pass.
- * Not urgent so long as this seems to work, but at any sign of trouble,
- * let's clean it up. -NM */
-
- /* Change defaults. */
- for (int i = 0; testing_tor_network_defaults[i].name; ++i) {
- const config_var_t *new_var = &testing_tor_network_defaults[i];
- config_var_t *old_var =
- config_find_option_mutable(&options_format, new_var->name);
- tor_assert(new_var);
- tor_assert(old_var);
- old_var->initvalue = new_var->initvalue;
-
- if ((config_find_deprecation(&options_format, new_var->name))) {
- log_warn(LD_GENERAL, "Testing options override the deprecated "
- "option %s. Is that intentional?",
- new_var->name);
- }
- }
-
- /* Clear newoptions and re-initialize them with new defaults. */
- or_options_free(newoptions);
- or_options_free(newdefaultoptions);
- newdefaultoptions = NULL;
- newoptions = tor_malloc_zero(sizeof(or_options_t));
- newoptions->magic_ = OR_OPTIONS_MAGIC;
- options_init(newoptions);
- newoptions->command = command;
- newoptions->command_arg = command_arg ? tor_strdup(command_arg) : NULL;
-
- /* Assign all options a second time. */
- opened_files = smartlist_new();
- for (int i = 0; i < 2; ++i) {
- const char *body = i==0 ? cf_defaults : cf;
- if (!body)
- continue;
-
- /* get config lines, assign them */
- retval = config_get_lines_include(body, &cl, 1,
- body == cf ? &cf_has_include : NULL,
- opened_files);
- if (retval < 0) {
- err = SETOPT_ERR_PARSE;
- goto err;
- }
- retval = config_assign(&options_format, newoptions, cl, 0, msg);
- config_free_lines(cl);
- if (retval < 0) {
- err = SETOPT_ERR_PARSE;
- goto err;
- }
- if (i==0)
- newdefaultoptions = config_dup(&options_format, newoptions);
- }
- /* Assign command-line variables a second time too */
- retval = config_assign(&options_format, newoptions,
- global_cmdline_options, 0, msg);
- if (retval < 0) {
- err = SETOPT_ERR_PARSE;
- goto err;
- }
+ * for a list of dependent config options, and try this function again. */
+ if (newoptions->TestingTorNetwork && ! testing_network_configured) {
+ // retry with the testing defaults.
+ testing_network_configured = true;
+ retry = true;
+ goto err;
}
newoptions->IncludeUsed = cf_has_include;
@@ -5560,6 +5520,9 @@ options_init_from_string(const char *cf_defaults, const char *cf,
tor_asprintf(msg, "Failed to parse/validate config: %s", old_msg);
tor_free(old_msg);
}
+ if (retry)
+ return options_init_from_string(cf_defaults, cf, command, command_arg,
+ msg);
return err;
}
@@ -5785,7 +5748,7 @@ options_init_logs(const or_options_t *old_options, or_options_t *options,
#else
log_warn(LD_CONFIG, "Android logging is not supported"
" on this system. Sorry.");
-#endif // HAVE_ANDROID_LOG_H.
+#endif /* defined(HAVE_ANDROID_LOG_H) */
goto cleanup;
}
}
@@ -7838,7 +7801,7 @@ get_data_directory(const char *val)
} else {
return tor_strdup(get_windows_conf_root());
}
-#else /* !(defined(_WIN32)) */
+#else /* !defined(_WIN32) */
const char *d = val;
if (!d)
d = "~/.tor";
@@ -8182,72 +8145,48 @@ getinfo_helper_config(control_connection_t *conn,
(void) errmsg;
if (!strcmp(question, "config/names")) {
smartlist_t *sl = smartlist_new();
- int i;
- for (i = 0; option_vars_[i].name; ++i) {
- const config_var_t *var = &option_vars_[i];
- const char *type;
- /* don't tell controller about triple-underscore options */
- if (!strncmp(option_vars_[i].name, "___", 3))
+ 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_listable(var))
continue;
- switch (var->type) {
- case CONFIG_TYPE_STRING: type = "String"; break;
- case CONFIG_TYPE_FILENAME: type = "Filename"; break;
- case CONFIG_TYPE_UINT: type = "Integer"; break;
- case CONFIG_TYPE_UINT64: type = "Integer"; break;
- case CONFIG_TYPE_INT: type = "SignedInteger"; break;
- case CONFIG_TYPE_PORT: type = "Port"; break;
- case CONFIG_TYPE_INTERVAL: type = "TimeInterval"; break;
- case CONFIG_TYPE_MSEC_INTERVAL: type = "TimeMsecInterval"; break;
- case CONFIG_TYPE_MEMUNIT: type = "DataSize"; break;
- case CONFIG_TYPE_DOUBLE: type = "Float"; break;
- case CONFIG_TYPE_BOOL: type = "Boolean"; break;
- case CONFIG_TYPE_AUTOBOOL: type = "Boolean+Auto"; break;
- case CONFIG_TYPE_ISOTIME: type = "Time"; break;
- case CONFIG_TYPE_ROUTERSET: type = "RouterList"; break;
- case CONFIG_TYPE_CSV: type = "CommaList"; break;
- /* This type accepts more inputs than TimeInterval, but it ignores
- * everything after the first entry, so we may as well pretend
- * it's a TimeInterval. */
- case CONFIG_TYPE_CSV_INTERVAL: type = "TimeInterval"; break;
- case CONFIG_TYPE_LINELIST: type = "LineList"; break;
- case CONFIG_TYPE_LINELIST_S: type = "Dependent"; break;
- case CONFIG_TYPE_LINELIST_V: type = "Virtual"; break;
- default:
- case CONFIG_TYPE_OBSOLETE:
- type = NULL; break;
- }
+ const char *type = struct_var_get_typename(&var->member);
if (!type)
continue;
- smartlist_add_asprintf(sl, "%s %s\n",var->name,type);
- }
+ smartlist_add_asprintf(sl, "%s %s\n",var->member.name,type);
+ } SMARTLIST_FOREACH_END(var);
*answer = smartlist_join_strings(sl, "", 0, NULL);
SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
smartlist_free(sl);
+ smartlist_free(vars);
} else if (!strcmp(question, "config/defaults")) {
smartlist_t *sl = smartlist_new();
int dirauth_lines_seen = 0, fallback_lines_seen = 0;
- for (int i = 0; option_vars_[i].name; ++i) {
- const config_var_t *var = &option_vars_[i];
+ /* 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) {
- if (strcmp(option_vars_[i].name, "DirAuthority") == 0) {
+ if (strcmp(var->member.name, "DirAuthority") == 0) {
/*
* Count dirauth lines we have a default for; we'll use the
* count later to decide whether to add the defaults manually
*/
++dirauth_lines_seen;
}
- if (strcmp(option_vars_[i].name, "FallbackDir") == 0) {
+ if (strcmp(var->member.name, "FallbackDir") == 0) {
/*
- * Similarly count fallback lines, so that we can decided later
+ * Similarly count fallback lines, so that we can decide later
* to add the defaults manually.
*/
++fallback_lines_seen;
}
char *val = esc_for_log(var->initvalue);
- smartlist_add_asprintf(sl, "%s %s\n",var->name,val);
+ smartlist_add_asprintf(sl, "%s %s\n",var->member.name,val);
tor_free(val);
}
- }
+ } SMARTLIST_FOREACH_END(var);
+ smartlist_free(vars);
if (dirauth_lines_seen == 0) {
/*
@@ -8408,7 +8347,7 @@ config_load_geoip_file_(sa_family_t family,
}
r = geoip_load_file(family, fname, severity);
tor_free(free_fname);
-#else /* !(defined(_WIN32)) */
+#else /* !defined(_WIN32) */
(void)default_fname;
r = geoip_load_file(family, fname, severity);
#endif /* defined(_WIN32) */
@@ -8496,7 +8435,7 @@ init_cookie_authentication(const char *fname, const char *header,
log_warn(LD_FS,"Unable to make %s group-readable.", escaped(fname));
}
}
-#else /* !(!defined(_WIN32)) */
+#else /* defined(_WIN32) */
(void) group_readable;
#endif /* !defined(_WIN32) */