diff options
Diffstat (limited to 'src/or/config.c')
-rw-r--r-- | src/or/config.c | 679 |
1 files changed, 373 insertions, 306 deletions
diff --git a/src/or/config.c b/src/or/config.c index b047b12717..be0bfc7687 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2013, The Tor Project, Inc. */ + * Copyright (c) 2007-2015, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -11,6 +11,7 @@ #define CONFIG_PRIVATE #include "or.h" +#include "compat.h" #include "addressmap.h" #include "channel.h" #include "circuitbuild.h" @@ -43,6 +44,7 @@ #include "util.h" #include "routerlist.h" #include "routerset.h" +#include "scheduler.h" #include "statefile.h" #include "transports.h" #include "ext_orport.h" @@ -99,8 +101,6 @@ static config_abbrev_t option_abbrevs_[] = { { "PreferTunnelledDirConns", "PreferTunneledDirConns", 0, 0}, { "BridgeAuthoritativeDirectory", "BridgeAuthoritativeDir", 0, 0}, { "HashedControlPassword", "__HashedControlSessionPassword", 1, 0}, - { "StrictEntryNodes", "StrictNodes", 0, 1}, - { "StrictExitNodes", "StrictNodes", 0, 1}, { "VirtualAddrNetwork", "VirtualAddrNetworkIPv4", 0, 0}, { "_UseFilteringSSLBufferevents", "UseFilteringSSLBufferevents", 0, 1}, { NULL, NULL, 0, 0}, @@ -127,8 +127,8 @@ static config_abbrev_t option_abbrevs_[] = { * be chosen first. */ static config_var_t option_vars_[] = { - OBSOLETE("AccountingMaxKB"), V(AccountingMax, MEMUNIT, "0 bytes"), + VAR("AccountingRule", STRING, AccountingRule_option, "max"), V(AccountingStart, STRING, NULL), V(Address, STRING, NULL), V(AllowDotExit, BOOL, "0"), @@ -140,8 +140,8 @@ static config_var_t option_vars_[] = { V(AlternateDirAuthority, LINELIST, NULL), OBSOLETE("AlternateHSAuthority"), V(AssumeReachable, BOOL, "0"), - V(AuthDirBadDir, LINELIST, NULL), - V(AuthDirBadDirCCs, CSV, ""), + OBSOLETE("AuthDirBadDir"), + OBSOLETE("AuthDirBadDirCCs"), V(AuthDirBadExit, LINELIST, NULL), V(AuthDirBadExitCCs, CSV, ""), V(AuthDirInvalid, LINELIST, NULL), @@ -150,8 +150,8 @@ static config_var_t option_vars_[] = { V(AuthDirGuardBWGuarantee, MEMUNIT, "2 MB"), V(AuthDirReject, LINELIST, NULL), V(AuthDirRejectCCs, CSV, ""), - V(AuthDirRejectUnlisted, BOOL, "0"), - V(AuthDirListBadDirs, BOOL, "0"), + OBSOLETE("AuthDirRejectUnlisted"), + OBSOLETE("AuthDirListBadDirs"), V(AuthDirListBadExits, BOOL, "0"), V(AuthDirMaxServersPerAddr, UINT, "2"), V(AuthDirMaxServersPerAuthAddr,UINT, "5"), @@ -196,21 +196,14 @@ static config_var_t option_vars_[] = { V(CookieAuthFile, STRING, NULL), V(CountPrivateBandwidth, BOOL, "0"), V(DataDirectory, FILENAME, NULL), - OBSOLETE("DebugLogFile"), V(DisableNetwork, BOOL, "0"), V(DirAllowPrivateAddresses, BOOL, "0"), V(TestingAuthDirTimeToLearnReachability, INTERVAL, "30 minutes"), V(DirListenAddress, LINELIST, NULL), - OBSOLETE("DirFetchPeriod"), V(DirPolicy, LINELIST, NULL), VPORT(DirPort, LINELIST, NULL), V(DirPortFrontPage, FILENAME, NULL), - OBSOLETE("DirPostPeriod"), - OBSOLETE("DirRecordUsageByCountry"), - OBSOLETE("DirRecordUsageGranularity"), - OBSOLETE("DirRecordUsageRetainIPs"), - OBSOLETE("DirRecordUsageSaveInterval"), - V(DirReqStatistics, BOOL, "1"), + VAR("DirReqStatistics", BOOL, DirReqStatistics_option, "1"), VAR("DirAuthority", LINELIST, DirAuthorities, NULL), V(DirAuthorityFallbackRate, DOUBLE, "1.0"), V(DisableAllSwap, BOOL, "0"), @@ -262,7 +255,6 @@ static config_var_t option_vars_[] = { V(GeoIPv6File, FILENAME, SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip6"), #endif - OBSOLETE("GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays"), OBSOLETE("Group"), V(GuardLifetime, INTERVAL, "0 minutes"), V(HardwareAccel, BOOL, "0"), @@ -272,15 +264,13 @@ static config_var_t option_vars_[] = { V(HashedControlPassword, LINELIST, NULL), V(HidServDirectoryV2, BOOL, "1"), VAR("HiddenServiceDir", LINELIST_S, RendConfigLines, NULL), - OBSOLETE("HiddenServiceExcludeNodes"), - OBSOLETE("HiddenServiceNodes"), + VAR("HiddenServiceDirGroupReadable", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceOptions",LINELIST_V, RendConfigLines, NULL), VAR("HiddenServicePort", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceVersion",LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceAuthorizeClient",LINELIST_S,RendConfigLines, NULL), + V(HiddenServiceStatistics, BOOL, "0"), V(HidServAuth, LINELIST, NULL), - OBSOLETE("HSAuthoritativeDir"), - OBSOLETE("HSAuthorityRecordStats"), V(CloseHSClientCircuitsImmediatelyOnTimeout, BOOL, "0"), V(CloseHSServiceRendCircuitsImmediatelyOnTimeout, BOOL, "0"), V(HTTPProxy, STRING, NULL), @@ -295,14 +285,11 @@ static config_var_t option_vars_[] = { V(Socks5Proxy, STRING, NULL), V(Socks5ProxyUsername, STRING, NULL), V(Socks5ProxyPassword, STRING, NULL), - OBSOLETE("IgnoreVersion"), V(KeepalivePeriod, INTERVAL, "5 minutes"), VAR("Log", LINELIST, Logs, NULL), V(LogMessageDomains, BOOL, "0"), - OBSOLETE("LinkPadding"), - OBSOLETE("LogLevel"), - OBSOLETE("LogFile"), V(LogTimeGranularity, MSEC_INTERVAL, "1 second"), + V(TruncateLogFile, BOOL, "0"), V(LongLivedPorts, CSV, "21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"), VAR("MapAddress", LINELIST, AddressMap, NULL), @@ -313,16 +300,14 @@ static config_var_t option_vars_[] = { OBSOLETE("MaxOnionsPending"), V(MaxOnionQueueDelay, MSEC_INTERVAL, "1750 msec"), V(MinMeasuredBWsForAuthToIgnoreAdvertised, INT, "500"), - OBSOLETE("MonthlyAccountingStart"), V(MyFamily, STRING, NULL), V(NewCircuitPeriod, INTERVAL, "30 seconds"), - VAR("NamingAuthoritativeDirectory",BOOL, NamingAuthoritativeDir, "0"), + OBSOLETE("NamingAuthoritativeDirectory"), V(NATDListenAddress, LINELIST, NULL), VPORT(NATDPort, LINELIST, NULL), V(Nickname, STRING, NULL), V(PredictedPortsRelevanceTime, INTERVAL, "1 hour"), V(WarnUnsafeSocks, BOOL, "1"), - OBSOLETE("NoPublish"), VAR("NodeFamily", LINELIST, NodeFamilies, NULL), V(NumCPUs, UINT, "0"), V(NumDirectoryGuards, UINT, "0"), @@ -348,7 +333,6 @@ static config_var_t option_vars_[] = { V(PathBiasScaleUseThreshold, INT, "-1"), V(PathsNeededToBuildCircuits, DOUBLE, "-1"), - OBSOLETE("PathlenCoinWeight"), V(PerConnBWBurst, MEMUNIT, "0"), V(PerConnBWRate, MEMUNIT, "0"), V(PidFile, STRING, NULL), @@ -368,18 +352,13 @@ static config_var_t option_vars_[] = { V(RecommendedVersions, LINELIST, NULL), V(RecommendedClientVersions, LINELIST, NULL), V(RecommendedServerVersions, LINELIST, NULL), - OBSOLETE("RedirectExit"), V(RefuseUnknownExits, AUTOBOOL, "auto"), V(RejectPlaintextPorts, CSV, ""), V(RelayBandwidthBurst, MEMUNIT, "0"), V(RelayBandwidthRate, MEMUNIT, "0"), - OBSOLETE("RendExcludeNodes"), - OBSOLETE("RendNodes"), V(RendPostPeriod, INTERVAL, "1 hour"), V(RephistTrackTime, INTERVAL, "24 hours"), - OBSOLETE("RouterFile"), V(RunAsDaemon, BOOL, "0"), -// V(RunTesting, BOOL, "0"), OBSOLETE("RunTesting"), // currently unused V(Sandbox, BOOL, "0"), V(SafeLogging, STRING, "1"), @@ -392,24 +371,25 @@ static config_var_t option_vars_[] = { V(ServerDNSSearchDomains, BOOL, "0"), V(ServerDNSTestAddresses, CSV, "www.google.com,www.mit.edu,www.yahoo.com,www.slashdot.org"), + V(SchedulerLowWaterMark__, MEMUNIT, "100 MB"), + V(SchedulerHighWaterMark__, MEMUNIT, "101 MB"), + V(SchedulerMaxFlushCells__, UINT, "1000"), V(ShutdownWaitLength, INTERVAL, "30 seconds"), V(SocksListenAddress, LINELIST, NULL), V(SocksPolicy, LINELIST, NULL), VPORT(SocksPort, LINELIST, NULL), V(SocksTimeout, INTERVAL, "2 minutes"), V(SSLKeyLifetime, INTERVAL, "0"), - OBSOLETE("StatusFetchPeriod"), + OBSOLETE("StrictEntryNodes"), + OBSOLETE("StrictExitNodes"), V(StrictNodes, BOOL, "0"), - V(Support022HiddenServices, AUTOBOOL, "auto"), - OBSOLETE("SysLog"), + OBSOLETE("Support022HiddenServices"), V(TestSocks, BOOL, "0"), - OBSOLETE("TestVia"), V(TokenBucketRefillInterval, MSEC_INTERVAL, "100 msec"), V(Tor2webMode, BOOL, "0"), V(TLSECGroup, STRING, NULL), V(TrackHostExits, CSV, NULL), V(TrackHostExitsExpire, INTERVAL, "30 minutes"), - OBSOLETE("TrafficShaping"), V(TransListenAddress, LINELIST, NULL), VPORT(TransPort, LINELIST, NULL), V(TransProxyType, STRING, "default"), @@ -466,6 +446,7 @@ static config_var_t option_vars_[] = { V(TestingDescriptorMaxDownloadTries, UINT, "8"), V(TestingMicrodescMaxDownloadTries, UINT, "8"), V(TestingCertMaxDownloadTries, UINT, "8"), + V(TestingDirAuthVoteExit, ROUTERSET, NULL), V(TestingDirAuthVoteGuard, ROUTERSET, NULL), VAR("___UsingTestNetworkDefaults", BOOL, UsingTestNetworkDefaults_, "0"), @@ -489,7 +470,7 @@ static const config_var_t testing_tor_network_defaults[] = { V(V3AuthVotingInterval, INTERVAL, "5 minutes"), V(V3AuthVoteDelay, INTERVAL, "20 seconds"), V(V3AuthDistDelay, INTERVAL, "20 seconds"), - V(TestingV3AuthInitialVotingInterval, INTERVAL, "5 minutes"), + V(TestingV3AuthInitialVotingInterval, INTERVAL, "150 seconds"), V(TestingV3AuthInitialVoteDelay, INTERVAL, "20 seconds"), V(TestingV3AuthInitialDistDelay, INTERVAL, "20 seconds"), V(TestingV3AuthVotingStartOffset, INTERVAL, "0"), @@ -536,12 +517,6 @@ static int options_transition_affects_workers( static int options_transition_affects_descriptor( const or_options_t *old_options, const or_options_t *new_options); static int check_nickname_list(char **lst, const char *name, char **msg); - -static int parse_client_transport_line(const or_options_t *options, - const char *line, int validate_only); - -static int parse_server_transport_line(const or_options_t *options, - const char *line, int validate_only); static char *get_bindaddr_from_transport_listen_line(const char *line, const char *transport); static int parse_dir_authority_line(const char *line, @@ -558,7 +533,8 @@ static int check_server_ports(const smartlist_t *ports, static int validate_data_directory(or_options_t *options); static int write_configuration_file(const char *fname, const or_options_t *options); -static int options_init_logs(or_options_t *options, int validate_only); +static int options_init_logs(const or_options_t *old_options, + or_options_t *options, int validate_only); static void init_libevent(const or_options_t *options); static int opt_streq(const char *s1, const char *s2); @@ -843,7 +819,9 @@ escaped_safe_str(const char *address) } /** Add the default directory authorities directly into the trusted dir list, - * but only add them insofar as they share bits with <b>type</b>. */ + * 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>. + * If <b>type</b> is ALL_DIRINFO or NO_DIRINFO (zero), add all authorities. */ static void add_default_trusted_dir_authorities(dirinfo_type_t type) { @@ -852,19 +830,22 @@ add_default_trusted_dir_authorities(dirinfo_type_t type) "moria1 orport=9101 " "v3ident=D586D18309DED4CD6D57C18FDB97EFA96D330566 " "128.31.0.39:9131 9695 DFC3 5FFE B861 329B 9F1A B04C 4639 7020 CE31", - "tor26 orport=443 v3ident=14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4 " + "tor26 orport=443 " + "v3ident=14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4 " "86.59.21.38:80 847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D", - "dizum orport=443 v3ident=E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58 " + "dizum orport=443 " + "v3ident=E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58 " "194.109.206.212:80 7EA6 EAD6 FD83 083C 538F 4403 8BBF A077 587D D755", - "Tonga orport=443 bridge 82.94.251.203:80 " - "4A0C CD2D DC79 9508 3D73 F5D6 6710 0C8A 5831 F16D", + "Tonga orport=443 bridge " + "82.94.251.203:80 4A0C CD2D DC79 9508 3D73 F5D6 6710 0C8A 5831 F16D", "gabelmoo orport=443 " "v3ident=ED03BB616EB2F60BEC80151114BB25CEF515B226 " "131.188.40.189:80 F204 4413 DAC2 E02E 3D6B CF47 35A1 9BCA 1DE9 7281", "dannenberg orport=443 " "v3ident=585769C78764D58426B8B52B6651A5A71137189A " "193.23.244.244:80 7BE6 83E6 5D48 1413 21C5 ED92 F075 C553 64AC 7123", - "urras orport=80 v3ident=80550987E1D626E3EBA5E5E75A458DE0626D088C " + "urras orport=80 " + "v3ident=80550987E1D626E3EBA5E5E75A458DE0626D088C " "208.83.223.34:443 0AD3 FA88 4D18 F89E EA2D 89C0 1937 9E0E 7FD9 4417", "maatuska orport=80 " "v3ident=49015F787433103580E3B66A1707A00E60F2D15B " @@ -985,7 +966,10 @@ consider_adding_dir_servers(const or_options_t *options, type |= BRIDGE_DIRINFO; if (!options->AlternateDirAuthority) type |= V3_DIRINFO | EXTRAINFO_DIRINFO | MICRODESC_DIRINFO; - add_default_trusted_dir_authorities(type); + /* if type == NO_DIRINFO, we don't want to add any of the + * default authorities, because we've replaced them all */ + if (type != NO_DIRINFO) + add_default_trusted_dir_authorities(type); } if (!options->FallbackDir) add_default_fallback_dir_servers(); @@ -1021,7 +1005,7 @@ options_act_reversible(const or_options_t *old_options, char **msg) int running_tor = options->command == CMD_RUN_TOR; int set_conn_limit = 0; int r = -1; - int logs_marked = 0; + int logs_marked = 0, logs_initialized = 0; int old_min_log_level = get_min_log_level(); /* Daemonize _first_, since we only want to open most of this stuff in @@ -1067,6 +1051,14 @@ options_act_reversible(const or_options_t *old_options, char **msg) if (running_tor && !libevent_initialized) { init_libevent(options); libevent_initialized = 1; + + /* + * Initialize the scheduler - this has to come after + * options_init_from_torrc() sets up libevent - why yes, that seems + * completely sensible to hide the libevent setup in the option parsing + * code! It also needs to happen before init_keys(), so it needs to + * happen here too. How yucky. */ + scheduler_init(); } /* Adjust the port configuration so we can launch listeners. */ @@ -1096,6 +1088,8 @@ options_act_reversible(const or_options_t *old_options, char **msg) "non-control network connections. Shutting down all existing " "connections."); connection_mark_all_noncontrol_connections(); + /* We can't complete circuits until the network is re-enabled. */ + note_that_we_maybe_cant_complete_circuits(); } } @@ -1146,10 +1140,12 @@ options_act_reversible(const or_options_t *old_options, char **msg) mark_logs_temp(); /* Close current logs once new logs are open. */ logs_marked = 1; - if (options_init_logs(options, 0)<0) { /* Configure the tor_log(s) */ + /* Configure the tor_log(s) */ + if (options_init_logs(old_options, options, 0)<0) { *msg = tor_strdup("Failed to init Log options. See logs for details."); goto rollback; } + logs_initialized = 1; commit: r = 0; @@ -1162,6 +1158,9 @@ options_act_reversible(const or_options_t *old_options, char **msg) tor_free(severity); tor_log_update_sigsafe_err_fds(); } + if (logs_initialized) { + flush_log_messages_from_startup(); + } { const char *badness = NULL; @@ -1425,24 +1424,26 @@ options_act(const or_options_t *old_options) mark_transport_list(); pt_prepare_proxy_list_for_config_read(); - if (options->ClientTransportPlugin) { - for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { - if (parse_client_transport_line(options, cl->value, 0)<0) { - log_warn(LD_BUG, - "Previously validated ClientTransportPlugin line " - "could not be added!"); - return -1; + if (!options->DisableNetwork) { + if (options->ClientTransportPlugin) { + for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { + if (parse_transport_line(options, cl->value, 0, 0) < 0) { + log_warn(LD_BUG, + "Previously validated ClientTransportPlugin line " + "could not be added!"); + return -1; + } } } - } - if (options->ServerTransportPlugin && server_mode(options)) { - for (cl = options->ServerTransportPlugin; cl; cl = cl->next) { - if (parse_server_transport_line(options, cl->value, 0)<0) { - log_warn(LD_BUG, - "Previously validated ServerTransportPlugin line " - "could not be added!"); - return -1; + if (options->ServerTransportPlugin && server_mode(options)) { + for (cl = options->ServerTransportPlugin; cl; cl = cl->next) { + if (parse_transport_line(options, cl->value, 0, 1) < 0) { + log_warn(LD_BUG, + "Previously validated ServerTransportPlugin line " + "could not be added!"); + return -1; + } } } } @@ -1539,6 +1540,12 @@ options_act(const or_options_t *old_options) return -1; } + /* Set up scheduler thresholds */ + scheduler_set_watermarks((uint32_t)options->SchedulerLowWaterMark__, + (uint32_t)options->SchedulerHighWaterMark__, + (options->SchedulerMaxFlushCells__ > 0) ? + options->SchedulerMaxFlushCells__ : 1000); + /* Set up accounting */ if (accounting_parse_options(options, 0)<0) { log_warn(LD_CONFIG,"Error in accounting options"); @@ -1593,6 +1600,20 @@ options_act(const or_options_t *old_options) return -1; } + config_maybe_load_geoip_files_(options, old_options); + + if (geoip_is_loaded(AF_INET) && options->GeoIPExcludeUnknown) { + /* ExcludeUnknown is true or "auto" */ + const int is_auto = options->GeoIPExcludeUnknown == -1; + int changed; + + changed = routerset_add_unknown_ccs(&options->ExcludeNodes, is_auto); + changed += routerset_add_unknown_ccs(&options->ExcludeExitNodes, is_auto); + + if (changed) + routerset_add_unknown_ccs(&options->ExcludeExitNodesUnion_, is_auto); + } + /* Check for transitions that need action. */ if (old_options) { int revise_trackexithosts = 0; @@ -1672,7 +1693,7 @@ options_act(const or_options_t *old_options) if (server_mode(options) && !server_mode(old_options)) { ip_address_changed(0); - if (can_complete_circuit || !any_predicted_circuits(time(NULL))) + if (have_completed_a_circuit() || !any_predicted_circuits(time(NULL))) inform_testing_reachability(); } cpuworkers_rotate(); @@ -1688,36 +1709,23 @@ options_act(const or_options_t *old_options) connection_or_update_token_buckets(get_connection_array(), options); } - config_maybe_load_geoip_files_(options, old_options); - - if (geoip_is_loaded(AF_INET) && options->GeoIPExcludeUnknown) { - /* ExcludeUnknown is true or "auto" */ - const int is_auto = options->GeoIPExcludeUnknown == -1; - int changed; - - changed = routerset_add_unknown_ccs(&options->ExcludeNodes, is_auto); - changed += routerset_add_unknown_ccs(&options->ExcludeExitNodes, is_auto); - - if (changed) - routerset_add_unknown_ccs(&options->ExcludeExitNodesUnion_, is_auto); - } + /* Only collect directory-request statistics on relays and bridges. */ + options->DirReqStatistics = options->DirReqStatistics_option && + server_mode(options); if (options->CellStatistics || options->DirReqStatistics || options->EntryStatistics || options->ExitPortStatistics || options->ConnDirectionStatistics || + options->HiddenServiceStatistics || options->BridgeAuthoritativeDir) { time_t now = time(NULL); int print_notice = 0; - /* Only collect directory-request statistics on relays and bridges. */ - if (!server_mode(options)) { - options->DirReqStatistics = 0; - } - /* Only collect other relay-only statistics on relays. */ if (!public_server_mode(options)) { options->CellStatistics = 0; options->EntryStatistics = 0; + options->HiddenServiceStatistics = 0; options->ExitPortStatistics = 0; } @@ -1732,8 +1740,8 @@ options_act(const or_options_t *old_options) geoip_dirreq_stats_init(now); print_notice = 1; } else { + /* disable statistics collection since we have no geoip file */ options->DirReqStatistics = 0; - /* Don't warn Tor clients, they don't use statistics */ if (options->ORPort_set) log_notice(LD_CONFIG, "Configured to measure directory request " "statistics, but no GeoIP database found. " @@ -1763,6 +1771,11 @@ options_act(const or_options_t *old_options) options->ConnDirectionStatistics) { rep_hist_conn_stats_init(now); } + if ((!old_options || !old_options->HiddenServiceStatistics) && + options->HiddenServiceStatistics) { + log_info(LD_CONFIG, "Configured to measure hidden service statistics."); + rep_hist_hs_stats_init(now); + } if ((!old_options || !old_options->BridgeAuthoritativeDir) && options->BridgeAuthoritativeDir) { rep_hist_desc_stats_init(now); @@ -1774,6 +1787,8 @@ options_act(const or_options_t *old_options) "data directory in 24 hours from now."); } + /* If we used to have statistics enabled but we just disabled them, + stop gathering them. */ if (old_options && old_options->CellStatistics && !options->CellStatistics) rep_hist_buffer_stats_term(); @@ -1783,6 +1798,9 @@ options_act(const or_options_t *old_options) if (old_options && old_options->EntryStatistics && !options->EntryStatistics) geoip_entry_stats_term(); + if (old_options && old_options->HiddenServiceStatistics && + !options->HiddenServiceStatistics) + rep_hist_hs_stats_term(); if (old_options && old_options->ExitPortStatistics && !options->ExitPortStatistics) rep_hist_exit_stats_term(); @@ -1815,7 +1833,7 @@ options_act(const or_options_t *old_options) directory_fetches_dir_info_early(old_options)) || !bool_eq(directory_fetches_dir_info_later(options), directory_fetches_dir_info_later(old_options))) { - /* Make sure update_router_have_min_dir_info gets called. */ + /* Make sure update_router_have_minimum_dir_info() gets called. */ router_dir_info_changed(); /* We might need to download a new consensus status later or sooner than * we had expected. */ @@ -2029,7 +2047,7 @@ print_usage(void) printf( "Copyright (c) 2001-2004, Roger Dingledine\n" "Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson\n" -"Copyright (c) 2007-2013, The Tor Project, Inc.\n\n" +"Copyright (c) 2007-2015, The Tor Project, Inc.\n\n" "tor -f <torrc> [args]\n" "See man page for options, or https://www.torproject.org/ for " "documentation.\n"); @@ -2061,8 +2079,41 @@ get_last_resolved_addr(void) return last_resolved_addr; } +/** Reset last_resolved_addr from outside this file. */ +void +reset_last_resolved_addr(void) +{ + last_resolved_addr = 0; +} + /** - * Use <b>options-\>Address</b> to guess our public IP address. + * Attempt getting our non-local (as judged by tor_addr_is_internal() + * function) IP address using following techniques, listed in + * order from best (most desirable, try first) to worst (least + * desirable, try if everything else fails). + * + * First, attempt using <b>options-\>Address</b> to get our + * non-local IP address. + * + * If <b>options-\>Address</b> represents a non-local IP address, + * consider it ours. + * + * If <b>options-\>Address</b> is a DNS name that resolves to + * a non-local IP address, consider this IP address ours. + * + * If <b>options-\>Address</b> is NULL, fall back to getting local + * hostname and using it in above-described ways to try and + * get our IP address. + * + * In case local hostname cannot be resolved to a non-local IP + * address, try getting an IP address of network interface + * in hopes it will be non-local one. + * + * Fail if one or more of the following is true: + * - DNS name in <b>options-\>Address</b> cannot be resolved. + * - <b>options-\>Address</b> is a local host address. + * - Attempt to getting local hostname fails. + * - Attempt to getting network interface address fails. * * Return 0 if all is well, or -1 if we can't find a suitable * public IP address. @@ -2071,6 +2122,11 @@ get_last_resolved_addr(void) * - Put our public IP address (in host order) into *<b>addr_out</b>. * - If <b>method_out</b> is non-NULL, set *<b>method_out</b> to a static * string describing how we arrived at our answer. + * - "CONFIGURED" - parsed from IP address string in + * <b>options-\>Address</b> + * - "RESOLVED" - resolved from DNS name in <b>options-\>Address</b> + * - "GETHOSTNAME" - resolved from a local hostname. + * - "INTERFACE" - retrieved from a network interface. * - If <b>hostname_out</b> is non-NULL, and we resolved a hostname to * get our address, set *<b>hostname_out</b> to a newly allocated string * holding that hostname. (If we didn't get our address by resolving a @@ -2109,7 +2165,7 @@ resolve_my_address(int warn_severity, const or_options_t *options, explicit_ip = 0; /* it's implicit */ explicit_hostname = 0; /* it's implicit */ - if (gethostname(hostname, sizeof(hostname)) < 0) { + if (tor_gethostname(hostname, sizeof(hostname)) < 0) { log_fn(warn_severity, LD_NET,"Error obtaining local hostname"); return -1; } @@ -2276,8 +2332,8 @@ resolve_my_address(int warn_severity, const or_options_t *options, /** Return true iff <b>addr</b> is judged to be on the same network as us, or * on a private network. */ -int -is_local_addr(const tor_addr_t *addr) +MOCK_IMPL(int, +is_local_addr, (const tor_addr_t *addr)) { if (tor_addr_is_internal(addr, 0)) return 1; @@ -2549,7 +2605,8 @@ options_validate(or_options_t *old_options, or_options_t *options, config_line_append(&options->Logs, "Log", "warn stdout"); } - if (options_init_logs(options, 1)<0) /* Validate the tor_log(s) */ + /* Validate the tor_log(s) */ + if (options_init_logs(old_options, options, 1)<0) REJECT("Failed to validate Log options. See logs for details."); if (authdir_mode(options)) { @@ -2585,20 +2642,24 @@ options_validate(or_options_t *old_options, or_options_t *options, if (!strcasecmp(options->TransProxyType, "default")) { options->TransProxyType_parsed = TPT_DEFAULT; } else if (!strcasecmp(options->TransProxyType, "pf-divert")) { -#ifndef __OpenBSD__ - REJECT("pf-divert is a OpenBSD-specific feature."); +#if !defined(__OpenBSD__) && !defined( DARWIN ) + /* Later versions of OS X have pf */ + REJECT("pf-divert is a OpenBSD-specific " + "and OS X/Darwin-specific feature."); #else options->TransProxyType_parsed = TPT_PF_DIVERT; #endif } else if (!strcasecmp(options->TransProxyType, "tproxy")) { -#ifndef __linux__ +#if !defined(__linux__) REJECT("TPROXY is a Linux-specific feature."); #else options->TransProxyType_parsed = TPT_TPROXY; #endif } else if (!strcasecmp(options->TransProxyType, "ipfw")) { -#ifndef __FreeBSD__ - REJECT("ipfw is a FreeBSD-specific feature."); +#if !defined(__FreeBSD__) && !defined( DARWIN ) + /* Earlier versions of OS X have ipfw */ + REJECT("ipfw is a FreeBSD-specific" + "and OS X/Darwin-specific feature."); #else options->TransProxyType_parsed = TPT_IPFW; #endif @@ -2629,6 +2690,17 @@ options_validate(or_options_t *old_options, or_options_t *options, routerset_union(options->ExcludeExitNodesUnion_,options->ExcludeNodes); } + if (options->SchedulerLowWaterMark__ == 0 || + options->SchedulerLowWaterMark__ > UINT32_MAX) { + log_warn(LD_GENERAL, "Bad SchedulerLowWaterMark__ option"); + return -1; + } else if (options->SchedulerHighWaterMark__ <= + options->SchedulerLowWaterMark__ || + options->SchedulerHighWaterMark__ > UINT32_MAX) { + log_warn(LD_GENERAL, "Bad SchedulerHighWaterMark option"); + return -1; + } + if (options->NodeFamilies) { options->NodeFamilySets = smartlist_new(); for (cl = options->NodeFamilies; cl; cl = cl->next) { @@ -2839,6 +2911,7 @@ options_validate(or_options_t *old_options, or_options_t *options, options->MaxMemInQueues = compute_real_max_mem_in_queues(options->MaxMemInQueues_raw, server_mode(options)); + options->MaxMemInQueues_low_threshold = (options->MaxMemInQueues / 4) * 3; options->AllowInvalid_ = 0; @@ -3135,6 +3208,16 @@ options_validate(or_options_t *old_options, or_options_t *options, } } + options->AccountingRule = ACCT_MAX; + if (options->AccountingRule_option) { + if (!strcmp(options->AccountingRule_option, "sum")) + options->AccountingRule = ACCT_SUM; + else if (!strcmp(options->AccountingRule_option, "max")) + options->AccountingRule = ACCT_MAX; + else + REJECT("AccountingRule must be 'sum' or 'max'"); + } + if (options->HTTPProxy) { /* parse it now */ if (tor_addr_port_lookup(options->HTTPProxy, &options->HTTPProxyAddr, &options->HTTPProxyPort) < 0) @@ -3183,11 +3266,11 @@ options_validate(or_options_t *old_options, or_options_t *options, } } - /* Check if more than one proxy type has been enabled. */ + /* Check if more than one exclusive proxy type has been enabled. */ if (!!options->Socks4Proxy + !!options->Socks5Proxy + - !!options->HTTPSProxy + !!options->ClientTransportPlugin > 1) + !!options->HTTPSProxy > 1) REJECT("You have configured more than one proxy type. " - "(Socks4Proxy|Socks5Proxy|HTTPSProxy|ClientTransportPlugin)"); + "(Socks4Proxy|Socks5Proxy|HTTPSProxy)"); /* Check if the proxies will give surprising behavior. */ if (options->HTTPProxy && !(options->Socks4Proxy || @@ -3295,12 +3378,12 @@ options_validate(or_options_t *old_options, or_options_t *options, } for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { - if (parse_client_transport_line(options, cl->value, 1)<0) + if (parse_transport_line(options, cl->value, 1, 0) < 0) REJECT("Invalid client transport line. See logs for details."); } for (cl = options->ServerTransportPlugin; cl; cl = cl->next) { - if (parse_server_transport_line(options, cl->value, 1)<0) + if (parse_transport_line(options, cl->value, 1, 1) < 0) REJECT("Invalid server transport line. See logs for details."); } @@ -3364,19 +3447,68 @@ options_validate(or_options_t *old_options, or_options_t *options, if (options->V3AuthVoteDelay + options->V3AuthDistDelay >= options->V3AuthVotingInterval/2) { - REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than half " - "V3AuthVotingInterval"); + /* + This doesn't work, but it seems like it should: + what code is preventing the interval being less than twice the lead-up? + if (options->TestingTorNetwork) { + if (options->V3AuthVoteDelay + options->V3AuthDistDelay >= + options->V3AuthVotingInterval) { + REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than " + "V3AuthVotingInterval"); + } else { + COMPLAIN("V3AuthVoteDelay plus V3AuthDistDelay is more than half " + "V3AuthVotingInterval. This may lead to " + "consensus instability, particularly if clocks drift."); + } + } else { + */ + REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than half " + "V3AuthVotingInterval"); + /* + } + */ + } + + if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS) { + if (options->TestingTorNetwork) { + if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS_TESTING) { + REJECT("V3AuthVoteDelay is way too low."); + } else { + COMPLAIN("V3AuthVoteDelay is very low. " + "This may lead to failure to vote for a consensus."); + } + } else { + REJECT("V3AuthVoteDelay is way too low."); + } + } + + if (options->V3AuthDistDelay < MIN_DIST_SECONDS) { + if (options->TestingTorNetwork) { + if (options->V3AuthDistDelay < MIN_DIST_SECONDS_TESTING) { + REJECT("V3AuthDistDelay is way too low."); + } else { + COMPLAIN("V3AuthDistDelay is very low. " + "This may lead to missing votes in a consensus."); + } + } else { + REJECT("V3AuthDistDelay is way too low."); + } } - if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS) - REJECT("V3AuthVoteDelay is way too low."); - if (options->V3AuthDistDelay < MIN_DIST_SECONDS) - REJECT("V3AuthDistDelay is way too low."); if (options->V3AuthNIntervalsValid < 2) REJECT("V3AuthNIntervalsValid must be at least 2."); if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL) { - REJECT("V3AuthVotingInterval is insanely low."); + if (options->TestingTorNetwork) { + if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL_TESTING) { + REJECT("V3AuthVotingInterval is insanely low."); + } else { + COMPLAIN("V3AuthVotingInterval is very low. " + "This may lead to failure to synchronise for a consensus."); + } + } else { + REJECT("V3AuthVotingInterval is insanely low."); + } } else if (options->V3AuthVotingInterval > 24*60*60) { REJECT("V3AuthVotingInterval is insanely high."); } else if (((24*60*60) % options->V3AuthVotingInterval) != 0) { @@ -3442,26 +3574,27 @@ options_validate(or_options_t *old_options, or_options_t *options, CHECK_DEFAULT(TestingCertMaxDownloadTries); #undef CHECK_DEFAULT - if (options->TestingV3AuthInitialVotingInterval < MIN_VOTE_INTERVAL) { + if (options->TestingV3AuthInitialVotingInterval + < MIN_VOTE_INTERVAL_TESTING_INITIAL) { REJECT("TestingV3AuthInitialVotingInterval is insanely low."); } else if (((30*60) % options->TestingV3AuthInitialVotingInterval) != 0) { REJECT("TestingV3AuthInitialVotingInterval does not divide evenly into " "30 minutes."); } - if (options->TestingV3AuthInitialVoteDelay < MIN_VOTE_SECONDS) { + if (options->TestingV3AuthInitialVoteDelay < MIN_VOTE_SECONDS_TESTING) { REJECT("TestingV3AuthInitialVoteDelay is way too low."); } - if (options->TestingV3AuthInitialDistDelay < MIN_DIST_SECONDS) { + if (options->TestingV3AuthInitialDistDelay < MIN_DIST_SECONDS_TESTING) { REJECT("TestingV3AuthInitialDistDelay is way too low."); } if (options->TestingV3AuthInitialVoteDelay + options->TestingV3AuthInitialDistDelay >= - options->TestingV3AuthInitialVotingInterval/2) { + options->TestingV3AuthInitialVotingInterval) { REJECT("TestingV3AuthInitialVoteDelay plus TestingV3AuthInitialDistDelay " - "must be less than half TestingV3AuthInitialVotingInterval"); + "must be less than TestingV3AuthInitialVotingInterval"); } if (options->TestingV3AuthVotingStartOffset > @@ -3469,6 +3602,8 @@ options_validate(or_options_t *old_options, or_options_t *options, options->V3AuthVotingInterval)) { REJECT("TestingV3AuthVotingStartOffset is higher than the voting " "interval."); + } else if (options->TestingV3AuthVotingStartOffset < 0) { + REJECT("TestingV3AuthVotingStartOffset must be non-negative."); } if (options->TestingAuthDirTimeToLearnReachability < 0) { @@ -4446,7 +4581,8 @@ addressmap_register_auto(const char *from, const char *to, * Initialize the logs based on the configuration file. */ static int -options_init_logs(or_options_t *options, int validate_only) +options_init_logs(const or_options_t *old_options, or_options_t *options, + int validate_only) { config_line_t *opt; int ok; @@ -4539,7 +4675,21 @@ options_init_logs(or_options_t *options, int validate_only) !strcasecmp(smartlist_get(elts,0), "file")) { if (!validate_only) { char *fname = expand_filename(smartlist_get(elts, 1)); - if (add_file_log(severity, fname) < 0) { + /* Truncate if TruncateLogFile is set and we haven't seen this option + line before. */ + int truncate = 0; + if (options->TruncateLogFile) { + truncate = 1; + if (old_options) { + config_line_t *opt2; + for (opt2 = old_options->Logs; opt2; opt2 = opt2->next) + if (!strcmp(opt->value, opt2->value)) { + truncate = 0; + break; + } + } + } + if (add_file_log(severity, fname, truncate) < 0) { log_warn(LD_CONFIG, "Couldn't open file for 'Log %s': %s", opt->value, strerror(errno)); ok = 0; @@ -4732,46 +4882,52 @@ parse_bridge_line(const char *line) return bridge_line; } -/** Read the contents of a ClientTransportPlugin line from - * <b>line</b>. Return 0 if the line is well-formed, and -1 if it - * isn't. +/** Read the contents of a ClientTransportPlugin or ServerTransportPlugin + * line from <b>line</b>, depending on the value of <b>server</b>. Return 0 + * if the line is well-formed, and -1 if it isn't. * - * If <b>validate_only</b> is 0, the line is well-formed, and the - * transport is needed by some bridge: + * If <b>validate_only</b> is 0, the line is well-formed, and the transport is + * needed by some bridge: * - If it's an external proxy line, add the transport described in the line to * our internal transport list. - * - If it's a managed proxy line, launch the managed proxy. */ -static int -parse_client_transport_line(const or_options_t *options, - const char *line, int validate_only) + * - If it's a managed proxy line, launch the managed proxy. + */ + +STATIC int +parse_transport_line(const or_options_t *options, + const char *line, int validate_only, + int server) { + smartlist_t *items = NULL; int r; - char *field2=NULL; - - const char *transports=NULL; - smartlist_t *transport_list=NULL; - char *addrport=NULL; + const char *transports = NULL; + smartlist_t *transport_list = NULL; + char *type = NULL; + char *addrport = NULL; tor_addr_t addr; uint16_t port = 0; - int socks_ver=PROXY_NONE; + int socks_ver = PROXY_NONE; /* managed proxy options */ - int is_managed=0; - char **proxy_argv=NULL; - char **tmp=NULL; + int is_managed = 0; + char **proxy_argv = NULL; + char **tmp = NULL; int proxy_argc, i; - int is_useless_proxy=1; + int is_useless_proxy = 1; int line_length; + /* Split the line into space-separated tokens */ items = smartlist_new(); smartlist_split_string(items, line, NULL, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); + line_length = smartlist_len(items); - line_length = smartlist_len(items); if (line_length < 3) { - log_warn(LD_CONFIG, "Too few arguments on ClientTransportPlugin line."); + log_warn(LD_CONFIG, + "Too few arguments on %sTransportPlugin line.", + server ? "Server" : "Client"); goto err; } @@ -4795,64 +4951,97 @@ parse_client_transport_line(const or_options_t *options, is_useless_proxy = 0; } SMARTLIST_FOREACH_END(transport_name); - /* field2 is either a SOCKS version or "exec" */ - field2 = smartlist_get(items, 1); - - if (!strcmp(field2,"socks4")) { + type = smartlist_get(items, 1); + if (!strcmp(type, "exec")) { + is_managed = 1; + } else if (server && !strcmp(type, "proxy")) { + /* 'proxy' syntax only with ServerTransportPlugin */ + is_managed = 0; + } else if (!server && !strcmp(type, "socks4")) { + /* 'socks4' syntax only with ClientTransportPlugin */ + is_managed = 0; socks_ver = PROXY_SOCKS4; - } else if (!strcmp(field2,"socks5")) { + } else if (!server && !strcmp(type, "socks5")) { + /* 'socks5' syntax only with ClientTransportPlugin */ + is_managed = 0; socks_ver = PROXY_SOCKS5; - } else if (!strcmp(field2,"exec")) { - is_managed=1; } else { - log_warn(LD_CONFIG, "Strange ClientTransportPlugin field '%s'.", - field2); + log_warn(LD_CONFIG, + "Strange %sTransportPlugin type '%s'", + server ? "Server" : "Client", type); goto err; } if (is_managed && options->Sandbox) { - log_warn(LD_CONFIG, "Managed proxies are not compatible with Sandbox mode." - "(ClientTransportPlugin line was %s)", escaped(line)); + log_warn(LD_CONFIG, + "Managed proxies are not compatible with Sandbox mode." + "(%sTransportPlugin line was %s)", + server ? "Server" : "Client", escaped(line)); goto err; } - if (is_managed) { /* managed */ - if (!validate_only && is_useless_proxy) { - log_info(LD_GENERAL, "Pluggable transport proxy (%s) does not provide " - "any needed transports and will not be launched.", line); + if (is_managed) { + /* managed */ + + if (!server && !validate_only && is_useless_proxy) { + log_info(LD_GENERAL, + "Pluggable transport proxy (%s) does not provide " + "any needed transports and will not be launched.", + line); } - /* If we are not just validating, use the rest of the line as the - argv of the proxy to be launched. Also, make sure that we are - only launching proxies that contribute useful transports. */ - if (!validate_only && !is_useless_proxy) { - proxy_argc = line_length-2; + /* + * If we are not just validating, use the rest of the line as the + * argv of the proxy to be launched. Also, make sure that we are + * only launching proxies that contribute useful transports. + */ + + if (!validate_only && (server || !is_useless_proxy)) { + proxy_argc = line_length - 2; tor_assert(proxy_argc > 0); - proxy_argv = tor_malloc_zero(sizeof(char*)*(proxy_argc+1)); + proxy_argv = tor_calloc((proxy_argc + 1), sizeof(char *)); tmp = proxy_argv; - for (i=0;i<proxy_argc;i++) { /* store arguments */ + + for (i = 0; i < proxy_argc; i++) { + /* store arguments */ *tmp++ = smartlist_get(items, 2); smartlist_del_keeporder(items, 2); } - *tmp = NULL; /*terminated with NULL, just like execve() likes it*/ + *tmp = NULL; /* terminated with NULL, just like execve() likes it */ /* kickstart the thing */ - pt_kickstart_client_proxy(transport_list, proxy_argv); + if (server) { + pt_kickstart_server_proxy(transport_list, proxy_argv); + } else { + pt_kickstart_client_proxy(transport_list, proxy_argv); + } } - } else { /* external */ + } else { + /* external */ + + /* ClientTransportPlugins connecting through a proxy is managed only. */ + if (!server && (options->Socks4Proxy || options->Socks5Proxy || + options->HTTPSProxy)) { + log_warn(LD_CONFIG, "You have configured an external proxy with another " + "proxy type. (Socks4Proxy|Socks5Proxy|HTTPSProxy)"); + goto err; + } + if (smartlist_len(transport_list) != 1) { - log_warn(LD_CONFIG, "You can't have an external proxy with " - "more than one transports."); + log_warn(LD_CONFIG, + "You can't have an external proxy with more than " + "one transport."); goto err; } addrport = smartlist_get(items, 2); - if (tor_addr_port_lookup(addrport, &addr, &port)<0) { - log_warn(LD_CONFIG, "Error parsing transport " - "address '%s'", addrport); + if (tor_addr_port_lookup(addrport, &addr, &port) < 0) { + log_warn(LD_CONFIG, + "Error parsing transport address '%s'", addrport); goto err; } + if (!port) { log_warn(LD_CONFIG, "Transport address '%s' has no port.", addrport); @@ -4860,11 +5049,15 @@ parse_client_transport_line(const or_options_t *options, } if (!validate_only) { - transport_add_from_config(&addr, port, smartlist_get(transport_list, 0), - socks_ver); - - log_info(LD_DIR, "Transport '%s' found at %s", + log_info(LD_DIR, "%s '%s' at %s.", + server ? "Server transport" : "Transport", transports, fmt_addrport(&addr, port)); + + if (!server) { + transport_add_from_config(&addr, port, + smartlist_get(transport_list, 0), + socks_ver); + } } } @@ -5036,138 +5229,12 @@ get_options_for_server_transport(const char *transport) return NULL; } -/** Read the contents of a ServerTransportPlugin line from - * <b>line</b>. Return 0 if the line is well-formed, and -1 if it - * isn't. - * If <b>validate_only</b> is 0, the line is well-formed, and it's a - * managed proxy line, launch the managed proxy. */ -static int -parse_server_transport_line(const or_options_t *options, - const char *line, int validate_only) -{ - smartlist_t *items = NULL; - int r; - const char *transports=NULL; - smartlist_t *transport_list=NULL; - char *type=NULL; - char *addrport=NULL; - tor_addr_t addr; - uint16_t port = 0; - - /* managed proxy options */ - int is_managed=0; - char **proxy_argv=NULL; - char **tmp=NULL; - int proxy_argc,i; - - int line_length; - - items = smartlist_new(); - smartlist_split_string(items, line, NULL, - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); - - line_length = smartlist_len(items); - if (line_length < 3) { - log_warn(LD_CONFIG, "Too few arguments on ServerTransportPlugin line."); - goto err; - } - - /* Get the first line element, split it to commas into - transport_list (in case it's multiple transports) and validate - the transport names. */ - transports = smartlist_get(items, 0); - transport_list = smartlist_new(); - smartlist_split_string(transport_list, transports, ",", - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - SMARTLIST_FOREACH_BEGIN(transport_list, const char *, transport_name) { - if (!string_is_C_identifier(transport_name)) { - log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).", - transport_name); - goto err; - } - } SMARTLIST_FOREACH_END(transport_name); - - type = smartlist_get(items, 1); - - if (!strcmp(type, "exec")) { - is_managed=1; - } else if (!strcmp(type, "proxy")) { - is_managed=0; - } else { - log_warn(LD_CONFIG, "Strange ServerTransportPlugin type '%s'", type); - goto err; - } - - if (is_managed && options->Sandbox) { - log_warn(LD_CONFIG, "Managed proxies are not compatible with Sandbox mode." - "(ServerTransportPlugin line was %s)", escaped(line)); - goto err; - } - - if (is_managed) { /* managed */ - if (!validate_only) { - proxy_argc = line_length-2; - tor_assert(proxy_argc > 0); - proxy_argv = tor_malloc_zero(sizeof(char*)*(proxy_argc+1)); - tmp = proxy_argv; - - for (i=0;i<proxy_argc;i++) { /* store arguments */ - *tmp++ = smartlist_get(items, 2); - smartlist_del_keeporder(items, 2); - } - *tmp = NULL; /*terminated with NULL, just like execve() likes it*/ - - /* kickstart the thing */ - pt_kickstart_server_proxy(transport_list, proxy_argv); - } - } else { /* external */ - if (smartlist_len(transport_list) != 1) { - log_warn(LD_CONFIG, "You can't have an external proxy with " - "more than one transports."); - goto err; - } - - addrport = smartlist_get(items, 2); - - if (tor_addr_port_lookup(addrport, &addr, &port)<0) { - log_warn(LD_CONFIG, "Error parsing transport " - "address '%s'", addrport); - goto err; - } - if (!port) { - log_warn(LD_CONFIG, - "Transport address '%s' has no port.", addrport); - goto err; - } - - if (!validate_only) { - log_info(LD_DIR, "Server transport '%s' at %s.", - transports, fmt_addrport(&addr, port)); - } - } - - r = 0; - goto done; - - err: - r = -1; - - done: - SMARTLIST_FOREACH(items, char*, s, tor_free(s)); - smartlist_free(items); - if (transport_list) { - SMARTLIST_FOREACH(transport_list, char*, s, tor_free(s)); - smartlist_free(transport_list); - } - - return r; -} - /** Read the contents of a DirAuthority line from <b>line</b>. If * <b>validate_only</b> is 0, and the line is well-formed, and it * shares any bits with <b>required_type</b> or <b>required_type</b> - * is 0, then add the dirserver described in the line (minus whatever - * bits it's missing) as a valid authority. Return 0 on success, + * is NO_DIRINFO (zero), then add the dirserver described in the line + * (minus whatever bits it's missing) as a valid authority. + * Return 0 on success or filtering out by type, * or -1 if the line isn't well-formed or if we can't add it. */ static int parse_dir_authority_line(const char *line, dirinfo_type_t required_type, |