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.c438
1 files changed, 286 insertions, 152 deletions
diff --git a/src/app/config/config.c b/src/app/config/config.c
index a0c188adc4..fa74907b3d 100644
--- a/src/app/config/config.c
+++ b/src/app/config/config.c
@@ -27,7 +27,7 @@
* <li>The option_vars_ array below in this module, which configures
* the names of the torrc options, their types, their multiplicities,
* and their mappings to fields in or_options_t.
- * <li>The manual in doc/tor.1.txt, to document what the new option
+ * <li>The manual in doc/man/tor.1.txt, to document what the new option
* is, and how it works.
* </ul>
*
@@ -91,6 +91,7 @@
#include "feature/dirclient/dirclient_modes.h"
#include "feature/hibernate/hibernate.h"
#include "feature/hs/hs_config.h"
+#include "feature/metrics/metrics.h"
#include "feature/nodelist/dirlist.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nickname.h"
@@ -140,6 +141,7 @@
#include "lib/meminfo/meminfo.h"
#include "lib/osinfo/uname.h"
+#include "lib/osinfo/libc.h"
#include "lib/process/daemon.h"
#include "lib/process/pidfile.h"
#include "lib/process/restrict.h"
@@ -313,7 +315,8 @@ static const config_var_t option_vars_[] = {
V(AccountingMax, MEMUNIT, "0 bytes"),
VAR("AccountingRule", STRING, AccountingRule_option, "max"),
V(AccountingStart, STRING, NULL),
- V(Address, STRING, NULL),
+ V(Address, LINELIST, NULL),
+ V(AddressDisableIPv6, BOOL, "0"),
OBSOLETE("AllowDotExit"),
OBSOLETE("AllowInvalidNodes"),
V(AllowNonRFC953Hostnames, BOOL, "0"),
@@ -323,6 +326,7 @@ static const config_var_t option_vars_[] = {
V(AlternateDirAuthority, LINELIST, NULL),
OBSOLETE("AlternateHSAuthority"),
V(AssumeReachable, BOOL, "0"),
+ V(AssumeReachableIPv6, AUTOBOOL, "auto"),
OBSOLETE("AuthDirBadDir"),
OBSOLETE("AuthDirBadDirCCs"),
V(AuthDirBadExit, LINELIST, NULL),
@@ -545,7 +549,7 @@ static const config_var_t option_vars_[] = {
V(LogTimeGranularity, MSEC_INTERVAL, "1 second"),
V(TruncateLogFile, BOOL, "0"),
V_IMMUTABLE(SyslogIdentityTag, STRING, NULL),
- V_IMMUTABLE(AndroidIdentityTag,STRING, NULL),
+ OBSOLETE("AndroidIdentityTag"),
V(LongLivedPorts, CSV,
"21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"),
VAR("MapAddress", LINELIST, AddressMap, NULL),
@@ -557,6 +561,8 @@ static const config_var_t option_vars_[] = {
OBSOLETE("MaxOnionsPending"),
V(MaxOnionQueueDelay, MSEC_INTERVAL, "1750 msec"),
V(MaxUnparseableDescSizeToLog, MEMUNIT, "10 MB"),
+ VPORT(MetricsPort),
+ V(MetricsPortPolicy, LINELIST, NULL),
VAR("MyFamily", LINELIST, MyFamily_lines, NULL),
V(NewCircuitPeriod, INTERVAL, "30 seconds"),
OBSOLETE("NamingAuthoritativeDirectory"),
@@ -577,6 +583,7 @@ static const config_var_t option_vars_[] = {
V(OutboundBindAddress, LINELIST, NULL),
V(OutboundBindAddressOR, LINELIST, NULL),
V(OutboundBindAddressExit, LINELIST, NULL),
+ V(OutboundBindAddressPT, LINELIST, NULL),
OBSOLETE("PathBiasDisableRate"),
V(PathBiasCircThreshold, INT, "-1"),
@@ -606,7 +613,7 @@ static const config_var_t option_vars_[] = {
V(TestingAuthKeySlop, INTERVAL, "3 hours"),
V(TestingSigningKeySlop, INTERVAL, "1 day"),
- V(OptimisticData, AUTOBOOL, "auto"),
+ OBSOLETE("OptimisticData"),
OBSOLETE("PortForwarding"),
OBSOLETE("PortForwardingHelper"),
OBSOLETE("PreferTunneledDirConns"),
@@ -1511,7 +1518,7 @@ compute_group_readable_flag(const char *datadir,
* the datadirectory */
return datadir_gr;
} else {
- /* The directores are different, so we default to "not group-readable" */
+ /* The directories are different, so we default to "not group-readable" */
return 0;
}
}
@@ -1735,8 +1742,8 @@ options_rollback_listener_transaction(listener_transaction_t *xn)
SMARTLIST_FOREACH(xn->new_listeners, connection_t *, conn,
{
- log_notice(LD_NET, "Closing partially-constructed %s on %s:%d",
- conn_type_to_string(conn->type), conn->address, conn->port);
+ log_notice(LD_NET, "Closing partially-constructed %s",
+ connection_describe(conn));
connection_close_immediate(conn);
connection_mark_for_close(conn);
});
@@ -2101,6 +2108,16 @@ options_act,(const or_options_t *old_options))
"in a non-anonymous mode. It will provide NO ANONYMITY.");
}
+ /* 31851: OutboundBindAddressExit is relay-only */
+ if (parse_outbound_addresses(options, 0, &msg) < 0) {
+ // LCOV_EXCL_START
+ log_warn(LD_BUG, "Failed parsing previously validated outbound "
+ "bind addresses: %s", msg);
+ tor_free(msg);
+ return -1;
+ // LCOV_EXCL_STOP
+ }
+
if (options->Bridges) {
mark_bridge_list();
for (cl = options->Bridges; cl; cl = cl->next) {
@@ -2262,16 +2279,6 @@ options_act,(const or_options_t *old_options))
tor_free(http_authenticator);
}
- /* 31851: OutboundBindAddressExit is relay-only */
- if (parse_outbound_addresses(options, 0, &msg) < 0) {
- // LCOV_EXCL_START
- log_warn(LD_BUG, "Failed parsing previously validated outbound "
- "bind addresses: %s", msg);
- tor_free(msg);
- return -1;
- // LCOV_EXCL_STOP
- }
-
config_maybe_load_geoip_files_(options, old_options);
if (geoip_is_loaded(AF_INET) && options->GeoIPExcludeUnknown) {
@@ -2465,6 +2472,8 @@ static const struct {
{ .name="--key-expiration",
.takes_argument=ARGUMENT_OPTIONAL,
.command=CMD_KEY_EXPIRATION },
+ { .name="--format",
+ .takes_argument=ARGUMENT_NECESSARY },
{ .name="--newpass" },
{ .name="--no-passphrase" },
{ .name="--passphrase-fd",
@@ -2722,6 +2731,140 @@ list_enabled_modules(void)
// test variants in test_parseconf.sh to no useful purpose.
}
+/** Prints compile-time and runtime library versions. */
+static void
+print_library_versions(void)
+{
+ printf("Tor version %s. \n", get_version());
+ printf("Library versions\tCompiled\t\tRuntime\n");
+ printf("Libevent\t\t%-15s\t\t%s\n",
+ tor_libevent_get_header_version_str(),
+ tor_libevent_get_version_str());
+#ifdef ENABLE_OPENSSL
+ printf("OpenSSL \t\t%-15s\t\t%s\n",
+ crypto_openssl_get_header_version_str(),
+ crypto_openssl_get_version_str());
+#endif
+#ifdef ENABLE_NSS
+ printf("NSS \t\t%-15s\t\t%s\n",
+ crypto_nss_get_header_version_str(),
+ crypto_nss_get_version_str());
+#endif
+ if (tor_compress_supports_method(ZLIB_METHOD)) {
+ printf("Zlib \t\t%-15s\t\t%s\n",
+ tor_compress_version_str(ZLIB_METHOD),
+ tor_compress_header_version_str(ZLIB_METHOD));
+ }
+ if (tor_compress_supports_method(LZMA_METHOD)) {
+ printf("Liblzma \t\t%-15s\t\t%s\n",
+ tor_compress_version_str(LZMA_METHOD),
+ tor_compress_header_version_str(LZMA_METHOD));
+ }
+ if (tor_compress_supports_method(ZSTD_METHOD)) {
+ printf("Libzstd \t\t%-15s\t\t%s\n",
+ tor_compress_version_str(ZSTD_METHOD),
+ tor_compress_header_version_str(ZSTD_METHOD));
+ }
+ if (tor_libc_get_name()) {
+ printf("%-7s \t\t%-15s\t\t%s\n",
+ tor_libc_get_name(),
+ tor_libc_get_header_version_str(),
+ tor_libc_get_version_str());
+ }
+ //TODO: Hex versions?
+}
+
+/** Handles the --no-passphrase command line option. */
+static int
+handle_cmdline_no_passphrase(tor_cmdline_mode_t command)
+{
+ if (command == CMD_KEYGEN) {
+ get_options_mutable()->keygen_force_passphrase = FORCE_PASSPHRASE_OFF;
+ return 0;
+ } else {
+ log_err(LD_CONFIG, "--no-passphrase specified without --keygen!");
+ return -1;
+ }
+}
+
+/** Handles the --format command line option. */
+static int
+handle_cmdline_format(tor_cmdline_mode_t command, const char *value)
+{
+ if (command == CMD_KEY_EXPIRATION) {
+ // keep the same order as enum key_expiration_format
+ const char *formats[] = { "iso8601", "timestamp" };
+ int format = -1;
+ for (unsigned i = 0; i < ARRAY_LENGTH(formats); i++) {
+ if (!strcmp(value, formats[i])) {
+ format = i;
+ break;
+ }
+ }
+
+ if (format < 0) {
+ log_err(LD_CONFIG, "Invalid --format value %s", escaped(value));
+ return -1;
+ } else {
+ get_options_mutable()->key_expiration_format = format;
+ }
+ return 0;
+ } else {
+ log_err(LD_CONFIG, "--format specified without --key-expiration!");
+ return -1;
+ }
+}
+
+/** Handles the --newpass command line option. */
+static int
+handle_cmdline_newpass(tor_cmdline_mode_t command)
+{
+ if (command == CMD_KEYGEN) {
+ get_options_mutable()->change_key_passphrase = 1;
+ return 0;
+ } else {
+ log_err(LD_CONFIG, "--newpass specified without --keygen!");
+ return -1;
+ }
+}
+
+/** Handles the --passphrase-fd command line option. */
+static int
+handle_cmdline_passphrase_fd(tor_cmdline_mode_t command, const char *value)
+{
+ if (get_options()->keygen_force_passphrase == FORCE_PASSPHRASE_OFF) {
+ log_err(LD_CONFIG, "--no-passphrase specified with --passphrase-fd!");
+ return -1;
+ } else if (command != CMD_KEYGEN) {
+ log_err(LD_CONFIG, "--passphrase-fd specified without --keygen!");
+ return -1;
+ } else {
+ int ok = 1;
+ long fd = tor_parse_long(value, 10, 0, INT_MAX, &ok, NULL);
+ if (fd < 0 || ok == 0) {
+ log_err(LD_CONFIG, "Invalid --passphrase-fd value %s", escaped(value));
+ return -1;
+ }
+ get_options_mutable()->keygen_passphrase_fd = (int)fd;
+ get_options_mutable()->use_keygen_passphrase_fd = 1;
+ get_options_mutable()->keygen_force_passphrase = FORCE_PASSPHRASE_ON;
+ return 0;
+ }
+}
+
+/** Handles the --master-key command line option. */
+static int
+handle_cmdline_master_key(tor_cmdline_mode_t command, const char *value)
+{
+ if (command != CMD_KEYGEN) {
+ log_err(LD_CONFIG, "--master-key without --keygen!");
+ return -1;
+ } else {
+ get_options_mutable()->master_key_fname = tor_strdup(value);
+ return 0;
+ }
+}
+
/* Return true if <b>options</b> is using the default authorities, and false
* if any authority-related option has been overridden. */
int
@@ -2771,10 +2914,6 @@ options_dump(const or_options_t *options, int how_to_dump)
use_defaults = global_default_options;
minimal = 1;
break;
- case OPTIONS_DUMP_DEFAULTS:
- use_defaults = NULL;
- minimal = 1;
- break;
case OPTIONS_DUMP_ALL:
use_defaults = NULL;
minimal = 0;
@@ -3229,6 +3368,10 @@ options_validate_cb(const void *old_options_, void *options_, char **msg)
REJECT("TokenBucketRefillInterval must be between 1 and 1000 inclusive.");
}
+ if (options->AssumeReachable && options->AssumeReachableIPv6 == 0) {
+ REJECT("Cannot set AssumeReachable 1 and AssumeReachableIPv6 0.");
+ }
+
if (options->ExcludeExitNodes || options->ExcludeNodes) {
options->ExcludeExitNodesUnion_ = routerset_new();
routerset_union(options->ExcludeExitNodesUnion_,options->ExcludeExitNodes);
@@ -3453,7 +3596,7 @@ options_validate_cb(const void *old_options_, void *options_, char **msg)
"configured. This is bad because it's very easy to locate your "
"entry guard which can then lead to the deanonymization of your "
"hidden service -- for more details, see "
- "https://trac.torproject.org/projects/tor/ticket/14917. "
+ "https://bugs.torproject.org/tpo/core/tor/14917. "
"For this reason, the use of one EntryNodes with an hidden "
"service is prohibited until a better solution is found.");
return -1;
@@ -3470,7 +3613,7 @@ options_validate_cb(const void *old_options_, void *options_, char **msg)
"be harmful to the service anonymity. Because of this, we "
"recommend you either don't do that or make sure you know what "
"you are doing. For more details, please look at "
- "https://trac.torproject.org/projects/tor/ticket/21155.");
+ "https://bugs.torproject.org/tpo/core/tor/21155.");
}
/* Single Onion Services: non-anonymous hidden services */
@@ -4045,7 +4188,7 @@ options_check_transition_cb(const void *old_,
if (! CFG_EQ_INT(old, new_val, opt)) \
BAD_CHANGE_TO(opt," with Sandbox active")
- SB_NOCHANGE_STR(Address);
+ SB_NOCHANGE_LINELIST(Address);
SB_NOCHANGE_STR(ServerDNSResolvConfFile);
SB_NOCHANGE_STR(DirPortFrontPage);
SB_NOCHANGE_STR(CookieAuthFile);
@@ -4351,37 +4494,7 @@ options_init_from_torrc(int argc, char **argv)
}
if (config_line_find(cmdline_only_options, "--library-versions")) {
- printf("Tor version %s. \n", get_version());
- printf("Library versions\tCompiled\t\tRuntime\n");
- printf("Libevent\t\t%-15s\t\t%s\n",
- tor_libevent_get_header_version_str(),
- tor_libevent_get_version_str());
-#ifdef ENABLE_OPENSSL
- printf("OpenSSL \t\t%-15s\t\t%s\n",
- crypto_openssl_get_header_version_str(),
- crypto_openssl_get_version_str());
-#endif
-#ifdef ENABLE_NSS
- printf("NSS \t\t%-15s\t\t%s\n",
- crypto_nss_get_header_version_str(),
- crypto_nss_get_version_str());
-#endif
- if (tor_compress_supports_method(ZLIB_METHOD)) {
- printf("Zlib \t\t%-15s\t\t%s\n",
- tor_compress_version_str(ZLIB_METHOD),
- tor_compress_header_version_str(ZLIB_METHOD));
- }
- if (tor_compress_supports_method(LZMA_METHOD)) {
- printf("Liblzma \t\t%-15s\t\t%s\n",
- tor_compress_version_str(LZMA_METHOD),
- tor_compress_header_version_str(LZMA_METHOD));
- }
- if (tor_compress_supports_method(ZSTD_METHOD)) {
- printf("Libzstd \t\t%-15s\t\t%s\n",
- tor_compress_version_str(ZSTD_METHOD),
- tor_compress_header_version_str(ZSTD_METHOD));
- }
- //TODO: Hex versions?
+ print_library_versions();
return 1;
}
@@ -4395,10 +4508,7 @@ options_init_from_torrc(int argc, char **argv)
cf = tor_strdup("");
} else {
cf_defaults = load_torrc_from_disk(cmdline_only_options, 1);
-
- const config_line_t *f_line = config_line_find(cmdline_only_options,
- "-f");
-
+ const config_line_t *f_line = config_line_find(cmdline_only_options, "-f");
const int read_torrc_from_stdin =
(f_line != NULL && strcmp(f_line->value, "-") == 0);
@@ -4419,74 +4529,54 @@ options_init_from_torrc(int argc, char **argv)
retval = options_init_from_string(cf_defaults, cf, command, command_arg,
&errmsg);
-
if (retval < 0)
goto err;
if (config_line_find(cmdline_only_options, "--no-passphrase")) {
- if (command == CMD_KEYGEN) {
- get_options_mutable()->keygen_force_passphrase = FORCE_PASSPHRASE_OFF;
- } else {
- log_err(LD_CONFIG, "--no-passphrase specified without --keygen!");
+ if (handle_cmdline_no_passphrase(command) < 0) {
retval = -1;
goto err;
}
}
+ const config_line_t *format_line = config_line_find(cmdline_only_options,
+ "--format");
+ if (format_line) {
+ if (handle_cmdline_format(command, format_line->value) < 0) {
+ retval = -1;
+ goto err;
+ }
+ } else {
+ get_options_mutable()->key_expiration_format =
+ KEY_EXPIRATION_FORMAT_ISO8601;
+ }
+
if (config_line_find(cmdline_only_options, "--newpass")) {
- if (command == CMD_KEYGEN) {
- get_options_mutable()->change_key_passphrase = 1;
- } else {
- log_err(LD_CONFIG, "--newpass specified without --keygen!");
+ if (handle_cmdline_newpass(command) < 0) {
retval = -1;
goto err;
}
}
- {
- const config_line_t *fd_line = config_line_find(cmdline_only_options,
- "--passphrase-fd");
- if (fd_line) {
- if (get_options()->keygen_force_passphrase == FORCE_PASSPHRASE_OFF) {
- log_err(LD_CONFIG, "--no-passphrase specified with --passphrase-fd!");
- retval = -1;
- goto err;
- } else if (command != CMD_KEYGEN) {
- log_err(LD_CONFIG, "--passphrase-fd specified without --keygen!");
- retval = -1;
- goto err;
- } else {
- const char *v = fd_line->value;
- int ok = 1;
- long fd = tor_parse_long(v, 10, 0, INT_MAX, &ok, NULL);
- if (fd < 0 || ok == 0) {
- log_err(LD_CONFIG, "Invalid --passphrase-fd value %s", escaped(v));
- retval = -1;
- goto err;
- }
- get_options_mutable()->keygen_passphrase_fd = (int)fd;
- get_options_mutable()->use_keygen_passphrase_fd = 1;
- get_options_mutable()->keygen_force_passphrase = FORCE_PASSPHRASE_ON;
- }
+ const config_line_t *fd_line = config_line_find(cmdline_only_options,
+ "--passphrase-fd");
+ if (fd_line) {
+ if (handle_cmdline_passphrase_fd(command, fd_line->value) < 0) {
+ retval = -1;
+ goto err;
}
}
- {
- const config_line_t *key_line = config_line_find(cmdline_only_options,
- "--master-key");
- if (key_line) {
- if (command != CMD_KEYGEN) {
- log_err(LD_CONFIG, "--master-key without --keygen!");
- retval = -1;
- goto err;
- } else {
- get_options_mutable()->master_key_fname = tor_strdup(key_line->value);
- }
+ const config_line_t *key_line = config_line_find(cmdline_only_options,
+ "--master-key");
+ if (key_line) {
+ if (handle_cmdline_master_key(command, key_line->value) < 0) {
+ retval = -1;
+ goto err;
}
}
err:
-
tor_free(cf);
tor_free(cf_defaults);
if (errmsg) {
@@ -4848,15 +4938,19 @@ options_init_logs(const or_options_t *old_options, const or_options_t *options,
goto cleanup;
}
+ /* We added this workaround in 0.4.5.x; we can remove it in 0.4.6 or
+ * later */
if (!strcasecmp(smartlist_get(elts, 0), "android")) {
-#ifdef HAVE_ANDROID_LOG_H
+#ifdef HAVE_SYSLOG_H
+ log_warn(LD_CONFIG, "The android logging API is no longer supported;"
+ " adding a syslog instead. The 'android' logging "
+ " type will no longer work in the future.");
if (!validate_only) {
- add_android_log(severity, options->AndroidIdentityTag);
+ add_syslog_log(severity, options->SyslogIdentityTag);
}
#else
- log_warn(LD_CONFIG, "Android logging is not supported"
- " on this system. Sorry.");
-#endif /* defined(HAVE_ANDROID_LOG_H) */
+ log_warn(LD_CONFIG, "The android logging API is no longer supported.");
+#endif
goto cleanup;
}
}
@@ -5778,9 +5872,9 @@ warn_client_dns_cache(const char *option, int disabling)
return;
warn_deprecated_option(option,
- "Client-side DNS cacheing enables a wide variety of route-"
+ "Client-side DNS caching enables a wide variety of route-"
"capture attacks. If a single bad exit node lies to you about "
- "an IP address, cacheing that address would make you visit "
+ "an IP address, caching that address would make you visit "
"an address of the attacker's choice every time you connected "
"to your destination.");
}
@@ -5839,6 +5933,14 @@ port_parse_config(smartlist_t *out,
int got_zero_port=0, got_nonzero_port=0;
char *unix_socket_path = NULL;
port_cfg_t *cfg = NULL;
+ bool addr_is_explicit = false;
+ tor_addr_t default_addr = TOR_ADDR_NULL;
+
+ /* Parse default address. This can fail for Unix socket so the default_addr
+ * will simply be made UNSPEC. */
+ if (defaultaddr) {
+ tor_addr_parse(&default_addr, defaultaddr);
+ }
/* If there's no FooPort, then maybe make a default one. */
if (! ports) {
@@ -5915,8 +6017,7 @@ port_parse_config(smartlist_t *out,
port = 1;
} else if (!strcasecmp(addrport, "auto")) {
port = CFG_AUTO_PORT;
- int af = tor_addr_parse(&addr, defaultaddr);
- tor_assert(af >= 0);
+ tor_addr_copy(&addr, &default_addr);
} else if (!strcasecmpend(addrport, ":auto")) {
char *addrtmp = tor_strndup(addrport, strlen(addrport)-5);
port = CFG_AUTO_PORT;
@@ -5932,14 +6033,15 @@ port_parse_config(smartlist_t *out,
"9050" might be a valid address. */
port = (int) tor_parse_long(addrport, 10, 0, 65535, &ok, NULL);
if (ok) {
- int af = tor_addr_parse(&addr, defaultaddr);
- tor_assert(af >= 0);
+ tor_addr_copy(&addr, &default_addr);
+ addr_is_explicit = false;
} else if (tor_addr_port_lookup(addrport, &addr, &ptmp) == 0) {
if (ptmp == 0) {
log_warn(LD_CONFIG, "%sPort line has address but no port", portname);
goto err;
}
port = ptmp;
+ addr_is_explicit = true;
} else {
log_warn(LD_CONFIG, "Couldn't parse address %s for %sPort",
escaped(addrport), portname);
@@ -5950,6 +6052,7 @@ port_parse_config(smartlist_t *out,
/* Default port_cfg_t object initialization */
cfg = port_cfg_new(unix_socket_path ? strlen(unix_socket_path) : 0);
+ cfg->explicit_addr = addr_is_explicit;
if (unix_socket_path && default_to_group_writable)
cfg->is_group_writable = 1;
@@ -5992,15 +6095,25 @@ port_parse_config(smartlist_t *out,
}
if (cfg->server_cfg.bind_ipv4_only &&
tor_addr_family(&addr) != AF_INET) {
- log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv4",
- portname);
- goto err;
+ if (cfg->explicit_addr) {
+ log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv4",
+ portname);
+ goto err;
+ }
+ /* This ORPort is IPv4Only but the default address is IPv6, ignore it
+ * since this will be configured with an IPv4 default address. */
+ goto ignore;
}
if (cfg->server_cfg.bind_ipv6_only &&
tor_addr_family(&addr) != AF_INET6) {
- log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv6",
- portname);
- goto err;
+ if (cfg->explicit_addr) {
+ log_warn(LD_CONFIG, "Could not interpret %sPort address as IPv6",
+ portname);
+ goto err;
+ }
+ /* This ORPort is IPv6Only but the default address is IPv4, ignore it
+ * since this will be configured with an IPv6 default address. */
+ goto ignore;
}
} else {
/* This is a client port; parse isolation options */
@@ -6213,9 +6326,10 @@ port_parse_config(smartlist_t *out,
smartlist_add(out, cfg);
/* out owns cfg now, don't re-use or free it */
cfg = NULL;
- } else {
- tor_free(cfg);
}
+
+ ignore:
+ tor_free(cfg);
SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
smartlist_clear(elts);
tor_free(addrport);
@@ -6343,6 +6457,10 @@ parse_ports(or_options_t *options, int validate_only,
*msg = tor_strdup("Invalid HTTPTunnelPort configuration");
goto err;
}
+ if (metrics_parse_ports(options, ports, msg) < 0) {
+ goto err;
+ }
+
{
unsigned control_port_flags = CL_PORT_NO_STREAM_OPTIONS |
CL_PORT_WARN_NONLOCAL;
@@ -6512,48 +6630,57 @@ get_first_listener_addrport_string(int listener_type)
return NULL;
}
-/** Return the first advertised port of type <b>listener_type</b> in
- * <b>address_family</b>. Returns 0 when no port is found, and when passed
- * AF_UNSPEC. */
-int
-get_first_advertised_port_by_type_af(int listener_type, int address_family)
+/** Find and return the first configured advertised `port_cfg_t` of type @a
+ * listener_type in @a address_family. */
+static const port_cfg_t *
+portconf_get_first_advertised(int listener_type, int address_family)
{
+ const port_cfg_t *first_port = NULL;
+ const port_cfg_t *first_port_explicit_addr = NULL;
+
if (address_family == AF_UNSPEC)
- return 0;
+ return NULL;
const smartlist_t *conf_ports = get_configured_ports();
SMARTLIST_FOREACH_BEGIN(conf_ports, const port_cfg_t *, cfg) {
- if (cfg->type == listener_type &&
- !cfg->server_cfg.no_advertise) {
+ if (cfg->type == listener_type && !cfg->server_cfg.no_advertise) {
if ((address_family == AF_INET && port_binds_ipv4(cfg)) ||
(address_family == AF_INET6 && port_binds_ipv6(cfg))) {
- return cfg->port;
+ if (cfg->explicit_addr && !first_port_explicit_addr) {
+ first_port_explicit_addr = cfg;
+ } else if (!first_port) {
+ first_port = cfg;
+ }
}
}
} SMARTLIST_FOREACH_END(cfg);
- return 0;
+
+ /* Prefer the port with the explicit address if any. */
+ return (first_port_explicit_addr) ? first_port_explicit_addr : first_port;
+}
+
+/** Return the first advertised port of type <b>listener_type</b> in
+ * <b>address_family</b>. Returns 0 when no port is found, and when passed
+ * AF_UNSPEC. */
+int
+portconf_get_first_advertised_port(int listener_type, int address_family)
+{
+ const port_cfg_t *cfg;
+ cfg = portconf_get_first_advertised(listener_type, address_family);
+
+ return cfg ? cfg->port : 0;
}
/** Return the first advertised address of type <b>listener_type</b> in
* <b>address_family</b>. Returns NULL if there is no advertised address,
* and when passed AF_UNSPEC. */
const tor_addr_t *
-get_first_advertised_addr_by_type_af(int listener_type, int address_family)
+portconf_get_first_advertised_addr(int listener_type, int address_family)
{
- if (address_family == AF_UNSPEC)
- return NULL;
- if (!configured_ports)
- return NULL;
- SMARTLIST_FOREACH_BEGIN(configured_ports, const port_cfg_t *, cfg) {
- if (cfg->type == listener_type &&
- !cfg->server_cfg.no_advertise) {
- if ((address_family == AF_INET && port_binds_ipv4(cfg)) ||
- (address_family == AF_INET6 && port_binds_ipv6(cfg))) {
- return &cfg->addr;
- }
- }
- } SMARTLIST_FOREACH_END(cfg);
- return NULL;
+ const port_cfg_t *cfg;
+ cfg = portconf_get_first_advertised(listener_type, address_family);
+
+ return cfg ? &cfg->addr : NULL;
}
/** Return 1 if a port exists of type <b>listener_type</b> on <b>addr</b> and
@@ -6883,7 +7010,7 @@ options_get_dir_fname2_suffix,(const or_options_t *options,
return fname;
}
-/** Check wether the data directory has a private subdirectory
+/** Check whether the data directory has a private subdirectory
* <b>subdir</b>. If not, try to create it. Return 0 on success,
* -1 otherwise. */
int
@@ -7066,7 +7193,8 @@ parse_outbound_address_lines(const config_line_t *lines, outbound_addr_t type,
"configured: %s",
family==AF_INET?" IPv4":(family==AF_INET6?" IPv6":""),
type==OUTBOUND_ADDR_OR?" OR":
- (type==OUTBOUND_ADDR_EXIT?" exit":""), lines->value);
+ (type==OUTBOUND_ADDR_EXIT?" exit":
+ (type==OUTBOUND_ADDR_PT?" PT":"")), lines->value);
return -1;
}
lines = lines->next;
@@ -7089,7 +7217,7 @@ parse_outbound_addresses(or_options_t *options, int validate_only, char **msg)
}
if (parse_outbound_address_lines(options->OutboundBindAddress,
- OUTBOUND_ADDR_EXIT_AND_OR, options,
+ OUTBOUND_ADDR_ANY, options,
validate_only, msg) < 0) {
goto err;
}
@@ -7106,6 +7234,12 @@ parse_outbound_addresses(or_options_t *options, int validate_only, char **msg)
goto err;
}
+ if (parse_outbound_address_lines(options->OutboundBindAddressPT,
+ OUTBOUND_ADDR_PT, options, validate_only,
+ msg) < 0) {
+ goto err;
+ }
+
return 0;
err:
return -1;