Create circuitbuild.h
[tor/rransom.git] / src / or / config.c
blob9996d1cc54bbfbb7667af87f0aa95bf9384ab049
1 /* Copyright (c) 2001 Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2010, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
7 /**
8 * \file config.c
9 * \brief Code to parse and interpret configuration files.
10 **/
12 #define CONFIG_PRIVATE
14 #include "or.h"
15 #include "circuitbuild.h"
16 #include "geoip.h"
17 #include "rendclient.h"
18 #include "rendservice.h"
19 #include "router.h"
20 #include "routerlist.h"
21 #ifdef MS_WINDOWS
22 #include <shlobj.h>
23 #endif
25 /** Enumeration of types which option values can take */
26 typedef enum config_type_t {
27 CONFIG_TYPE_STRING = 0, /**< An arbitrary string. */
28 CONFIG_TYPE_FILENAME, /**< A filename: some prefixes get expanded. */
29 CONFIG_TYPE_UINT, /**< A non-negative integer less than MAX_INT */
30 CONFIG_TYPE_INTERVAL, /**< A number of seconds, with optional units*/
31 CONFIG_TYPE_MEMUNIT, /**< A number of bytes, with optional units*/
32 CONFIG_TYPE_DOUBLE, /**< A floating-point value */
33 CONFIG_TYPE_BOOL, /**< A boolean value, expressed as 0 or 1. */
34 CONFIG_TYPE_ISOTIME, /**< An ISO-formatted time relative to GMT. */
35 CONFIG_TYPE_CSV, /**< A list of strings, separated by commas and
36 * optional whitespace. */
37 CONFIG_TYPE_LINELIST, /**< Uninterpreted config lines */
38 CONFIG_TYPE_LINELIST_S, /**< Uninterpreted, context-sensitive config lines,
39 * mixed with other keywords. */
40 CONFIG_TYPE_LINELIST_V, /**< Catch-all "virtual" option to summarize
41 * context-sensitive config lines when fetching.
43 CONFIG_TYPE_ROUTERSET, /**< A list of router names, addrs, and fps,
44 * parsed into a routerset_t. */
45 CONFIG_TYPE_OBSOLETE, /**< Obsolete (ignored) option. */
46 } config_type_t;
48 /** An abbreviation for a configuration option allowed on the command line. */
49 typedef struct config_abbrev_t {
50 const char *abbreviated;
51 const char *full;
52 int commandline_only;
53 int warn;
54 } config_abbrev_t;
56 /* Handy macro for declaring "In the config file or on the command line,
57 * you can abbreviate <b>tok</b>s as <b>tok</b>". */
58 #define PLURAL(tok) { #tok, #tok "s", 0, 0 }
60 /** A list of abbreviations and aliases to map command-line options, obsolete
61 * option names, or alternative option names, to their current values. */
62 static config_abbrev_t _option_abbrevs[] = {
63 PLURAL(ExitNode),
64 PLURAL(EntryNode),
65 PLURAL(ExcludeNode),
66 PLURAL(FirewallPort),
67 PLURAL(LongLivedPort),
68 PLURAL(HiddenServiceNode),
69 PLURAL(HiddenServiceExcludeNode),
70 PLURAL(NumCpu),
71 PLURAL(RendNode),
72 PLURAL(RendExcludeNode),
73 PLURAL(StrictEntryNode),
74 PLURAL(StrictExitNode),
75 PLURAL(StrictNode),
76 { "l", "Log", 1, 0},
77 { "AllowUnverifiedNodes", "AllowInvalidNodes", 0, 0},
78 { "AutomapHostSuffixes", "AutomapHostsSuffixes", 0, 0},
79 { "AutomapHostOnResolve", "AutomapHostsOnResolve", 0, 0},
80 { "BandwidthRateBytes", "BandwidthRate", 0, 0},
81 { "BandwidthBurstBytes", "BandwidthBurst", 0, 0},
82 { "DirFetchPostPeriod", "StatusFetchPeriod", 0, 0},
83 { "MaxConn", "ConnLimit", 0, 1},
84 { "ORBindAddress", "ORListenAddress", 0, 0},
85 { "DirBindAddress", "DirListenAddress", 0, 0},
86 { "SocksBindAddress", "SocksListenAddress", 0, 0},
87 { "UseHelperNodes", "UseEntryGuards", 0, 0},
88 { "NumHelperNodes", "NumEntryGuards", 0, 0},
89 { "UseEntryNodes", "UseEntryGuards", 0, 0},
90 { "NumEntryNodes", "NumEntryGuards", 0, 0},
91 { "ResolvConf", "ServerDNSResolvConfFile", 0, 1},
92 { "SearchDomains", "ServerDNSSearchDomains", 0, 1},
93 { "ServerDNSAllowBrokenResolvConf", "ServerDNSAllowBrokenConfig", 0, 0},
94 { "PreferTunnelledDirConns", "PreferTunneledDirConns", 0, 0},
95 { "BridgeAuthoritativeDirectory", "BridgeAuthoritativeDir", 0, 0},
96 { "HashedControlPassword", "__HashedControlSessionPassword", 1, 0},
97 { "StrictEntryNodes", "StrictNodes", 0, 1},
98 { "StrictExitNodes", "StrictNodes", 0, 1},
99 { NULL, NULL, 0, 0},
102 /** A list of state-file "abbreviations," for compatibility. */
103 static config_abbrev_t _state_abbrevs[] = {
104 { "AccountingBytesReadInterval", "AccountingBytesReadInInterval", 0, 0 },
105 { "HelperNode", "EntryGuard", 0, 0 },
106 { "HelperNodeDownSince", "EntryGuardDownSince", 0, 0 },
107 { "HelperNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 },
108 { "EntryNode", "EntryGuard", 0, 0 },
109 { "EntryNodeDownSince", "EntryGuardDownSince", 0, 0 },
110 { "EntryNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 },
111 { NULL, NULL, 0, 0},
113 #undef PLURAL
115 /** A variable allowed in the configuration file or on the command line. */
116 typedef struct config_var_t {
117 const char *name; /**< The full keyword (case insensitive). */
118 config_type_t type; /**< How to interpret the type and turn it into a
119 * value. */
120 off_t var_offset; /**< Offset of the corresponding member of or_options_t. */
121 const char *initvalue; /**< String (or null) describing initial value. */
122 } config_var_t;
124 /** An entry for config_vars: "The option <b>name</b> has type
125 * CONFIG_TYPE_<b>conftype</b>, and corresponds to
126 * or_options_t.<b>member</b>"
128 #define VAR(name,conftype,member,initvalue) \
129 { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_options_t, member), \
130 initvalue }
131 /** As VAR, but the option name and member name are the same. */
132 #define V(member,conftype,initvalue) \
133 VAR(#member, conftype, member, initvalue)
134 /** An entry for config_vars: "The option <b>name</b> is obsolete." */
135 #define OBSOLETE(name) { name, CONFIG_TYPE_OBSOLETE, 0, NULL }
137 /** Array of configuration options. Until we disallow nonstandard
138 * abbreviations, order is significant, since the first matching option will
139 * be chosen first.
141 static config_var_t _option_vars[] = {
142 OBSOLETE("AccountingMaxKB"),
143 V(AccountingMax, MEMUNIT, "0 bytes"),
144 V(AccountingStart, STRING, NULL),
145 V(Address, STRING, NULL),
146 V(AllowDotExit, BOOL, "0"),
147 V(AllowInvalidNodes, CSV, "middle,rendezvous"),
148 V(AllowNonRFC953Hostnames, BOOL, "0"),
149 V(AllowSingleHopCircuits, BOOL, "0"),
150 V(AllowSingleHopExits, BOOL, "0"),
151 V(AlternateBridgeAuthority, LINELIST, NULL),
152 V(AlternateDirAuthority, LINELIST, NULL),
153 V(AlternateHSAuthority, LINELIST, NULL),
154 V(AssumeReachable, BOOL, "0"),
155 V(AuthDirBadDir, LINELIST, NULL),
156 V(AuthDirBadExit, LINELIST, NULL),
157 V(AuthDirInvalid, LINELIST, NULL),
158 V(AuthDirReject, LINELIST, NULL),
159 V(AuthDirRejectUnlisted, BOOL, "0"),
160 V(AuthDirListBadDirs, BOOL, "0"),
161 V(AuthDirListBadExits, BOOL, "0"),
162 V(AuthDirMaxServersPerAddr, UINT, "2"),
163 V(AuthDirMaxServersPerAuthAddr,UINT, "5"),
164 VAR("AuthoritativeDirectory", BOOL, AuthoritativeDir, "0"),
165 V(AutomapHostsOnResolve, BOOL, "0"),
166 V(AutomapHostsSuffixes, CSV, ".onion,.exit"),
167 V(AvoidDiskWrites, BOOL, "0"),
168 V(BandwidthBurst, MEMUNIT, "10 MB"),
169 V(BandwidthRate, MEMUNIT, "5 MB"),
170 V(BridgeAuthoritativeDir, BOOL, "0"),
171 VAR("Bridge", LINELIST, Bridges, NULL),
172 V(BridgePassword, STRING, NULL),
173 V(BridgeRecordUsageByCountry, BOOL, "1"),
174 V(BridgeRelay, BOOL, "0"),
175 V(CellStatistics, BOOL, "0"),
176 V(LearnCircuitBuildTimeout, BOOL, "1"),
177 V(CircuitBuildTimeout, INTERVAL, "0"),
178 V(CircuitIdleTimeout, INTERVAL, "1 hour"),
179 V(CircuitStreamTimeout, INTERVAL, "0"),
180 V(CircuitPriorityHalflife, DOUBLE, "-100.0"), /*negative:'Use default'*/
181 V(ClientDNSRejectInternalAddresses, BOOL,"1"),
182 V(ClientOnly, BOOL, "0"),
183 V(ConsensusParams, STRING, NULL),
184 V(ConnLimit, UINT, "1000"),
185 V(ConstrainedSockets, BOOL, "0"),
186 V(ConstrainedSockSize, MEMUNIT, "8192"),
187 V(ContactInfo, STRING, NULL),
188 V(ControlListenAddress, LINELIST, NULL),
189 V(ControlPort, UINT, "0"),
190 V(ControlSocket, LINELIST, NULL),
191 V(CookieAuthentication, BOOL, "0"),
192 V(CookieAuthFileGroupReadable, BOOL, "0"),
193 V(CookieAuthFile, STRING, NULL),
194 V(DataDirectory, FILENAME, NULL),
195 OBSOLETE("DebugLogFile"),
196 V(DirAllowPrivateAddresses, BOOL, NULL),
197 V(TestingAuthDirTimeToLearnReachability, INTERVAL, "30 minutes"),
198 V(DirListenAddress, LINELIST, NULL),
199 OBSOLETE("DirFetchPeriod"),
200 V(DirPolicy, LINELIST, NULL),
201 V(DirPort, UINT, "0"),
202 V(DirPortFrontPage, FILENAME, NULL),
203 OBSOLETE("DirPostPeriod"),
204 OBSOLETE("DirRecordUsageByCountry"),
205 OBSOLETE("DirRecordUsageGranularity"),
206 OBSOLETE("DirRecordUsageRetainIPs"),
207 OBSOLETE("DirRecordUsageSaveInterval"),
208 V(DirReqStatistics, BOOL, "0"),
209 VAR("DirServer", LINELIST, DirServers, NULL),
210 V(DisableAllSwap, BOOL, "0"),
211 V(DNSPort, UINT, "0"),
212 V(DNSListenAddress, LINELIST, NULL),
213 V(DownloadExtraInfo, BOOL, "0"),
214 V(EnforceDistinctSubnets, BOOL, "1"),
215 V(EntryNodes, ROUTERSET, NULL),
216 V(EntryStatistics, BOOL, "0"),
217 V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "10 minutes"),
218 V(ExcludeNodes, ROUTERSET, NULL),
219 V(ExcludeExitNodes, ROUTERSET, NULL),
220 V(ExcludeSingleHopRelays, BOOL, "1"),
221 V(ExitNodes, ROUTERSET, NULL),
222 V(ExitPolicy, LINELIST, NULL),
223 V(ExitPolicyRejectPrivate, BOOL, "1"),
224 V(ExitPortStatistics, BOOL, "0"),
225 V(ExtraInfoStatistics, BOOL, "0"),
227 #if defined (WINCE)
228 V(FallbackNetworkstatusFile, FILENAME, "fallback-consensus"),
229 #else
230 V(FallbackNetworkstatusFile, FILENAME,
231 SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "fallback-consensus"),
232 #endif
233 V(FascistFirewall, BOOL, "0"),
234 V(FirewallPorts, CSV, ""),
235 V(FastFirstHopPK, BOOL, "1"),
236 V(FetchDirInfoEarly, BOOL, "0"),
237 V(FetchDirInfoExtraEarly, BOOL, "0"),
238 V(FetchServerDescriptors, BOOL, "1"),
239 V(FetchHidServDescriptors, BOOL, "1"),
240 V(FetchUselessDescriptors, BOOL, "0"),
241 #ifdef WIN32
242 V(GeoIPFile, FILENAME, "<default>"),
243 #else
244 V(GeoIPFile, FILENAME,
245 SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip"),
246 #endif
247 OBSOLETE("Group"),
248 V(HardwareAccel, BOOL, "0"),
249 V(AccelName, STRING, NULL),
250 V(AccelDir, FILENAME, NULL),
251 V(HashedControlPassword, LINELIST, NULL),
252 V(HidServDirectoryV2, BOOL, "1"),
253 VAR("HiddenServiceDir", LINELIST_S, RendConfigLines, NULL),
254 OBSOLETE("HiddenServiceExcludeNodes"),
255 OBSOLETE("HiddenServiceNodes"),
256 VAR("HiddenServiceOptions",LINELIST_V, RendConfigLines, NULL),
257 VAR("HiddenServicePort", LINELIST_S, RendConfigLines, NULL),
258 VAR("HiddenServiceVersion",LINELIST_S, RendConfigLines, NULL),
259 VAR("HiddenServiceAuthorizeClient",LINELIST_S,RendConfigLines, NULL),
260 V(HidServAuth, LINELIST, NULL),
261 V(HSAuthoritativeDir, BOOL, "0"),
262 OBSOLETE("HSAuthorityRecordStats"),
263 V(HttpProxy, STRING, NULL),
264 V(HttpProxyAuthenticator, STRING, NULL),
265 V(HttpsProxy, STRING, NULL),
266 V(HttpsProxyAuthenticator, STRING, NULL),
267 V(Socks4Proxy, STRING, NULL),
268 V(Socks5Proxy, STRING, NULL),
269 V(Socks5ProxyUsername, STRING, NULL),
270 V(Socks5ProxyPassword, STRING, NULL),
271 OBSOLETE("IgnoreVersion"),
272 V(KeepalivePeriod, INTERVAL, "5 minutes"),
273 VAR("Log", LINELIST, Logs, NULL),
274 OBSOLETE("LinkPadding"),
275 OBSOLETE("LogLevel"),
276 OBSOLETE("LogFile"),
277 V(LongLivedPorts, CSV,
278 "21,22,706,1863,5050,5190,5222,5223,6667,6697,8300"),
279 VAR("MapAddress", LINELIST, AddressMap, NULL),
280 V(MaxAdvertisedBandwidth, MEMUNIT, "1 GB"),
281 V(MaxCircuitDirtiness, INTERVAL, "10 minutes"),
282 V(MaxOnionsPending, UINT, "100"),
283 OBSOLETE("MonthlyAccountingStart"),
284 V(MyFamily, STRING, NULL),
285 V(NewCircuitPeriod, INTERVAL, "30 seconds"),
286 VAR("NamingAuthoritativeDirectory",BOOL, NamingAuthoritativeDir, "0"),
287 V(NatdListenAddress, LINELIST, NULL),
288 V(NatdPort, UINT, "0"),
289 V(Nickname, STRING, NULL),
290 V(WarnUnsafeSocks, BOOL, "1"),
291 V(NoPublish, BOOL, "0"),
292 VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
293 V(NumCpus, UINT, "1"),
294 V(NumEntryGuards, UINT, "3"),
295 V(ORListenAddress, LINELIST, NULL),
296 V(ORPort, UINT, "0"),
297 V(OutboundBindAddress, STRING, NULL),
298 OBSOLETE("PathlenCoinWeight"),
299 V(PerConnBWBurst, MEMUNIT, "0"),
300 V(PerConnBWRate, MEMUNIT, "0"),
301 V(PidFile, STRING, NULL),
302 V(TestingTorNetwork, BOOL, "0"),
303 V(PreferTunneledDirConns, BOOL, "1"),
304 V(ProtocolWarnings, BOOL, "0"),
305 V(PublishServerDescriptor, CSV, "1"),
306 V(PublishHidServDescriptors, BOOL, "1"),
307 V(ReachableAddresses, LINELIST, NULL),
308 V(ReachableDirAddresses, LINELIST, NULL),
309 V(ReachableORAddresses, LINELIST, NULL),
310 V(RecommendedVersions, LINELIST, NULL),
311 V(RecommendedClientVersions, LINELIST, NULL),
312 V(RecommendedServerVersions, LINELIST, NULL),
313 OBSOLETE("RedirectExit"),
314 V(RefuseUnknownExits, BOOL, "0"),
315 V(RejectPlaintextPorts, CSV, ""),
316 V(RelayBandwidthBurst, MEMUNIT, "0"),
317 V(RelayBandwidthRate, MEMUNIT, "0"),
318 OBSOLETE("RendExcludeNodes"),
319 OBSOLETE("RendNodes"),
320 V(RendPostPeriod, INTERVAL, "1 hour"),
321 V(RephistTrackTime, INTERVAL, "24 hours"),
322 OBSOLETE("RouterFile"),
323 V(RunAsDaemon, BOOL, "0"),
324 V(RunTesting, BOOL, "0"),
325 V(SafeLogging, STRING, "1"),
326 V(SafeSocks, BOOL, "0"),
327 V(ServerDNSAllowBrokenConfig, BOOL, "1"),
328 V(ServerDNSAllowNonRFC953Hostnames, BOOL,"0"),
329 V(ServerDNSDetectHijacking, BOOL, "1"),
330 V(ServerDNSRandomizeCase, BOOL, "1"),
331 V(ServerDNSResolvConfFile, STRING, NULL),
332 V(ServerDNSSearchDomains, BOOL, "0"),
333 V(ServerDNSTestAddresses, CSV,
334 "www.google.com,www.mit.edu,www.yahoo.com,www.slashdot.org"),
335 V(ShutdownWaitLength, INTERVAL, "30 seconds"),
336 V(SocksListenAddress, LINELIST, NULL),
337 V(SocksPolicy, LINELIST, NULL),
338 V(SocksPort, UINT, "9050"),
339 V(SocksTimeout, INTERVAL, "2 minutes"),
340 OBSOLETE("StatusFetchPeriod"),
341 V(StrictNodes, BOOL, "0"),
342 OBSOLETE("SysLog"),
343 V(TestSocks, BOOL, "0"),
344 OBSOLETE("TestVia"),
345 V(TrackHostExits, CSV, NULL),
346 V(TrackHostExitsExpire, INTERVAL, "30 minutes"),
347 OBSOLETE("TrafficShaping"),
348 V(TransListenAddress, LINELIST, NULL),
349 V(TransPort, UINT, "0"),
350 V(TunnelDirConns, BOOL, "1"),
351 V(UpdateBridgesFromAuthority, BOOL, "0"),
352 V(UseBridges, BOOL, "0"),
353 V(UseEntryGuards, BOOL, "1"),
354 V(User, STRING, NULL),
355 VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"),
356 VAR("V2AuthoritativeDirectory",BOOL, V2AuthoritativeDir, "0"),
357 VAR("V3AuthoritativeDirectory",BOOL, V3AuthoritativeDir, "0"),
358 V(TestingV3AuthInitialVotingInterval, INTERVAL, "30 minutes"),
359 V(TestingV3AuthInitialVoteDelay, INTERVAL, "5 minutes"),
360 V(TestingV3AuthInitialDistDelay, INTERVAL, "5 minutes"),
361 V(V3AuthVotingInterval, INTERVAL, "1 hour"),
362 V(V3AuthVoteDelay, INTERVAL, "5 minutes"),
363 V(V3AuthDistDelay, INTERVAL, "5 minutes"),
364 V(V3AuthNIntervalsValid, UINT, "3"),
365 V(V3AuthUseLegacyKey, BOOL, "0"),
366 V(V3BandwidthsFile, FILENAME, NULL),
367 VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"),
368 V(VirtualAddrNetwork, STRING, "127.192.0.0/10"),
369 V(WarnPlaintextPorts, CSV, "23,109,110,143"),
370 VAR("__ReloadTorrcOnSIGHUP", BOOL, ReloadTorrcOnSIGHUP, "1"),
371 VAR("__AllDirActionsPrivate", BOOL, AllDirActionsPrivate, "0"),
372 VAR("__DisablePredictedCircuits",BOOL,DisablePredictedCircuits, "0"),
373 VAR("__LeaveStreamsUnattached",BOOL, LeaveStreamsUnattached, "0"),
374 VAR("__HashedControlSessionPassword", LINELIST, HashedControlSessionPassword,
375 NULL),
376 V(MinUptimeHidServDirectoryV2, INTERVAL, "24 hours"),
378 { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
381 /** Override default values with these if the user sets the TestingTorNetwork
382 * option. */
383 static config_var_t testing_tor_network_defaults[] = {
384 V(ServerDNSAllowBrokenConfig, BOOL, "1"),
385 V(DirAllowPrivateAddresses, BOOL, "1"),
386 V(EnforceDistinctSubnets, BOOL, "0"),
387 V(AssumeReachable, BOOL, "1"),
388 V(AuthDirMaxServersPerAddr, UINT, "0"),
389 V(AuthDirMaxServersPerAuthAddr,UINT, "0"),
390 V(ClientDNSRejectInternalAddresses, BOOL,"0"),
391 V(ExitPolicyRejectPrivate, BOOL, "0"),
392 V(V3AuthVotingInterval, INTERVAL, "5 minutes"),
393 V(V3AuthVoteDelay, INTERVAL, "20 seconds"),
394 V(V3AuthDistDelay, INTERVAL, "20 seconds"),
395 V(TestingV3AuthInitialVotingInterval, INTERVAL, "5 minutes"),
396 V(TestingV3AuthInitialVoteDelay, INTERVAL, "20 seconds"),
397 V(TestingV3AuthInitialDistDelay, INTERVAL, "20 seconds"),
398 V(TestingAuthDirTimeToLearnReachability, INTERVAL, "0 minutes"),
399 V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "0 minutes"),
400 { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
402 #undef VAR
404 #define VAR(name,conftype,member,initvalue) \
405 { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_state_t, member), \
406 initvalue }
408 /** Array of "state" variables saved to the ~/.tor/state file. */
409 static config_var_t _state_vars[] = {
410 V(AccountingBytesReadInInterval, MEMUNIT, NULL),
411 V(AccountingBytesWrittenInInterval, MEMUNIT, NULL),
412 V(AccountingExpectedUsage, MEMUNIT, NULL),
413 V(AccountingIntervalStart, ISOTIME, NULL),
414 V(AccountingSecondsActive, INTERVAL, NULL),
416 VAR("EntryGuard", LINELIST_S, EntryGuards, NULL),
417 VAR("EntryGuardDownSince", LINELIST_S, EntryGuards, NULL),
418 VAR("EntryGuardUnlistedSince", LINELIST_S, EntryGuards, NULL),
419 VAR("EntryGuardAddedBy", LINELIST_S, EntryGuards, NULL),
420 V(EntryGuards, LINELIST_V, NULL),
422 V(BWHistoryReadEnds, ISOTIME, NULL),
423 V(BWHistoryReadInterval, UINT, "900"),
424 V(BWHistoryReadValues, CSV, ""),
425 V(BWHistoryWriteEnds, ISOTIME, NULL),
426 V(BWHistoryWriteInterval, UINT, "900"),
427 V(BWHistoryWriteValues, CSV, ""),
429 V(TorVersion, STRING, NULL),
431 V(LastRotatedOnionKey, ISOTIME, NULL),
432 V(LastWritten, ISOTIME, NULL),
434 V(TotalBuildTimes, UINT, NULL),
435 V(CircuitBuildAbandonedCount, UINT, "0"),
436 VAR("CircuitBuildTimeBin", LINELIST_S, BuildtimeHistogram, NULL),
437 VAR("BuildtimeHistogram", LINELIST_V, BuildtimeHistogram, NULL),
439 { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
442 #undef VAR
443 #undef V
444 #undef OBSOLETE
446 /** Represents an English description of a configuration variable; used when
447 * generating configuration file comments. */
448 typedef struct config_var_description_t {
449 const char *name;
450 const char *description;
451 } config_var_description_t;
453 /** Type of a callback to validate whether a given configuration is
454 * well-formed and consistent. See options_trial_assign() for documentation
455 * of arguments. */
456 typedef int (*validate_fn_t)(void*,void*,int,char**);
458 /** Information on the keys, value types, key-to-struct-member mappings,
459 * variable descriptions, validation functions, and abbreviations for a
460 * configuration or storage format. */
461 typedef struct {
462 size_t size; /**< Size of the struct that everything gets parsed into. */
463 uint32_t magic; /**< Required 'magic value' to make sure we have a struct
464 * of the right type. */
465 off_t magic_offset; /**< Offset of the magic value within the struct. */
466 config_abbrev_t *abbrevs; /**< List of abbreviations that we expand when
467 * parsing this format. */
468 config_var_t *vars; /**< List of variables we recognize, their default
469 * values, and where we stick them in the structure. */
470 validate_fn_t validate_fn; /**< Function to validate config. */
471 /** If present, extra is a LINELIST variable for unrecognized
472 * lines. Otherwise, unrecognized lines are an error. */
473 config_var_t *extra;
474 } config_format_t;
476 /** Macro: assert that <b>cfg</b> has the right magic field for format
477 * <b>fmt</b>. */
478 #define CHECK(fmt, cfg) STMT_BEGIN \
479 tor_assert(fmt && cfg); \
480 tor_assert((fmt)->magic == \
481 *(uint32_t*)STRUCT_VAR_P(cfg,fmt->magic_offset)); \
482 STMT_END
484 #ifdef MS_WINDOWS
485 static char *get_windows_conf_root(void);
486 #endif
487 static void config_line_append(config_line_t **lst,
488 const char *key, const char *val);
489 static void option_clear(config_format_t *fmt, or_options_t *options,
490 config_var_t *var);
491 static void option_reset(config_format_t *fmt, or_options_t *options,
492 config_var_t *var, int use_defaults);
493 static void config_free(config_format_t *fmt, void *options);
494 static int config_lines_eq(config_line_t *a, config_line_t *b);
495 static int option_is_same(config_format_t *fmt,
496 or_options_t *o1, or_options_t *o2,
497 const char *name);
498 static or_options_t *options_dup(config_format_t *fmt, or_options_t *old);
499 static int options_validate(or_options_t *old_options, or_options_t *options,
500 int from_setconf, char **msg);
501 static int options_act_reversible(or_options_t *old_options, char **msg);
502 static int options_act(or_options_t *old_options);
503 static int options_transition_allowed(or_options_t *old, or_options_t *new,
504 char **msg);
505 static int options_transition_affects_workers(or_options_t *old_options,
506 or_options_t *new_options);
507 static int options_transition_affects_descriptor(or_options_t *old_options,
508 or_options_t *new_options);
509 static int check_nickname_list(const char *lst, const char *name, char **msg);
510 static void config_register_addressmaps(or_options_t *options);
512 static int parse_bridge_line(const char *line, int validate_only);
513 static int parse_dir_server_line(const char *line,
514 authority_type_t required_type,
515 int validate_only);
516 static int validate_data_directory(or_options_t *options);
517 static int write_configuration_file(const char *fname, or_options_t *options);
518 static config_line_t *get_assigned_option(config_format_t *fmt,
519 void *options, const char *key,
520 int escape_val);
521 static void config_init(config_format_t *fmt, void *options);
522 static int or_state_validate(or_state_t *old_options, or_state_t *options,
523 int from_setconf, char **msg);
524 static int or_state_load(void);
525 static int options_init_logs(or_options_t *options, int validate_only);
527 static int is_listening_on_low_port(uint16_t port_option,
528 const config_line_t *listen_options);
530 static uint64_t config_parse_memunit(const char *s, int *ok);
531 static int config_parse_interval(const char *s, int *ok);
532 static void init_libevent(void);
533 static int opt_streq(const char *s1, const char *s2);
535 /** Magic value for or_options_t. */
536 #define OR_OPTIONS_MAGIC 9090909
538 /** Configuration format for or_options_t. */
539 static config_format_t options_format = {
540 sizeof(or_options_t),
541 OR_OPTIONS_MAGIC,
542 STRUCT_OFFSET(or_options_t, _magic),
543 _option_abbrevs,
544 _option_vars,
545 (validate_fn_t)options_validate,
546 NULL
549 /** Magic value for or_state_t. */
550 #define OR_STATE_MAGIC 0x57A73f57
552 /** "Extra" variable in the state that receives lines we can't parse. This
553 * lets us preserve options from versions of Tor newer than us. */
554 static config_var_t state_extra_var = {
555 "__extra", CONFIG_TYPE_LINELIST, STRUCT_OFFSET(or_state_t, ExtraLines), NULL
558 /** Configuration format for or_state_t. */
559 static config_format_t state_format = {
560 sizeof(or_state_t),
561 OR_STATE_MAGIC,
562 STRUCT_OFFSET(or_state_t, _magic),
563 _state_abbrevs,
564 _state_vars,
565 (validate_fn_t)or_state_validate,
566 &state_extra_var,
570 * Functions to read and write the global options pointer.
573 /** Command-line and config-file options. */
574 static or_options_t *global_options = NULL;
575 /** Name of most recently read torrc file. */
576 static char *torrc_fname = NULL;
577 /** Persistent serialized state. */
578 static or_state_t *global_state = NULL;
579 /** Configuration Options set by command line. */
580 static config_line_t *global_cmdline_options = NULL;
581 /** Contents of most recently read DirPortFrontPage file. */
582 static char *global_dirfrontpagecontents = NULL;
584 /** Return the contents of our frontpage string, or NULL if not configured. */
585 const char *
586 get_dirportfrontpage(void)
588 return global_dirfrontpagecontents;
591 /** Allocate an empty configuration object of a given format type. */
592 static void *
593 config_alloc(config_format_t *fmt)
595 void *opts = tor_malloc_zero(fmt->size);
596 *(uint32_t*)STRUCT_VAR_P(opts, fmt->magic_offset) = fmt->magic;
597 CHECK(fmt, opts);
598 return opts;
601 /** Return the currently configured options. */
602 or_options_t *
603 get_options(void)
605 tor_assert(global_options);
606 return global_options;
609 /** Change the current global options to contain <b>new_val</b> instead of
610 * their current value; take action based on the new value; free the old value
611 * as necessary. Returns 0 on success, -1 on failure.
614 set_options(or_options_t *new_val, char **msg)
616 or_options_t *old_options = global_options;
617 global_options = new_val;
618 /* Note that we pass the *old* options below, for comparison. It
619 * pulls the new options directly out of global_options. */
620 if (options_act_reversible(old_options, msg)<0) {
621 tor_assert(*msg);
622 global_options = old_options;
623 return -1;
625 if (options_act(old_options) < 0) { /* acting on the options failed. die. */
626 log_err(LD_BUG,
627 "Acting on config options left us in a broken state. Dying.");
628 exit(1);
631 config_free(&options_format, old_options);
633 return 0;
636 extern const char tor_git_revision[]; /* from tor_main.c */
638 /** The version of this Tor process, as parsed. */
639 static char *_version = NULL;
641 /** Return the current Tor version. */
642 const char *
643 get_version(void)
645 if (_version == NULL) {
646 if (strlen(tor_git_revision)) {
647 size_t len = strlen(VERSION)+strlen(tor_git_revision)+16;
648 _version = tor_malloc(len);
649 tor_snprintf(_version, len, "%s (git-%s)", VERSION, tor_git_revision);
650 } else {
651 _version = tor_strdup(VERSION);
654 return _version;
657 /** Release additional memory allocated in options
659 static void
660 or_options_free(or_options_t *options)
662 if (!options)
663 return;
665 routerset_free(options->_ExcludeExitNodesUnion);
666 config_free(&options_format, options);
669 /** Release all memory and resources held by global configuration structures.
671 void
672 config_free_all(void)
674 or_options_free(global_options);
675 global_options = NULL;
677 config_free(&state_format, global_state);
678 global_state = NULL;
680 config_free_lines(global_cmdline_options);
681 global_cmdline_options = NULL;
683 tor_free(torrc_fname);
684 tor_free(_version);
685 tor_free(global_dirfrontpagecontents);
688 /** Make <b>address</b> -- a piece of information related to our operation as
689 * a client -- safe to log according to the settings in options->SafeLogging,
690 * and return it.
692 * (We return "[scrubbed]" if SafeLogging is "1", and address otherwise.)
694 const char *
695 safe_str_client(const char *address)
697 tor_assert(address);
698 if (get_options()->_SafeLogging == SAFELOG_SCRUB_ALL)
699 return "[scrubbed]";
700 else
701 return address;
704 /** Make <b>address</b> -- a piece of information of unspecified sensitivity
705 * -- safe to log according to the settings in options->SafeLogging, and
706 * return it.
708 * (We return "[scrubbed]" if SafeLogging is anything besides "0", and address
709 * otherwise.)
711 const char *
712 safe_str(const char *address)
714 tor_assert(address);
715 if (get_options()->_SafeLogging != SAFELOG_SCRUB_NONE)
716 return "[scrubbed]";
717 else
718 return address;
721 /** Equivalent to escaped(safe_str_client(address)). See reentrancy note on
722 * escaped(): don't use this outside the main thread, or twice in the same
723 * log statement. */
724 const char *
725 escaped_safe_str_client(const char *address)
727 if (get_options()->_SafeLogging == SAFELOG_SCRUB_ALL)
728 return "[scrubbed]";
729 else
730 return escaped(address);
733 /** Equivalent to escaped(safe_str(address)). See reentrancy note on
734 * escaped(): don't use this outside the main thread, or twice in the same
735 * log statement. */
736 const char *
737 escaped_safe_str(const char *address)
739 if (get_options()->_SafeLogging != SAFELOG_SCRUB_NONE)
740 return "[scrubbed]";
741 else
742 return escaped(address);
745 /** Add the default directory authorities directly into the trusted dir list,
746 * but only add them insofar as they share bits with <b>type</b>. */
747 static void
748 add_default_trusted_dir_authorities(authority_type_t type)
750 int i;
751 const char *dirservers[] = {
752 "moria1 orport=9101 no-v2 "
753 "v3ident=D586D18309DED4CD6D57C18FDB97EFA96D330566 "
754 "128.31.0.39:9131 9695 DFC3 5FFE B861 329B 9F1A B04C 4639 7020 CE31",
755 "tor26 v1 orport=443 v3ident=14C131DFC5C6F93646BE72FA1401C02A8DF2E8B4 "
756 "86.59.21.38:80 847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D",
757 "dizum orport=443 v3ident=E8A9C45EDE6D711294FADF8E7951F4DE6CA56B58 "
758 "194.109.206.212:80 7EA6 EAD6 FD83 083C 538F 4403 8BBF A077 587D D755",
759 "Tonga orport=443 bridge no-v2 82.94.251.203:80 "
760 "4A0C CD2D DC79 9508 3D73 F5D6 6710 0C8A 5831 F16D",
761 "ides orport=9090 no-v2 v3ident=27B6B5996C426270A5C95488AA5BCEB6BCC86956 "
762 "216.224.124.114:9030 F397 038A DC51 3361 35E7 B80B D99C A384 4360 292B",
763 "gabelmoo orport=8080 no-v2 "
764 "v3ident=ED03BB616EB2F60BEC80151114BB25CEF515B226 "
765 "80.190.246.100:8180 F204 4413 DAC2 E02E 3D6B CF47 35A1 9BCA 1DE9 7281",
766 "dannenberg orport=443 no-v2 "
767 "v3ident=585769C78764D58426B8B52B6651A5A71137189A "
768 "193.23.244.244:80 7BE6 83E6 5D48 1413 21C5 ED92 F075 C553 64AC 7123",
769 "urras orport=80 no-v2 v3ident=80550987E1D626E3EBA5E5E75A458DE0626D088C "
770 "208.83.223.34:443 0AD3 FA88 4D18 F89E EA2D 89C0 1937 9E0E 7FD9 4417",
771 "maatuska orport=80 no-v2 "
772 "v3ident=49015F787433103580E3B66A1707A00E60F2D15B "
773 "213.115.239.118:443 BD6A 8292 55CB 08E6 6FBE 7D37 4836 3586 E46B 3810",
774 NULL
776 for (i=0; dirservers[i]; i++) {
777 if (parse_dir_server_line(dirservers[i], type, 0)<0) {
778 log_err(LD_BUG, "Couldn't parse internal dirserver line %s",
779 dirservers[i]);
784 /** Look at all the config options for using alternate directory
785 * authorities, and make sure none of them are broken. Also, warn the
786 * user if we changed any dangerous ones.
788 static int
789 validate_dir_authorities(or_options_t *options, or_options_t *old_options)
791 config_line_t *cl;
793 if (options->DirServers &&
794 (options->AlternateDirAuthority || options->AlternateBridgeAuthority ||
795 options->AlternateHSAuthority)) {
796 log_warn(LD_CONFIG,
797 "You cannot set both DirServers and Alternate*Authority.");
798 return -1;
801 /* do we want to complain to the user about being partitionable? */
802 if ((options->DirServers &&
803 (!old_options ||
804 !config_lines_eq(options->DirServers, old_options->DirServers))) ||
805 (options->AlternateDirAuthority &&
806 (!old_options ||
807 !config_lines_eq(options->AlternateDirAuthority,
808 old_options->AlternateDirAuthority)))) {
809 log_warn(LD_CONFIG,
810 "You have used DirServer or AlternateDirAuthority to "
811 "specify alternate directory authorities in "
812 "your configuration. This is potentially dangerous: it can "
813 "make you look different from all other Tor users, and hurt "
814 "your anonymity. Even if you've specified the same "
815 "authorities as Tor uses by default, the defaults could "
816 "change in the future. Be sure you know what you're doing.");
819 /* Now go through the four ways you can configure an alternate
820 * set of directory authorities, and make sure none are broken. */
821 for (cl = options->DirServers; cl; cl = cl->next)
822 if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
823 return -1;
824 for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next)
825 if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
826 return -1;
827 for (cl = options->AlternateDirAuthority; cl; cl = cl->next)
828 if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
829 return -1;
830 for (cl = options->AlternateHSAuthority; cl; cl = cl->next)
831 if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
832 return -1;
833 return 0;
836 /** Look at all the config options and assign new dir authorities
837 * as appropriate.
839 static int
840 consider_adding_dir_authorities(or_options_t *options,
841 or_options_t *old_options)
843 config_line_t *cl;
844 int need_to_update =
845 !smartlist_len(router_get_trusted_dir_servers()) || !old_options ||
846 !config_lines_eq(options->DirServers, old_options->DirServers) ||
847 !config_lines_eq(options->AlternateBridgeAuthority,
848 old_options->AlternateBridgeAuthority) ||
849 !config_lines_eq(options->AlternateDirAuthority,
850 old_options->AlternateDirAuthority) ||
851 !config_lines_eq(options->AlternateHSAuthority,
852 old_options->AlternateHSAuthority);
854 if (!need_to_update)
855 return 0; /* all done */
857 /* Start from a clean slate. */
858 clear_trusted_dir_servers();
860 if (!options->DirServers) {
861 /* then we may want some of the defaults */
862 authority_type_t type = NO_AUTHORITY;
863 if (!options->AlternateBridgeAuthority)
864 type |= BRIDGE_AUTHORITY;
865 if (!options->AlternateDirAuthority)
866 type |= V1_AUTHORITY | V2_AUTHORITY | V3_AUTHORITY;
867 if (!options->AlternateHSAuthority)
868 type |= HIDSERV_AUTHORITY;
869 add_default_trusted_dir_authorities(type);
872 for (cl = options->DirServers; cl; cl = cl->next)
873 if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
874 return -1;
875 for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next)
876 if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
877 return -1;
878 for (cl = options->AlternateDirAuthority; cl; cl = cl->next)
879 if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
880 return -1;
881 for (cl = options->AlternateHSAuthority; cl; cl = cl->next)
882 if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
883 return -1;
884 return 0;
887 /** Fetch the active option list, and take actions based on it. All of the
888 * things we do should survive being done repeatedly. If present,
889 * <b>old_options</b> contains the previous value of the options.
891 * Return 0 if all goes well, return -1 if things went badly.
893 static int
894 options_act_reversible(or_options_t *old_options, char **msg)
896 smartlist_t *new_listeners = smartlist_create();
897 smartlist_t *replaced_listeners = smartlist_create();
898 static int libevent_initialized = 0;
899 or_options_t *options = get_options();
900 int running_tor = options->command == CMD_RUN_TOR;
901 int set_conn_limit = 0;
902 int r = -1;
903 int logs_marked = 0;
905 /* Daemonize _first_, since we only want to open most of this stuff in
906 * the subprocess. Libevent bases can't be reliably inherited across
907 * processes. */
908 if (running_tor && options->RunAsDaemon) {
909 /* No need to roll back, since you can't change the value. */
910 start_daemon();
913 #ifndef HAVE_SYS_UN_H
914 if (options->ControlSocket) {
915 *msg = tor_strdup("Unix domain sockets (ControlSocket) not supported"
916 " on this OS/with this build.");
917 goto rollback;
919 #endif
921 if (running_tor) {
922 /* We need to set the connection limit before we can open the listeners. */
923 if (set_max_file_descriptors((unsigned)options->ConnLimit,
924 &options->_ConnLimit) < 0) {
925 *msg = tor_strdup("Problem with ConnLimit value. See logs for details.");
926 goto rollback;
928 set_conn_limit = 1;
930 /* Set up libevent. (We need to do this before we can register the
931 * listeners as listeners.) */
932 if (running_tor && !libevent_initialized) {
933 init_libevent();
934 libevent_initialized = 1;
937 /* Launch the listeners. (We do this before we setuid, so we can bind to
938 * ports under 1024.) */
939 if (retry_all_listeners(replaced_listeners, new_listeners) < 0) {
940 *msg = tor_strdup("Failed to bind one of the listener ports.");
941 goto rollback;
945 #if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
946 /* Open /dev/pf before dropping privileges. */
947 if (options->TransPort) {
948 if (get_pf_socket() < 0) {
949 *msg = tor_strdup("Unable to open /dev/pf for transparent proxy.");
950 goto rollback;
953 #endif
955 /* Attempt to lock all current and future memory with mlockall() only once */
956 if (options->DisableAllSwap) {
957 if (tor_mlockall() == -1) {
958 *msg = tor_strdup("DisableAllSwap failure. Do you have proper "
959 "permissions?");
960 goto done;
964 /* Setuid/setgid as appropriate */
965 if (options->User) {
966 if (switch_id(options->User) != 0) {
967 /* No need to roll back, since you can't change the value. */
968 *msg = tor_strdup("Problem with User value. See logs for details.");
969 goto done;
973 /* Ensure data directory is private; create if possible. */
974 if (check_private_dir(options->DataDirectory,
975 running_tor ? CPD_CREATE : CPD_CHECK)<0) {
976 tor_asprintf(msg,
977 "Couldn't access/create private data directory \"%s\"",
978 options->DataDirectory);
979 goto done;
980 /* No need to roll back, since you can't change the value. */
983 if (directory_caches_v2_dir_info(options)) {
984 size_t len = strlen(options->DataDirectory)+32;
985 char *fn = tor_malloc(len);
986 tor_snprintf(fn, len, "%s"PATH_SEPARATOR"cached-status",
987 options->DataDirectory);
988 if (check_private_dir(fn, running_tor ? CPD_CREATE : CPD_CHECK) < 0) {
989 tor_asprintf(msg,
990 "Couldn't access/create private data directory \"%s\"", fn);
991 tor_free(fn);
992 goto done;
994 tor_free(fn);
997 /* Bail out at this point if we're not going to be a client or server:
998 * we don't run Tor itself. */
999 if (!running_tor)
1000 goto commit;
1002 mark_logs_temp(); /* Close current logs once new logs are open. */
1003 logs_marked = 1;
1004 if (options_init_logs(options, 0)<0) { /* Configure the log(s) */
1005 *msg = tor_strdup("Failed to init Log options. See logs for details.");
1006 goto rollback;
1009 commit:
1010 r = 0;
1011 if (logs_marked) {
1012 log_severity_list_t *severity =
1013 tor_malloc_zero(sizeof(log_severity_list_t));
1014 close_temp_logs();
1015 add_callback_log(severity, control_event_logmsg);
1016 control_adjust_event_log_severity();
1017 tor_free(severity);
1019 SMARTLIST_FOREACH(replaced_listeners, connection_t *, conn,
1021 log_notice(LD_NET, "Closing old %s on %s:%d",
1022 conn_type_to_string(conn->type), conn->address, conn->port);
1023 connection_close_immediate(conn);
1024 connection_mark_for_close(conn);
1026 goto done;
1028 rollback:
1029 r = -1;
1030 tor_assert(*msg);
1032 if (logs_marked) {
1033 rollback_log_changes();
1034 control_adjust_event_log_severity();
1037 if (set_conn_limit && old_options)
1038 set_max_file_descriptors((unsigned)old_options->ConnLimit,
1039 &options->_ConnLimit);
1041 SMARTLIST_FOREACH(new_listeners, connection_t *, conn,
1043 log_notice(LD_NET, "Closing partially-constructed listener %s on %s:%d",
1044 conn_type_to_string(conn->type), conn->address, conn->port);
1045 connection_close_immediate(conn);
1046 connection_mark_for_close(conn);
1049 done:
1050 smartlist_free(new_listeners);
1051 smartlist_free(replaced_listeners);
1052 return r;
1055 /** If we need to have a GEOIP ip-to-country map to run with our configured
1056 * options, return 1 and set *<b>reason_out</b> to a description of why. */
1058 options_need_geoip_info(or_options_t *options, const char **reason_out)
1060 int bridge_usage =
1061 options->BridgeRelay && options->BridgeRecordUsageByCountry;
1062 int routerset_usage =
1063 routerset_needs_geoip(options->EntryNodes) ||
1064 routerset_needs_geoip(options->ExitNodes) ||
1065 routerset_needs_geoip(options->ExcludeExitNodes) ||
1066 routerset_needs_geoip(options->ExcludeNodes);
1068 if (routerset_usage && reason_out) {
1069 *reason_out = "We've been configured to use (or avoid) nodes in certain "
1070 "countries, and we need GEOIP information to figure out which ones they "
1071 "are.";
1072 } else if (bridge_usage && reason_out) {
1073 *reason_out = "We've been configured to see which countries can access "
1074 "us as a bridge, and we need GEOIP information to tell which countries "
1075 "clients are in.";
1077 return bridge_usage || routerset_usage;
1080 /** Return the bandwidthrate that we are going to report to the authorities
1081 * based on the config options. */
1082 uint32_t
1083 get_effective_bwrate(or_options_t *options)
1085 uint64_t bw = options->BandwidthRate;
1086 if (bw > options->MaxAdvertisedBandwidth)
1087 bw = options->MaxAdvertisedBandwidth;
1088 if (options->RelayBandwidthRate > 0 && bw > options->RelayBandwidthRate)
1089 bw = options->RelayBandwidthRate;
1090 /* ensure_bandwidth_cap() makes sure that this cast can't overflow. */
1091 return (uint32_t)bw;
1094 /** Return the bandwidthburst that we are going to report to the authorities
1095 * based on the config options. */
1096 uint32_t
1097 get_effective_bwburst(or_options_t *options)
1099 uint64_t bw = options->BandwidthBurst;
1100 if (options->RelayBandwidthBurst > 0 && bw > options->RelayBandwidthBurst)
1101 bw = options->RelayBandwidthBurst;
1102 /* ensure_bandwidth_cap() makes sure that this cast can't overflow. */
1103 return (uint32_t)bw;
1106 /** Fetch the active option list, and take actions based on it. All of the
1107 * things we do should survive being done repeatedly. If present,
1108 * <b>old_options</b> contains the previous value of the options.
1110 * Return 0 if all goes well, return -1 if it's time to die.
1112 * Note: We haven't moved all the "act on new configuration" logic
1113 * here yet. Some is still in do_hup() and other places.
1115 static int
1116 options_act(or_options_t *old_options)
1118 config_line_t *cl;
1119 or_options_t *options = get_options();
1120 int running_tor = options->command == CMD_RUN_TOR;
1121 char *msg;
1123 if (running_tor && !have_lockfile()) {
1124 if (try_locking(options, 1) < 0)
1125 return -1;
1128 if (consider_adding_dir_authorities(options, old_options) < 0)
1129 return -1;
1131 if (options->Bridges) {
1132 clear_bridge_list();
1133 for (cl = options->Bridges; cl; cl = cl->next) {
1134 if (parse_bridge_line(cl->value, 0)<0) {
1135 log_warn(LD_BUG,
1136 "Previously validated Bridge line could not be added!");
1137 return -1;
1142 if (running_tor && rend_config_services(options, 0)<0) {
1143 log_warn(LD_BUG,
1144 "Previously validated hidden services line could not be added!");
1145 return -1;
1148 if (running_tor && rend_parse_service_authorization(options, 0) < 0) {
1149 log_warn(LD_BUG, "Previously validated client authorization for "
1150 "hidden services could not be added!");
1151 return -1;
1154 /* Load state */
1155 if (! global_state && running_tor) {
1156 if (or_state_load())
1157 return -1;
1158 rep_hist_load_mtbf_data(time(NULL));
1161 /* Bail out at this point if we're not going to be a client or server:
1162 * we want to not fork, and to log stuff to stderr. */
1163 if (!running_tor)
1164 return 0;
1166 /* Finish backgrounding the process */
1167 if (options->RunAsDaemon) {
1168 /* We may be calling this for the n'th time (on SIGHUP), but it's safe. */
1169 finish_daemon(options->DataDirectory);
1172 /* Write our PID to the PID file. If we do not have write permissions we
1173 * will log a warning */
1174 if (options->PidFile)
1175 write_pidfile(options->PidFile);
1177 /* Register addressmap directives */
1178 config_register_addressmaps(options);
1179 parse_virtual_addr_network(options->VirtualAddrNetwork, 0, &msg);
1181 /* Update address policies. */
1182 if (policies_parse_from_options(options) < 0) {
1183 /* This should be impossible, but let's be sure. */
1184 log_warn(LD_BUG,"Error parsing already-validated policy options.");
1185 return -1;
1188 if (init_cookie_authentication(options->CookieAuthentication) < 0) {
1189 log_warn(LD_CONFIG,"Error creating cookie authentication file.");
1190 return -1;
1193 /* reload keys as needed for rendezvous services. */
1194 if (rend_service_load_keys()<0) {
1195 log_warn(LD_GENERAL,"Error loading rendezvous service keys");
1196 return -1;
1199 /* Set up accounting */
1200 if (accounting_parse_options(options, 0)<0) {
1201 log_warn(LD_CONFIG,"Error in accounting options");
1202 return -1;
1204 if (accounting_is_enabled(options))
1205 configure_accounting(time(NULL));
1207 /* Change the cell EWMA settings */
1208 cell_ewma_set_scale_factor(options, networkstatus_get_latest_consensus());
1210 /* Check for transitions that need action. */
1211 if (old_options) {
1213 if ((options->UseEntryGuards && !old_options->UseEntryGuards) ||
1214 (options->ExcludeNodes &&
1215 !routerset_equal(old_options->ExcludeNodes,options->ExcludeNodes)) ||
1216 (options->ExcludeExitNodes &&
1217 !routerset_equal(old_options->ExcludeExitNodes,
1218 options->ExcludeExitNodes)) ||
1219 (options->EntryNodes &&
1220 !routerset_equal(old_options->EntryNodes, options->EntryNodes)) ||
1221 (options->ExitNodes &&
1222 !routerset_equal(old_options->ExitNodes, options->ExitNodes)) ||
1223 options->StrictNodes != old_options->StrictNodes) {
1224 log_info(LD_CIRC,
1225 "Changed to using entry guards, or changed preferred or "
1226 "excluded node lists. Abandoning previous circuits.");
1227 circuit_mark_all_unused_circs();
1228 circuit_expire_all_dirty_circs();
1231 if (! bool_eq(options->BridgeRelay, old_options->BridgeRelay)) {
1232 log_info(LD_GENERAL, "Bridge status changed. Forgetting GeoIP stats.");
1233 geoip_remove_old_clients(time(NULL)+(2*60*60));
1236 if (options_transition_affects_workers(old_options, options)) {
1237 log_info(LD_GENERAL,
1238 "Worker-related options changed. Rotating workers.");
1239 if (server_mode(options) && !server_mode(old_options)) {
1240 if (init_keys() < 0) {
1241 log_warn(LD_BUG,"Error initializing keys; exiting");
1242 return -1;
1244 ip_address_changed(0);
1245 if (has_completed_circuit || !any_predicted_circuits(time(NULL)))
1246 inform_testing_reachability();
1248 cpuworkers_rotate();
1249 if (dns_reset())
1250 return -1;
1251 } else {
1252 if (dns_reset())
1253 return -1;
1256 if (options->V3AuthoritativeDir && !old_options->V3AuthoritativeDir)
1257 init_keys();
1260 /* Maybe load geoip file */
1261 if (options->GeoIPFile &&
1262 ((!old_options || !opt_streq(old_options->GeoIPFile, options->GeoIPFile))
1263 || !geoip_is_loaded())) {
1264 /* XXXX Don't use this "<default>" junk; make our filename options
1265 * understand prefixes somehow. -NM */
1266 /* XXXX021 Reload GeoIPFile on SIGHUP. -NM */
1267 char *actual_fname = tor_strdup(options->GeoIPFile);
1268 #ifdef WIN32
1269 if (!strcmp(actual_fname, "<default>")) {
1270 const char *conf_root = get_windows_conf_root();
1271 size_t len = strlen(conf_root)+16;
1272 tor_free(actual_fname);
1273 actual_fname = tor_malloc(len+1);
1274 tor_snprintf(actual_fname, len, "%s\\geoip", conf_root);
1276 #endif
1277 geoip_load_file(actual_fname, options);
1278 tor_free(actual_fname);
1281 if (options->DirReqStatistics && !geoip_is_loaded()) {
1282 /* Check if GeoIP database could be loaded. */
1283 log_warn(LD_CONFIG, "Configured to measure directory request "
1284 "statistics, but no GeoIP database found!");
1285 return -1;
1288 if (options->EntryStatistics) {
1289 if (should_record_bridge_info(options)) {
1290 /* Don't allow measuring statistics on entry guards when configured
1291 * as bridge. */
1292 log_warn(LD_CONFIG, "Bridges cannot be configured to measure "
1293 "additional GeoIP statistics as entry guards.");
1294 return -1;
1295 } else if (!geoip_is_loaded()) {
1296 /* Check if GeoIP database could be loaded. */
1297 log_warn(LD_CONFIG, "Configured to measure entry node statistics, "
1298 "but no GeoIP database found!");
1299 return -1;
1303 /* Check if we need to parse and add the EntryNodes config option. */
1304 if (options->EntryNodes &&
1305 (!old_options ||
1306 (!routerset_equal(old_options->EntryNodes,options->EntryNodes))))
1307 entry_nodes_should_be_added();
1309 /* Since our options changed, we might need to regenerate and upload our
1310 * server descriptor.
1312 if (!old_options ||
1313 options_transition_affects_descriptor(old_options, options))
1314 mark_my_descriptor_dirty();
1316 /* We may need to reschedule some directory stuff if our status changed. */
1317 if (old_options) {
1318 if (authdir_mode_v3(options) && !authdir_mode_v3(old_options))
1319 dirvote_recalculate_timing(options, time(NULL));
1320 if (!bool_eq(directory_fetches_dir_info_early(options),
1321 directory_fetches_dir_info_early(old_options)) ||
1322 !bool_eq(directory_fetches_dir_info_later(options),
1323 directory_fetches_dir_info_later(old_options))) {
1324 /* Make sure update_router_have_min_dir_info gets called. */
1325 router_dir_info_changed();
1326 /* We might need to download a new consensus status later or sooner than
1327 * we had expected. */
1328 update_consensus_networkstatus_fetch_time(time(NULL));
1332 /* Load the webpage we're going to serve every time someone asks for '/' on
1333 our DirPort. */
1334 tor_free(global_dirfrontpagecontents);
1335 if (options->DirPortFrontPage) {
1336 global_dirfrontpagecontents =
1337 read_file_to_str(options->DirPortFrontPage, 0, NULL);
1338 if (!global_dirfrontpagecontents) {
1339 log_warn(LD_CONFIG,
1340 "DirPortFrontPage file '%s' not found. Continuing anyway.",
1341 options->DirPortFrontPage);
1345 return 0;
1349 * Functions to parse config options
1352 /** If <b>option</b> is an official abbreviation for a longer option,
1353 * return the longer option. Otherwise return <b>option</b>.
1354 * If <b>command_line</b> is set, apply all abbreviations. Otherwise, only
1355 * apply abbreviations that work for the config file and the command line.
1356 * If <b>warn_obsolete</b> is set, warn about deprecated names. */
1357 static const char *
1358 expand_abbrev(config_format_t *fmt, const char *option, int command_line,
1359 int warn_obsolete)
1361 int i;
1362 if (! fmt->abbrevs)
1363 return option;
1364 for (i=0; fmt->abbrevs[i].abbreviated; ++i) {
1365 /* Abbreviations are case insensitive. */
1366 if (!strcasecmp(option,fmt->abbrevs[i].abbreviated) &&
1367 (command_line || !fmt->abbrevs[i].commandline_only)) {
1368 if (warn_obsolete && fmt->abbrevs[i].warn) {
1369 log_warn(LD_CONFIG,
1370 "The configuration option '%s' is deprecated; "
1371 "use '%s' instead.",
1372 fmt->abbrevs[i].abbreviated,
1373 fmt->abbrevs[i].full);
1375 /* Keep going through the list in case we want to rewrite it more.
1376 * (We could imagine recursing here, but I don't want to get the
1377 * user into an infinite loop if we craft our list wrong.) */
1378 option = fmt->abbrevs[i].full;
1381 return option;
1384 /** Helper: Read a list of configuration options from the command line.
1385 * If successful, put them in *<b>result</b> and return 0, and return
1386 * -1 and leave *<b>result</b> alone. */
1387 static int
1388 config_get_commandlines(int argc, char **argv, config_line_t **result)
1390 config_line_t *front = NULL;
1391 config_line_t **new = &front;
1392 char *s;
1393 int i = 1;
1395 while (i < argc) {
1396 if (!strcmp(argv[i],"-f") ||
1397 !strcmp(argv[i],"--hash-password")) {
1398 i += 2; /* command-line option with argument. ignore them. */
1399 continue;
1400 } else if (!strcmp(argv[i],"--list-fingerprint") ||
1401 !strcmp(argv[i],"--verify-config") ||
1402 !strcmp(argv[i],"--ignore-missing-torrc") ||
1403 !strcmp(argv[i],"--quiet") ||
1404 !strcmp(argv[i],"--hush")) {
1405 i += 1; /* command-line option. ignore it. */
1406 continue;
1407 } else if (!strcmp(argv[i],"--nt-service") ||
1408 !strcmp(argv[i],"-nt-service")) {
1409 i += 1;
1410 continue;
1413 if (i == argc-1) {
1414 log_warn(LD_CONFIG,"Command-line option '%s' with no value. Failing.",
1415 argv[i]);
1416 config_free_lines(front);
1417 return -1;
1420 *new = tor_malloc_zero(sizeof(config_line_t));
1421 s = argv[i];
1423 /* Each keyword may be prefixed with one or two dashes. */
1424 if (*s == '-')
1425 s++;
1426 if (*s == '-')
1427 s++;
1429 (*new)->key = tor_strdup(expand_abbrev(&options_format, s, 1, 1));
1430 (*new)->value = tor_strdup(argv[i+1]);
1431 (*new)->next = NULL;
1432 log(LOG_DEBUG, LD_CONFIG, "command line: parsed keyword '%s', value '%s'",
1433 (*new)->key, (*new)->value);
1435 new = &((*new)->next);
1436 i += 2;
1438 *result = front;
1439 return 0;
1442 /** Helper: allocate a new configuration option mapping 'key' to 'val',
1443 * append it to *<b>lst</b>. */
1444 static void
1445 config_line_append(config_line_t **lst,
1446 const char *key,
1447 const char *val)
1449 config_line_t *newline;
1451 newline = tor_malloc(sizeof(config_line_t));
1452 newline->key = tor_strdup(key);
1453 newline->value = tor_strdup(val);
1454 newline->next = NULL;
1455 while (*lst)
1456 lst = &((*lst)->next);
1458 (*lst) = newline;
1461 /** Helper: parse the config string and strdup into key/value
1462 * strings. Set *result to the list, or NULL if parsing the string
1463 * failed. Return 0 on success, -1 on failure. Warn and ignore any
1464 * misformatted lines. */
1466 config_get_lines(const char *string, config_line_t **result)
1468 config_line_t *list = NULL, **next;
1469 char *k, *v;
1471 next = &list;
1472 do {
1473 k = v = NULL;
1474 string = parse_config_line_from_str(string, &k, &v);
1475 if (!string) {
1476 config_free_lines(list);
1477 tor_free(k);
1478 tor_free(v);
1479 return -1;
1481 if (k && v) {
1482 /* This list can get long, so we keep a pointer to the end of it
1483 * rather than using config_line_append over and over and getting
1484 * n^2 performance. */
1485 *next = tor_malloc(sizeof(config_line_t));
1486 (*next)->key = k;
1487 (*next)->value = v;
1488 (*next)->next = NULL;
1489 next = &((*next)->next);
1490 } else {
1491 tor_free(k);
1492 tor_free(v);
1494 } while (*string);
1496 *result = list;
1497 return 0;
1501 * Free all the configuration lines on the linked list <b>front</b>.
1503 void
1504 config_free_lines(config_line_t *front)
1506 config_line_t *tmp;
1508 while (front) {
1509 tmp = front;
1510 front = tmp->next;
1512 tor_free(tmp->key);
1513 tor_free(tmp->value);
1514 tor_free(tmp);
1518 /** If <b>key</b> is a configuration option, return the corresponding
1519 * config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation,
1520 * warn, and return the corresponding config_var_t. Otherwise return NULL.
1522 static config_var_t *
1523 config_find_option(config_format_t *fmt, const char *key)
1525 int i;
1526 size_t keylen = strlen(key);
1527 if (!keylen)
1528 return NULL; /* if they say "--" on the command line, it's not an option */
1529 /* First, check for an exact (case-insensitive) match */
1530 for (i=0; fmt->vars[i].name; ++i) {
1531 if (!strcasecmp(key, fmt->vars[i].name)) {
1532 return &fmt->vars[i];
1535 /* If none, check for an abbreviated match */
1536 for (i=0; fmt->vars[i].name; ++i) {
1537 if (!strncasecmp(key, fmt->vars[i].name, keylen)) {
1538 log_warn(LD_CONFIG, "The abbreviation '%s' is deprecated. "
1539 "Please use '%s' instead",
1540 key, fmt->vars[i].name);
1541 return &fmt->vars[i];
1544 /* Okay, unrecognized option */
1545 return NULL;
1549 * Functions to assign config options.
1552 /** <b>c</b>-\>key is known to be a real key. Update <b>options</b>
1553 * with <b>c</b>-\>value and return 0, or return -1 if bad value.
1555 * Called from config_assign_line() and option_reset().
1557 static int
1558 config_assign_value(config_format_t *fmt, or_options_t *options,
1559 config_line_t *c, char **msg)
1561 int i, ok;
1562 config_var_t *var;
1563 void *lvalue;
1565 CHECK(fmt, options);
1567 var = config_find_option(fmt, c->key);
1568 tor_assert(var);
1570 lvalue = STRUCT_VAR_P(options, var->var_offset);
1572 switch (var->type) {
1574 case CONFIG_TYPE_UINT:
1575 i = (int)tor_parse_long(c->value, 10, 0, INT_MAX, &ok, NULL);
1576 if (!ok) {
1577 tor_asprintf(msg,
1578 "Int keyword '%s %s' is malformed or out of bounds.",
1579 c->key, c->value);
1580 return -1;
1582 *(int *)lvalue = i;
1583 break;
1585 case CONFIG_TYPE_INTERVAL: {
1586 i = config_parse_interval(c->value, &ok);
1587 if (!ok) {
1588 tor_asprintf(msg,
1589 "Interval '%s %s' is malformed or out of bounds.",
1590 c->key, c->value);
1591 return -1;
1593 *(int *)lvalue = i;
1594 break;
1597 case CONFIG_TYPE_MEMUNIT: {
1598 uint64_t u64 = config_parse_memunit(c->value, &ok);
1599 if (!ok) {
1600 tor_asprintf(msg,
1601 "Value '%s %s' is malformed or out of bounds.",
1602 c->key, c->value);
1603 return -1;
1605 *(uint64_t *)lvalue = u64;
1606 break;
1609 case CONFIG_TYPE_BOOL:
1610 i = (int)tor_parse_long(c->value, 10, 0, 1, &ok, NULL);
1611 if (!ok) {
1612 tor_asprintf(msg,
1613 "Boolean '%s %s' expects 0 or 1.",
1614 c->key, c->value);
1615 return -1;
1617 *(int *)lvalue = i;
1618 break;
1620 case CONFIG_TYPE_STRING:
1621 case CONFIG_TYPE_FILENAME:
1622 tor_free(*(char **)lvalue);
1623 *(char **)lvalue = tor_strdup(c->value);
1624 break;
1626 case CONFIG_TYPE_DOUBLE:
1627 *(double *)lvalue = atof(c->value);
1628 break;
1630 case CONFIG_TYPE_ISOTIME:
1631 if (parse_iso_time(c->value, (time_t *)lvalue)) {
1632 tor_asprintf(msg,
1633 "Invalid time '%s' for keyword '%s'", c->value, c->key);
1634 return -1;
1636 break;
1638 case CONFIG_TYPE_ROUTERSET:
1639 if (*(routerset_t**)lvalue) {
1640 routerset_free(*(routerset_t**)lvalue);
1642 *(routerset_t**)lvalue = routerset_new();
1643 if (routerset_parse(*(routerset_t**)lvalue, c->value, c->key)<0) {
1644 tor_asprintf(msg, "Invalid exit list '%s' for option '%s'",
1645 c->value, c->key);
1646 return -1;
1648 break;
1650 case CONFIG_TYPE_CSV:
1651 if (*(smartlist_t**)lvalue) {
1652 SMARTLIST_FOREACH(*(smartlist_t**)lvalue, char *, cp, tor_free(cp));
1653 smartlist_clear(*(smartlist_t**)lvalue);
1654 } else {
1655 *(smartlist_t**)lvalue = smartlist_create();
1658 smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",",
1659 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
1660 break;
1662 case CONFIG_TYPE_LINELIST:
1663 case CONFIG_TYPE_LINELIST_S:
1664 config_line_append((config_line_t**)lvalue, c->key, c->value);
1665 break;
1666 case CONFIG_TYPE_OBSOLETE:
1667 log_warn(LD_CONFIG, "Skipping obsolete configuration option '%s'", c->key);
1668 break;
1669 case CONFIG_TYPE_LINELIST_V:
1670 tor_asprintf(msg,
1671 "You may not provide a value for virtual option '%s'", c->key);
1672 return -1;
1673 default:
1674 tor_assert(0);
1675 break;
1677 return 0;
1680 /** If <b>c</b> is a syntactically valid configuration line, update
1681 * <b>options</b> with its value and return 0. Otherwise return -1 for bad
1682 * key, -2 for bad value.
1684 * If <b>clear_first</b> is set, clear the value first. Then if
1685 * <b>use_defaults</b> is set, set the value to the default.
1687 * Called from config_assign().
1689 static int
1690 config_assign_line(config_format_t *fmt, or_options_t *options,
1691 config_line_t *c, int use_defaults,
1692 int clear_first, char **msg)
1694 config_var_t *var;
1696 CHECK(fmt, options);
1698 var = config_find_option(fmt, c->key);
1699 if (!var) {
1700 if (fmt->extra) {
1701 void *lvalue = STRUCT_VAR_P(options, fmt->extra->var_offset);
1702 log_info(LD_CONFIG,
1703 "Found unrecognized option '%s'; saving it.", c->key);
1704 config_line_append((config_line_t**)lvalue, c->key, c->value);
1705 return 0;
1706 } else {
1707 tor_asprintf(msg,
1708 "Unknown option '%s'. Failing.", c->key);
1709 return -1;
1712 /* Put keyword into canonical case. */
1713 if (strcmp(var->name, c->key)) {
1714 tor_free(c->key);
1715 c->key = tor_strdup(var->name);
1718 if (!strlen(c->value)) {
1719 /* reset or clear it, then return */
1720 if (!clear_first) {
1721 if (var->type == CONFIG_TYPE_LINELIST ||
1722 var->type == CONFIG_TYPE_LINELIST_S) {
1723 /* We got an empty linelist from the torrc or command line.
1724 As a special case, call this an error. Warn and ignore. */
1725 log_warn(LD_CONFIG,
1726 "Linelist option '%s' has no value. Skipping.", c->key);
1727 } else { /* not already cleared */
1728 option_reset(fmt, options, var, use_defaults);
1731 return 0;
1734 if (config_assign_value(fmt, options, c, msg) < 0)
1735 return -2;
1736 return 0;
1739 /** Restore the option named <b>key</b> in options to its default value.
1740 * Called from config_assign(). */
1741 static void
1742 config_reset_line(config_format_t *fmt, or_options_t *options,
1743 const char *key, int use_defaults)
1745 config_var_t *var;
1747 CHECK(fmt, options);
1749 var = config_find_option(fmt, key);
1750 if (!var)
1751 return; /* give error on next pass. */
1753 option_reset(fmt, options, var, use_defaults);
1756 /** Return true iff key is a valid configuration option. */
1758 option_is_recognized(const char *key)
1760 config_var_t *var = config_find_option(&options_format, key);
1761 return (var != NULL);
1764 /** Return the canonical name of a configuration option, or NULL
1765 * if no such option exists. */
1766 const char *
1767 option_get_canonical_name(const char *key)
1769 config_var_t *var = config_find_option(&options_format, key);
1770 return var ? var->name : NULL;
1773 /** Return a canonical list of the options assigned for key.
1775 config_line_t *
1776 option_get_assignment(or_options_t *options, const char *key)
1778 return get_assigned_option(&options_format, options, key, 1);
1781 /** Return true iff value needs to be quoted and escaped to be used in
1782 * a configuration file. */
1783 static int
1784 config_value_needs_escape(const char *value)
1786 if (*value == '\"')
1787 return 1;
1788 while (*value) {
1789 switch (*value)
1791 case '\r':
1792 case '\n':
1793 case '#':
1794 /* Note: quotes and backspaces need special handling when we are using
1795 * quotes, not otherwise, so they don't trigger escaping on their
1796 * own. */
1797 return 1;
1798 default:
1799 if (!TOR_ISPRINT(*value))
1800 return 1;
1802 ++value;
1804 return 0;
1807 /** Return a newly allocated deep copy of the lines in <b>inp</b>. */
1808 static config_line_t *
1809 config_lines_dup(const config_line_t *inp)
1811 config_line_t *result = NULL;
1812 config_line_t **next_out = &result;
1813 while (inp) {
1814 *next_out = tor_malloc(sizeof(config_line_t));
1815 (*next_out)->key = tor_strdup(inp->key);
1816 (*next_out)->value = tor_strdup(inp->value);
1817 inp = inp->next;
1818 next_out = &((*next_out)->next);
1820 (*next_out) = NULL;
1821 return result;
1824 /** Return newly allocated line or lines corresponding to <b>key</b> in the
1825 * configuration <b>options</b>. If <b>escape_val</b> is true and a
1826 * value needs to be quoted before it's put in a config file, quote and
1827 * escape that value. Return NULL if no such key exists. */
1828 static config_line_t *
1829 get_assigned_option(config_format_t *fmt, void *options,
1830 const char *key, int escape_val)
1832 config_var_t *var;
1833 const void *value;
1834 config_line_t *result;
1835 tor_assert(options && key);
1837 CHECK(fmt, options);
1839 var = config_find_option(fmt, key);
1840 if (!var) {
1841 log_warn(LD_CONFIG, "Unknown option '%s'. Failing.", key);
1842 return NULL;
1844 value = STRUCT_VAR_P(options, var->var_offset);
1846 result = tor_malloc_zero(sizeof(config_line_t));
1847 result->key = tor_strdup(var->name);
1848 switch (var->type)
1850 case CONFIG_TYPE_STRING:
1851 case CONFIG_TYPE_FILENAME:
1852 if (*(char**)value) {
1853 result->value = tor_strdup(*(char**)value);
1854 } else {
1855 tor_free(result->key);
1856 tor_free(result);
1857 return NULL;
1859 break;
1860 case CONFIG_TYPE_ISOTIME:
1861 if (*(time_t*)value) {
1862 result->value = tor_malloc(ISO_TIME_LEN+1);
1863 format_iso_time(result->value, *(time_t*)value);
1864 } else {
1865 tor_free(result->key);
1866 tor_free(result);
1868 escape_val = 0; /* Can't need escape. */
1869 break;
1870 case CONFIG_TYPE_INTERVAL:
1871 case CONFIG_TYPE_UINT:
1872 /* This means every or_options_t uint or bool element
1873 * needs to be an int. Not, say, a uint16_t or char. */
1874 tor_asprintf(&result->value, "%d", *(int*)value);
1875 escape_val = 0; /* Can't need escape. */
1876 break;
1877 case CONFIG_TYPE_MEMUNIT:
1878 tor_asprintf(&result->value, U64_FORMAT,
1879 U64_PRINTF_ARG(*(uint64_t*)value));
1880 escape_val = 0; /* Can't need escape. */
1881 break;
1882 case CONFIG_TYPE_DOUBLE:
1883 tor_asprintf(&result->value, "%f", *(double*)value);
1884 escape_val = 0; /* Can't need escape. */
1885 break;
1886 case CONFIG_TYPE_BOOL:
1887 result->value = tor_strdup(*(int*)value ? "1" : "0");
1888 escape_val = 0; /* Can't need escape. */
1889 break;
1890 case CONFIG_TYPE_ROUTERSET:
1891 result->value = routerset_to_string(*(routerset_t**)value);
1892 break;
1893 case CONFIG_TYPE_CSV:
1894 if (*(smartlist_t**)value)
1895 result->value =
1896 smartlist_join_strings(*(smartlist_t**)value, ",", 0, NULL);
1897 else
1898 result->value = tor_strdup("");
1899 break;
1900 case CONFIG_TYPE_OBSOLETE:
1901 log_fn(LOG_PROTOCOL_WARN, LD_CONFIG,
1902 "You asked me for the value of an obsolete config option '%s'.",
1903 key);
1904 tor_free(result->key);
1905 tor_free(result);
1906 return NULL;
1907 case CONFIG_TYPE_LINELIST_S:
1908 log_warn(LD_CONFIG,
1909 "Can't return context-sensitive '%s' on its own", key);
1910 tor_free(result->key);
1911 tor_free(result);
1912 return NULL;
1913 case CONFIG_TYPE_LINELIST:
1914 case CONFIG_TYPE_LINELIST_V:
1915 tor_free(result->key);
1916 tor_free(result);
1917 result = config_lines_dup(*(const config_line_t**)value);
1918 break;
1919 default:
1920 tor_free(result->key);
1921 tor_free(result);
1922 log_warn(LD_BUG,"Unknown type %d for known key '%s'",
1923 var->type, key);
1924 return NULL;
1927 if (escape_val) {
1928 config_line_t *line;
1929 for (line = result; line; line = line->next) {
1930 if (line->value && config_value_needs_escape(line->value)) {
1931 char *newval = esc_for_log(line->value);
1932 tor_free(line->value);
1933 line->value = newval;
1938 return result;
1941 /** Iterate through the linked list of requested options <b>list</b>.
1942 * For each item, convert as appropriate and assign to <b>options</b>.
1943 * If an item is unrecognized, set *msg and return -1 immediately,
1944 * else return 0 for success.
1946 * If <b>clear_first</b>, interpret config options as replacing (not
1947 * extending) their previous values. If <b>clear_first</b> is set,
1948 * then <b>use_defaults</b> to decide if you set to defaults after
1949 * clearing, or make the value 0 or NULL.
1951 * Here are the use cases:
1952 * 1. A non-empty AllowInvalid line in your torrc. Appends to current
1953 * if linelist, replaces current if csv.
1954 * 2. An empty AllowInvalid line in your torrc. Should clear it.
1955 * 3. "RESETCONF AllowInvalid" sets it to default.
1956 * 4. "SETCONF AllowInvalid" makes it NULL.
1957 * 5. "SETCONF AllowInvalid=foo" clears it and sets it to "foo".
1959 * Use_defaults Clear_first
1960 * 0 0 "append"
1961 * 1 0 undefined, don't use
1962 * 0 1 "set to null first"
1963 * 1 1 "set to defaults first"
1964 * Return 0 on success, -1 on bad key, -2 on bad value.
1966 * As an additional special case, if a LINELIST config option has
1967 * no value and clear_first is 0, then warn and ignore it.
1971 There are three call cases for config_assign() currently.
1973 Case one: Torrc entry
1974 options_init_from_torrc() calls config_assign(0, 0)
1975 calls config_assign_line(0, 0).
1976 if value is empty, calls option_reset(0) and returns.
1977 calls config_assign_value(), appends.
1979 Case two: setconf
1980 options_trial_assign() calls config_assign(0, 1)
1981 calls config_reset_line(0)
1982 calls option_reset(0)
1983 calls option_clear().
1984 calls config_assign_line(0, 1).
1985 if value is empty, returns.
1986 calls config_assign_value(), appends.
1988 Case three: resetconf
1989 options_trial_assign() calls config_assign(1, 1)
1990 calls config_reset_line(1)
1991 calls option_reset(1)
1992 calls option_clear().
1993 calls config_assign_value(default)
1994 calls config_assign_line(1, 1).
1995 returns.
1997 static int
1998 config_assign(config_format_t *fmt, void *options, config_line_t *list,
1999 int use_defaults, int clear_first, char **msg)
2001 config_line_t *p;
2003 CHECK(fmt, options);
2005 /* pass 1: normalize keys */
2006 for (p = list; p; p = p->next) {
2007 const char *full = expand_abbrev(fmt, p->key, 0, 1);
2008 if (strcmp(full,p->key)) {
2009 tor_free(p->key);
2010 p->key = tor_strdup(full);
2014 /* pass 2: if we're reading from a resetting source, clear all
2015 * mentioned config options, and maybe set to their defaults. */
2016 if (clear_first) {
2017 for (p = list; p; p = p->next)
2018 config_reset_line(fmt, options, p->key, use_defaults);
2021 /* pass 3: assign. */
2022 while (list) {
2023 int r;
2024 if ((r=config_assign_line(fmt, options, list, use_defaults,
2025 clear_first, msg)))
2026 return r;
2027 list = list->next;
2029 return 0;
2032 /** Try assigning <b>list</b> to the global options. You do this by duping
2033 * options, assigning list to the new one, then validating it. If it's
2034 * ok, then throw out the old one and stick with the new one. Else,
2035 * revert to old and return failure. Return SETOPT_OK on success, or
2036 * a setopt_err_t on failure.
2038 * If not success, point *<b>msg</b> to a newly allocated string describing
2039 * what went wrong.
2041 setopt_err_t
2042 options_trial_assign(config_line_t *list, int use_defaults,
2043 int clear_first, char **msg)
2045 int r;
2046 or_options_t *trial_options = options_dup(&options_format, get_options());
2048 if ((r=config_assign(&options_format, trial_options,
2049 list, use_defaults, clear_first, msg)) < 0) {
2050 config_free(&options_format, trial_options);
2051 return r;
2054 if (options_validate(get_options(), trial_options, 1, msg) < 0) {
2055 config_free(&options_format, trial_options);
2056 return SETOPT_ERR_PARSE; /*XXX make this a separate return value. */
2059 if (options_transition_allowed(get_options(), trial_options, msg) < 0) {
2060 config_free(&options_format, trial_options);
2061 return SETOPT_ERR_TRANSITION;
2064 if (set_options(trial_options, msg)<0) {
2065 config_free(&options_format, trial_options);
2066 return SETOPT_ERR_SETTING;
2069 /* we liked it. put it in place. */
2070 return SETOPT_OK;
2073 /** Reset config option <b>var</b> to 0, 0.0, NULL, or the equivalent.
2074 * Called from option_reset() and config_free(). */
2075 static void
2076 option_clear(config_format_t *fmt, or_options_t *options, config_var_t *var)
2078 void *lvalue = STRUCT_VAR_P(options, var->var_offset);
2079 (void)fmt; /* unused */
2080 switch (var->type) {
2081 case CONFIG_TYPE_STRING:
2082 case CONFIG_TYPE_FILENAME:
2083 tor_free(*(char**)lvalue);
2084 break;
2085 case CONFIG_TYPE_DOUBLE:
2086 *(double*)lvalue = 0.0;
2087 break;
2088 case CONFIG_TYPE_ISOTIME:
2089 *(time_t*)lvalue = 0;
2090 break;
2091 case CONFIG_TYPE_INTERVAL:
2092 case CONFIG_TYPE_UINT:
2093 case CONFIG_TYPE_BOOL:
2094 *(int*)lvalue = 0;
2095 break;
2096 case CONFIG_TYPE_MEMUNIT:
2097 *(uint64_t*)lvalue = 0;
2098 break;
2099 case CONFIG_TYPE_ROUTERSET:
2100 if (*(routerset_t**)lvalue) {
2101 routerset_free(*(routerset_t**)lvalue);
2102 *(routerset_t**)lvalue = NULL;
2104 break;
2105 case CONFIG_TYPE_CSV:
2106 if (*(smartlist_t**)lvalue) {
2107 SMARTLIST_FOREACH(*(smartlist_t **)lvalue, char *, cp, tor_free(cp));
2108 smartlist_free(*(smartlist_t **)lvalue);
2109 *(smartlist_t **)lvalue = NULL;
2111 break;
2112 case CONFIG_TYPE_LINELIST:
2113 case CONFIG_TYPE_LINELIST_S:
2114 config_free_lines(*(config_line_t **)lvalue);
2115 *(config_line_t **)lvalue = NULL;
2116 break;
2117 case CONFIG_TYPE_LINELIST_V:
2118 /* handled by linelist_s. */
2119 break;
2120 case CONFIG_TYPE_OBSOLETE:
2121 break;
2125 /** Clear the option indexed by <b>var</b> in <b>options</b>. Then if
2126 * <b>use_defaults</b>, set it to its default value.
2127 * Called by config_init() and option_reset_line() and option_assign_line(). */
2128 static void
2129 option_reset(config_format_t *fmt, or_options_t *options,
2130 config_var_t *var, int use_defaults)
2132 config_line_t *c;
2133 char *msg = NULL;
2134 CHECK(fmt, options);
2135 option_clear(fmt, options, var); /* clear it first */
2136 if (!use_defaults)
2137 return; /* all done */
2138 if (var->initvalue) {
2139 c = tor_malloc_zero(sizeof(config_line_t));
2140 c->key = tor_strdup(var->name);
2141 c->value = tor_strdup(var->initvalue);
2142 if (config_assign_value(fmt, options, c, &msg) < 0) {
2143 log_warn(LD_BUG, "Failed to assign default: %s", msg);
2144 tor_free(msg); /* if this happens it's a bug */
2146 config_free_lines(c);
2150 /** Print a usage message for tor. */
2151 static void
2152 print_usage(void)
2154 printf(
2155 "Copyright (c) 2001-2004, Roger Dingledine\n"
2156 "Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson\n"
2157 "Copyright (c) 2007-2010, The Tor Project, Inc.\n\n"
2158 "tor -f <torrc> [args]\n"
2159 "See man page for options, or https://www.torproject.org/ for "
2160 "documentation.\n");
2163 /** Print all non-obsolete torrc options. */
2164 static void
2165 list_torrc_options(void)
2167 int i;
2168 smartlist_t *lines = smartlist_create();
2169 for (i = 0; _option_vars[i].name; ++i) {
2170 config_var_t *var = &_option_vars[i];
2171 if (var->type == CONFIG_TYPE_OBSOLETE ||
2172 var->type == CONFIG_TYPE_LINELIST_V)
2173 continue;
2174 printf("%s\n", var->name);
2176 smartlist_free(lines);
2179 /** Last value actually set by resolve_my_address. */
2180 static uint32_t last_resolved_addr = 0;
2182 * Based on <b>options-\>Address</b>, guess our public IP address and put it
2183 * (in host order) into *<b>addr_out</b>. If <b>hostname_out</b> is provided,
2184 * set *<b>hostname_out</b> to a new string holding the hostname we used to
2185 * get the address. Return 0 if all is well, or -1 if we can't find a suitable
2186 * public IP address.
2189 resolve_my_address(int warn_severity, or_options_t *options,
2190 uint32_t *addr_out, char **hostname_out)
2192 struct in_addr in;
2193 uint32_t addr; /* host order */
2194 char hostname[256];
2195 int explicit_ip=1;
2196 int explicit_hostname=1;
2197 int from_interface=0;
2198 char tmpbuf[INET_NTOA_BUF_LEN];
2199 const char *address = options->Address;
2200 int notice_severity = warn_severity <= LOG_NOTICE ?
2201 LOG_NOTICE : warn_severity;
2203 tor_assert(addr_out);
2205 if (address && *address) {
2206 strlcpy(hostname, address, sizeof(hostname));
2207 } else { /* then we need to guess our address */
2208 explicit_ip = 0; /* it's implicit */
2209 explicit_hostname = 0; /* it's implicit */
2211 if (gethostname(hostname, sizeof(hostname)) < 0) {
2212 log_fn(warn_severity, LD_NET,"Error obtaining local hostname");
2213 return -1;
2215 log_debug(LD_CONFIG,"Guessed local host name as '%s'",hostname);
2218 /* now we know hostname. resolve it and keep only the IP address */
2220 if (tor_inet_aton(hostname, &in) == 0) {
2221 /* then we have to resolve it */
2222 explicit_ip = 0;
2223 if (tor_lookup_hostname(hostname, &addr)) { /* failed to resolve */
2224 uint32_t interface_ip; /* host order */
2226 if (explicit_hostname) {
2227 log_fn(warn_severity, LD_CONFIG,
2228 "Could not resolve local Address '%s'. Failing.", hostname);
2229 return -1;
2231 log_fn(notice_severity, LD_CONFIG,
2232 "Could not resolve guessed local hostname '%s'. "
2233 "Trying something else.", hostname);
2234 if (get_interface_address(warn_severity, &interface_ip)) {
2235 log_fn(warn_severity, LD_CONFIG,
2236 "Could not get local interface IP address. Failing.");
2237 return -1;
2239 from_interface = 1;
2240 in.s_addr = htonl(interface_ip);
2241 tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
2242 log_fn(notice_severity, LD_CONFIG, "Learned IP address '%s' for "
2243 "local interface. Using that.", tmpbuf);
2244 strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
2245 } else { /* resolved hostname into addr */
2246 in.s_addr = htonl(addr);
2248 if (!explicit_hostname &&
2249 is_internal_IP(ntohl(in.s_addr), 0)) {
2250 uint32_t interface_ip;
2252 tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
2253 log_fn(notice_severity, LD_CONFIG, "Guessed local hostname '%s' "
2254 "resolves to a private IP address (%s). Trying something "
2255 "else.", hostname, tmpbuf);
2257 if (get_interface_address(warn_severity, &interface_ip)) {
2258 log_fn(warn_severity, LD_CONFIG,
2259 "Could not get local interface IP address. Too bad.");
2260 } else if (is_internal_IP(interface_ip, 0)) {
2261 struct in_addr in2;
2262 in2.s_addr = htonl(interface_ip);
2263 tor_inet_ntoa(&in2,tmpbuf,sizeof(tmpbuf));
2264 log_fn(notice_severity, LD_CONFIG,
2265 "Interface IP address '%s' is a private address too. "
2266 "Ignoring.", tmpbuf);
2267 } else {
2268 from_interface = 1;
2269 in.s_addr = htonl(interface_ip);
2270 tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
2271 log_fn(notice_severity, LD_CONFIG,
2272 "Learned IP address '%s' for local interface."
2273 " Using that.", tmpbuf);
2274 strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
2280 tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
2281 if (is_internal_IP(ntohl(in.s_addr), 0) &&
2282 options->_PublishServerDescriptor) {
2283 /* make sure we're ok with publishing an internal IP */
2284 if (!options->DirServers && !options->AlternateDirAuthority) {
2285 /* if they are using the default dirservers, disallow internal IPs
2286 * always. */
2287 log_fn(warn_severity, LD_CONFIG,
2288 "Address '%s' resolves to private IP address '%s'. "
2289 "Tor servers that use the default DirServers must have public "
2290 "IP addresses.", hostname, tmpbuf);
2291 return -1;
2293 if (!explicit_ip) {
2294 /* even if they've set their own dirservers, require an explicit IP if
2295 * they're using an internal address. */
2296 log_fn(warn_severity, LD_CONFIG, "Address '%s' resolves to private "
2297 "IP address '%s'. Please set the Address config option to be "
2298 "the IP address you want to use.", hostname, tmpbuf);
2299 return -1;
2303 log_debug(LD_CONFIG, "Resolved Address to '%s'.", tmpbuf);
2304 *addr_out = ntohl(in.s_addr);
2305 if (last_resolved_addr && last_resolved_addr != *addr_out) {
2306 /* Leave this as a notice, regardless of the requested severity,
2307 * at least until dynamic IP address support becomes bulletproof. */
2308 log_notice(LD_NET,
2309 "Your IP address seems to have changed to %s. Updating.",
2310 tmpbuf);
2311 ip_address_changed(0);
2313 if (last_resolved_addr != *addr_out) {
2314 const char *method;
2315 const char *h = hostname;
2316 if (explicit_ip) {
2317 method = "CONFIGURED";
2318 h = NULL;
2319 } else if (explicit_hostname) {
2320 method = "RESOLVED";
2321 } else if (from_interface) {
2322 method = "INTERFACE";
2323 h = NULL;
2324 } else {
2325 method = "GETHOSTNAME";
2327 control_event_server_status(LOG_NOTICE,
2328 "EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s %s%s",
2329 tmpbuf, method, h?"HOSTNAME=":"", h);
2331 last_resolved_addr = *addr_out;
2332 if (hostname_out)
2333 *hostname_out = tor_strdup(hostname);
2334 return 0;
2337 /** Return true iff <b>addr</b> is judged to be on the same network as us, or
2338 * on a private network.
2341 is_local_addr(const tor_addr_t *addr)
2343 if (tor_addr_is_internal(addr, 0))
2344 return 1;
2345 /* Check whether ip is on the same /24 as we are. */
2346 if (get_options()->EnforceDistinctSubnets == 0)
2347 return 0;
2348 if (tor_addr_family(addr) == AF_INET) {
2349 /*XXXX022 IP6 what corresponds to an /24? */
2350 uint32_t ip = tor_addr_to_ipv4h(addr);
2352 /* It's possible that this next check will hit before the first time
2353 * resolve_my_address actually succeeds. (For clients, it is likely that
2354 * resolve_my_address will never be called at all). In those cases,
2355 * last_resolved_addr will be 0, and so checking to see whether ip is on
2356 * the same /24 as last_resolved_addr will be the same as checking whether
2357 * it was on net 0, which is already done by is_internal_IP.
2359 if ((last_resolved_addr & (uint32_t)0xffffff00ul)
2360 == (ip & (uint32_t)0xffffff00ul))
2361 return 1;
2363 return 0;
2366 /** Called when we don't have a nickname set. Try to guess a good nickname
2367 * based on the hostname, and return it in a newly allocated string. If we
2368 * can't, return NULL and let the caller warn if it wants to. */
2369 static char *
2370 get_default_nickname(void)
2372 static const char * const bad_default_nicknames[] = {
2373 "localhost",
2374 NULL,
2376 char localhostname[256];
2377 char *cp, *out, *outp;
2378 int i;
2380 if (gethostname(localhostname, sizeof(localhostname)) < 0)
2381 return NULL;
2383 /* Put it in lowercase; stop at the first dot. */
2384 if ((cp = strchr(localhostname, '.')))
2385 *cp = '\0';
2386 tor_strlower(localhostname);
2388 /* Strip invalid characters. */
2389 cp = localhostname;
2390 out = outp = tor_malloc(strlen(localhostname) + 1);
2391 while (*cp) {
2392 if (strchr(LEGAL_NICKNAME_CHARACTERS, *cp))
2393 *outp++ = *cp++;
2394 else
2395 cp++;
2397 *outp = '\0';
2399 /* Enforce length. */
2400 if (strlen(out) > MAX_NICKNAME_LEN)
2401 out[MAX_NICKNAME_LEN]='\0';
2403 /* Check for dumb names. */
2404 for (i = 0; bad_default_nicknames[i]; ++i) {
2405 if (!strcmp(out, bad_default_nicknames[i])) {
2406 tor_free(out);
2407 return NULL;
2411 return out;
2414 /** Release storage held by <b>options</b>. */
2415 static void
2416 config_free(config_format_t *fmt, void *options)
2418 int i;
2420 if (!options)
2421 return;
2423 tor_assert(fmt);
2425 for (i=0; fmt->vars[i].name; ++i)
2426 option_clear(fmt, options, &(fmt->vars[i]));
2427 if (fmt->extra) {
2428 config_line_t **linep = STRUCT_VAR_P(options, fmt->extra->var_offset);
2429 config_free_lines(*linep);
2430 *linep = NULL;
2432 tor_free(options);
2435 /** Return true iff a and b contain identical keys and values in identical
2436 * order. */
2437 static int
2438 config_lines_eq(config_line_t *a, config_line_t *b)
2440 while (a && b) {
2441 if (strcasecmp(a->key, b->key) || strcmp(a->value, b->value))
2442 return 0;
2443 a = a->next;
2444 b = b->next;
2446 if (a || b)
2447 return 0;
2448 return 1;
2451 /** Return true iff the option <b>name</b> has the same value in <b>o1</b>
2452 * and <b>o2</b>. Must not be called for LINELIST_S or OBSOLETE options.
2454 static int
2455 option_is_same(config_format_t *fmt,
2456 or_options_t *o1, or_options_t *o2, const char *name)
2458 config_line_t *c1, *c2;
2459 int r = 1;
2460 CHECK(fmt, o1);
2461 CHECK(fmt, o2);
2463 c1 = get_assigned_option(fmt, o1, name, 0);
2464 c2 = get_assigned_option(fmt, o2, name, 0);
2465 r = config_lines_eq(c1, c2);
2466 config_free_lines(c1);
2467 config_free_lines(c2);
2468 return r;
2471 /** Copy storage held by <b>old</b> into a new or_options_t and return it. */
2472 static or_options_t *
2473 options_dup(config_format_t *fmt, or_options_t *old)
2475 or_options_t *newopts;
2476 int i;
2477 config_line_t *line;
2479 newopts = config_alloc(fmt);
2480 for (i=0; fmt->vars[i].name; ++i) {
2481 if (fmt->vars[i].type == CONFIG_TYPE_LINELIST_S)
2482 continue;
2483 if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE)
2484 continue;
2485 line = get_assigned_option(fmt, old, fmt->vars[i].name, 0);
2486 if (line) {
2487 char *msg = NULL;
2488 if (config_assign(fmt, newopts, line, 0, 0, &msg) < 0) {
2489 log_err(LD_BUG, "Config_get_assigned_option() generated "
2490 "something we couldn't config_assign(): %s", msg);
2491 tor_free(msg);
2492 tor_assert(0);
2495 config_free_lines(line);
2497 return newopts;
2500 /** Return a new empty or_options_t. Used for testing. */
2501 or_options_t *
2502 options_new(void)
2504 return config_alloc(&options_format);
2507 /** Set <b>options</b> to hold reasonable defaults for most options.
2508 * Each option defaults to zero. */
2509 void
2510 options_init(or_options_t *options)
2512 config_init(&options_format, options);
2515 /* Check if the port number given in <b>port_option</b> in combination with
2516 * the specified port in <b>listen_options</b> will result in Tor actually
2517 * opening a low port (meaning a port lower than 1024). Return 1 if
2518 * it is, or 0 if it isn't or the concept of a low port isn't applicable for
2519 * the platform we're on. */
2520 static int
2521 is_listening_on_low_port(uint16_t port_option,
2522 const config_line_t *listen_options)
2524 #ifdef MS_WINDOWS
2525 (void) port_option;
2526 (void) listen_options;
2527 return 0; /* No port is too low for windows. */
2528 #else
2529 const config_line_t *l;
2530 uint16_t p;
2531 if (port_option == 0)
2532 return 0; /* We're not listening */
2533 if (listen_options == NULL)
2534 return (port_option < 1024);
2536 for (l = listen_options; l; l = l->next) {
2537 parse_addr_port(LOG_WARN, l->value, NULL, NULL, &p);
2538 if (p<1024) {
2539 return 1;
2542 return 0;
2543 #endif
2546 /** Set all vars in the configuration object <b>options</b> to their default
2547 * values. */
2548 static void
2549 config_init(config_format_t *fmt, void *options)
2551 int i;
2552 config_var_t *var;
2553 CHECK(fmt, options);
2555 for (i=0; fmt->vars[i].name; ++i) {
2556 var = &fmt->vars[i];
2557 if (!var->initvalue)
2558 continue; /* defaults to NULL or 0 */
2559 option_reset(fmt, options, var, 1);
2563 /** Allocate and return a new string holding the written-out values of the vars
2564 * in 'options'. If 'minimal', do not write out any default-valued vars.
2565 * Else, if comment_defaults, write default values as comments.
2567 static char *
2568 config_dump(config_format_t *fmt, void *options, int minimal,
2569 int comment_defaults)
2571 smartlist_t *elements;
2572 or_options_t *defaults;
2573 config_line_t *line, *assigned;
2574 char *result;
2575 int i;
2576 char *msg = NULL;
2578 defaults = config_alloc(fmt);
2579 config_init(fmt, defaults);
2581 /* XXX use a 1 here so we don't add a new log line while dumping */
2582 if (fmt->validate_fn(NULL,defaults, 1, &msg) < 0) {
2583 log_err(LD_BUG, "Failed to validate default config.");
2584 tor_free(msg);
2585 tor_assert(0);
2588 elements = smartlist_create();
2589 for (i=0; fmt->vars[i].name; ++i) {
2590 int comment_option = 0;
2591 if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE ||
2592 fmt->vars[i].type == CONFIG_TYPE_LINELIST_S)
2593 continue;
2594 /* Don't save 'hidden' control variables. */
2595 if (!strcmpstart(fmt->vars[i].name, "__"))
2596 continue;
2597 if (minimal && option_is_same(fmt, options, defaults, fmt->vars[i].name))
2598 continue;
2599 else if (comment_defaults &&
2600 option_is_same(fmt, options, defaults, fmt->vars[i].name))
2601 comment_option = 1;
2603 line = assigned = get_assigned_option(fmt, options, fmt->vars[i].name, 1);
2605 for (; line; line = line->next) {
2606 char *tmp;
2607 tor_asprintf(&tmp, "%s%s %s\n",
2608 comment_option ? "# " : "",
2609 line->key, line->value);
2610 smartlist_add(elements, tmp);
2612 config_free_lines(assigned);
2615 if (fmt->extra) {
2616 line = *(config_line_t**)STRUCT_VAR_P(options, fmt->extra->var_offset);
2617 for (; line; line = line->next) {
2618 char *tmp;
2619 tor_asprintf(&tmp, "%s %s\n", line->key, line->value);
2620 smartlist_add(elements, tmp);
2624 result = smartlist_join_strings(elements, "", 0, NULL);
2625 SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
2626 smartlist_free(elements);
2627 config_free(fmt, defaults);
2628 return result;
2631 /** Return a string containing a possible configuration file that would give
2632 * the configuration in <b>options</b>. If <b>minimal</b> is true, do not
2633 * include options that are the same as Tor's defaults.
2635 char *
2636 options_dump(or_options_t *options, int minimal)
2638 return config_dump(&options_format, options, minimal, 0);
2641 /** Return 0 if every element of sl is a string holding a decimal
2642 * representation of a port number, or if sl is NULL.
2643 * Otherwise set *msg and return -1. */
2644 static int
2645 validate_ports_csv(smartlist_t *sl, const char *name, char **msg)
2647 int i;
2648 tor_assert(name);
2650 if (!sl)
2651 return 0;
2653 SMARTLIST_FOREACH(sl, const char *, cp,
2655 i = atoi(cp);
2656 if (i < 1 || i > 65535) {
2657 tor_asprintf(msg, "Port '%s' out of range in %s", cp, name);
2658 return -1;
2661 return 0;
2664 /** If <b>value</b> exceeds ROUTER_MAX_DECLARED_BANDWIDTH, write
2665 * a complaint into *<b>msg</b> using string <b>desc</b>, and return -1.
2666 * Else return 0.
2668 static int
2669 ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg)
2671 if (*value > ROUTER_MAX_DECLARED_BANDWIDTH) {
2672 /* This handles an understandable special case where somebody says "2gb"
2673 * whereas our actual maximum is 2gb-1 (INT_MAX) */
2674 --*value;
2676 if (*value > ROUTER_MAX_DECLARED_BANDWIDTH) {
2677 tor_asprintf(msg, "%s ("U64_FORMAT") must be at most %d",
2678 desc, U64_PRINTF_ARG(*value),
2679 ROUTER_MAX_DECLARED_BANDWIDTH);
2680 return -1;
2682 return 0;
2685 /** Parse an authority type from <b>options</b>-\>PublishServerDescriptor
2686 * and write it to <b>options</b>-\>_PublishServerDescriptor. Treat "1"
2687 * as "v2,v3" unless BridgeRelay is 1, in which case treat it as "bridge".
2688 * Treat "0" as "".
2689 * Return 0 on success or -1 if not a recognized authority type (in which
2690 * case the value of _PublishServerDescriptor is undefined). */
2691 static int
2692 compute_publishserverdescriptor(or_options_t *options)
2694 smartlist_t *list = options->PublishServerDescriptor;
2695 authority_type_t *auth = &options->_PublishServerDescriptor;
2696 *auth = NO_AUTHORITY;
2697 if (!list) /* empty list, answer is none */
2698 return 0;
2699 SMARTLIST_FOREACH(list, const char *, string, {
2700 if (!strcasecmp(string, "v1"))
2701 *auth |= V1_AUTHORITY;
2702 else if (!strcmp(string, "1"))
2703 if (options->BridgeRelay)
2704 *auth |= BRIDGE_AUTHORITY;
2705 else
2706 *auth |= V2_AUTHORITY | V3_AUTHORITY;
2707 else if (!strcasecmp(string, "v2"))
2708 *auth |= V2_AUTHORITY;
2709 else if (!strcasecmp(string, "v3"))
2710 *auth |= V3_AUTHORITY;
2711 else if (!strcasecmp(string, "bridge"))
2712 *auth |= BRIDGE_AUTHORITY;
2713 else if (!strcasecmp(string, "hidserv"))
2714 *auth |= HIDSERV_AUTHORITY;
2715 else if (!strcasecmp(string, "") || !strcmp(string, "0"))
2716 /* no authority */;
2717 else
2718 return -1;
2720 return 0;
2723 /** Lowest allowable value for RendPostPeriod; if this is too low, hidden
2724 * services can overload the directory system. */
2725 #define MIN_REND_POST_PERIOD (10*60)
2727 /** Highest allowable value for RendPostPeriod. */
2728 #define MAX_DIR_PERIOD (MIN_ONION_KEY_LIFETIME/2)
2730 /** Lowest allowable value for MaxCircuitDirtiness; if this is too low, Tor
2731 * will generate too many circuits and potentially overload the network. */
2732 #define MIN_MAX_CIRCUIT_DIRTINESS 10
2734 /** Lowest allowable value for CircuitStreamTimeout; if this is too low, Tor
2735 * will generate too many circuits and potentially overload the network. */
2736 #define MIN_CIRCUIT_STREAM_TIMEOUT 10
2738 /** Return 0 if every setting in <b>options</b> is reasonable, and a
2739 * permissible transition from <b>old_options</b>. Else return -1.
2740 * Should have no side effects, except for normalizing the contents of
2741 * <b>options</b>.
2743 * On error, tor_strdup an error explanation into *<b>msg</b>.
2745 * XXX
2746 * If <b>from_setconf</b>, we were called by the controller, and our
2747 * Log line should stay empty. If it's 0, then give us a default log
2748 * if there are no logs defined.
2750 static int
2751 options_validate(or_options_t *old_options, or_options_t *options,
2752 int from_setconf, char **msg)
2754 int i;
2755 config_line_t *cl;
2756 const char *uname = get_uname();
2757 #define REJECT(arg) \
2758 STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
2759 #define COMPLAIN(arg) STMT_BEGIN log(LOG_WARN, LD_CONFIG, arg); STMT_END
2761 tor_assert(msg);
2762 *msg = NULL;
2764 if (options->ORPort < 0 || options->ORPort > 65535)
2765 REJECT("ORPort option out of bounds.");
2767 if (server_mode(options) &&
2768 (!strcmpstart(uname, "Windows 95") ||
2769 !strcmpstart(uname, "Windows 98") ||
2770 !strcmpstart(uname, "Windows Me"))) {
2771 log(LOG_WARN, LD_CONFIG, "Tor is running as a server, but you are "
2772 "running %s; this probably won't work. See "
2773 "https://wiki.torproject.org/TheOnionRouter/TorFAQ#ServerOS "
2774 "for details.", uname);
2777 if (options->ORPort == 0 && options->ORListenAddress != NULL)
2778 REJECT("ORPort must be defined if ORListenAddress is defined.");
2780 if (options->DirPort == 0 && options->DirListenAddress != NULL)
2781 REJECT("DirPort must be defined if DirListenAddress is defined.");
2783 if (options->DNSPort == 0 && options->DNSListenAddress != NULL)
2784 REJECT("DNSPort must be defined if DNSListenAddress is defined.");
2786 if (options->ControlPort == 0 && options->ControlListenAddress != NULL)
2787 REJECT("ControlPort must be defined if ControlListenAddress is defined.");
2789 if (options->TransPort == 0 && options->TransListenAddress != NULL)
2790 REJECT("TransPort must be defined if TransListenAddress is defined.");
2792 if (options->NatdPort == 0 && options->NatdListenAddress != NULL)
2793 REJECT("NatdPort must be defined if NatdListenAddress is defined.");
2795 /* Don't gripe about SocksPort 0 with SocksListenAddress set; a standard
2796 * configuration does this. */
2798 for (i = 0; i < 3; ++i) {
2799 int is_socks = i==0;
2800 int is_trans = i==1;
2801 config_line_t *line, *opt, *old;
2802 const char *tp;
2803 if (is_socks) {
2804 opt = options->SocksListenAddress;
2805 old = old_options ? old_options->SocksListenAddress : NULL;
2806 tp = "SOCKS proxy";
2807 } else if (is_trans) {
2808 opt = options->TransListenAddress;
2809 old = old_options ? old_options->TransListenAddress : NULL;
2810 tp = "transparent proxy";
2811 } else {
2812 opt = options->NatdListenAddress;
2813 old = old_options ? old_options->NatdListenAddress : NULL;
2814 tp = "natd proxy";
2817 for (line = opt; line; line = line->next) {
2818 char *address = NULL;
2819 uint16_t port;
2820 uint32_t addr;
2821 if (parse_addr_port(LOG_WARN, line->value, &address, &addr, &port)<0)
2822 continue; /* We'll warn about this later. */
2823 if (!is_internal_IP(addr, 1) &&
2824 (!old_options || !config_lines_eq(old, opt))) {
2825 log_warn(LD_CONFIG,
2826 "You specified a public address '%s' for a %s. Other "
2827 "people on the Internet might find your computer and use it as "
2828 "an open %s. Please don't allow this unless you have "
2829 "a good reason.", address, tp, tp);
2831 tor_free(address);
2835 if (validate_data_directory(options)<0)
2836 REJECT("Invalid DataDirectory");
2838 if (options->Nickname == NULL) {
2839 if (server_mode(options)) {
2840 if (!(options->Nickname = get_default_nickname())) {
2841 log_notice(LD_CONFIG, "Couldn't pick a nickname based on "
2842 "our hostname; using %s instead.", UNNAMED_ROUTER_NICKNAME);
2843 options->Nickname = tor_strdup(UNNAMED_ROUTER_NICKNAME);
2844 } else {
2845 log_notice(LD_CONFIG, "Choosing default nickname '%s'",
2846 options->Nickname);
2849 } else {
2850 if (!is_legal_nickname(options->Nickname)) {
2851 tor_asprintf(msg,
2852 "Nickname '%s' is wrong length or contains illegal characters.",
2853 options->Nickname);
2854 return -1;
2858 if (server_mode(options) && !options->ContactInfo)
2859 log(LOG_NOTICE, LD_CONFIG, "Your ContactInfo config option is not set. "
2860 "Please consider setting it, so we can contact you if your server is "
2861 "misconfigured or something else goes wrong.");
2863 /* Special case on first boot if no Log options are given. */
2864 if (!options->Logs && !options->RunAsDaemon && !from_setconf)
2865 config_line_append(&options->Logs, "Log", "notice stdout");
2867 if (options_init_logs(options, 1)<0) /* Validate the log(s) */
2868 REJECT("Failed to validate Log options. See logs for details.");
2870 if (options->NoPublish) {
2871 log(LOG_WARN, LD_CONFIG,
2872 "NoPublish is obsolete. Use PublishServerDescriptor instead.");
2873 SMARTLIST_FOREACH(options->PublishServerDescriptor, char *, s,
2874 tor_free(s));
2875 smartlist_clear(options->PublishServerDescriptor);
2878 if (authdir_mode(options)) {
2879 /* confirm that our address isn't broken, so we can complain now */
2880 uint32_t tmp;
2881 if (resolve_my_address(LOG_WARN, options, &tmp, NULL) < 0)
2882 REJECT("Failed to resolve/guess local address. See logs for details.");
2885 #ifndef MS_WINDOWS
2886 if (options->RunAsDaemon && torrc_fname && path_is_relative(torrc_fname))
2887 REJECT("Can't use a relative path to torrc when RunAsDaemon is set.");
2888 #endif
2890 if (options->SocksPort < 0 || options->SocksPort > 65535)
2891 REJECT("SocksPort option out of bounds.");
2893 if (options->DNSPort < 0 || options->DNSPort > 65535)
2894 REJECT("DNSPort option out of bounds.");
2896 if (options->TransPort < 0 || options->TransPort > 65535)
2897 REJECT("TransPort option out of bounds.");
2899 if (options->NatdPort < 0 || options->NatdPort > 65535)
2900 REJECT("NatdPort option out of bounds.");
2902 if (options->SocksPort == 0 && options->TransPort == 0 &&
2903 options->NatdPort == 0 && options->ORPort == 0 &&
2904 options->DNSPort == 0 && !options->RendConfigLines)
2905 log(LOG_WARN, LD_CONFIG,
2906 "SocksPort, TransPort, NatdPort, DNSPort, and ORPort are all "
2907 "undefined, and there aren't any hidden services configured. "
2908 "Tor will still run, but probably won't do anything.");
2910 if (options->ControlPort < 0 || options->ControlPort > 65535)
2911 REJECT("ControlPort option out of bounds.");
2913 if (options->DirPort < 0 || options->DirPort > 65535)
2914 REJECT("DirPort option out of bounds.");
2916 #ifndef USE_TRANSPARENT
2917 if (options->TransPort || options->TransListenAddress)
2918 REJECT("TransPort and TransListenAddress are disabled in this build.");
2919 #endif
2921 if (options->AccountingMax &&
2922 (is_listening_on_low_port(options->ORPort, options->ORListenAddress) ||
2923 is_listening_on_low_port(options->DirPort, options->DirListenAddress)))
2925 log(LOG_WARN, LD_CONFIG,
2926 "You have set AccountingMax to use hibernation. You have also "
2927 "chosen a low DirPort or OrPort. This combination can make Tor stop "
2928 "working when it tries to re-attach the port after a period of "
2929 "hibernation. Please choose a different port or turn off "
2930 "hibernation unless you know this combination will work on your "
2931 "platform.");
2934 if (options->ExcludeExitNodes || options->ExcludeNodes) {
2935 options->_ExcludeExitNodesUnion = routerset_new();
2936 routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeExitNodes);
2937 routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeNodes);
2940 if (options->ExcludeNodes && options->StrictNodes) {
2941 COMPLAIN("You have asked to exclude certain relays from all positions "
2942 "in your circuits. Expect hidden services and other Tor "
2943 "features to be broken in unpredictable ways.");
2946 if (options->EntryNodes && !routerset_is_list(options->EntryNodes)) {
2947 /* XXXX fix this; see entry_guards_prepend_from_config(). */
2948 REJECT("IPs or countries are not yet supported in EntryNodes.");
2951 if (options->AuthoritativeDir) {
2952 if (!options->ContactInfo && !options->TestingTorNetwork)
2953 REJECT("Authoritative directory servers must set ContactInfo");
2954 if (options->V1AuthoritativeDir && !options->RecommendedVersions)
2955 REJECT("V1 authoritative dir servers must set RecommendedVersions.");
2956 if (!options->RecommendedClientVersions)
2957 options->RecommendedClientVersions =
2958 config_lines_dup(options->RecommendedVersions);
2959 if (!options->RecommendedServerVersions)
2960 options->RecommendedServerVersions =
2961 config_lines_dup(options->RecommendedVersions);
2962 if (options->VersioningAuthoritativeDir &&
2963 (!options->RecommendedClientVersions ||
2964 !options->RecommendedServerVersions))
2965 REJECT("Versioning authoritative dir servers must set "
2966 "Recommended*Versions.");
2967 if (options->UseEntryGuards) {
2968 log_info(LD_CONFIG, "Authoritative directory servers can't set "
2969 "UseEntryGuards. Disabling.");
2970 options->UseEntryGuards = 0;
2972 if (!options->DownloadExtraInfo && authdir_mode_any_main(options)) {
2973 log_info(LD_CONFIG, "Authoritative directories always try to download "
2974 "extra-info documents. Setting DownloadExtraInfo.");
2975 options->DownloadExtraInfo = 1;
2977 if (!(options->BridgeAuthoritativeDir || options->HSAuthoritativeDir ||
2978 options->V1AuthoritativeDir || options->V2AuthoritativeDir ||
2979 options->V3AuthoritativeDir))
2980 REJECT("AuthoritativeDir is set, but none of "
2981 "(Bridge/HS/V1/V2/V3)AuthoritativeDir is set.");
2982 /* If we have a v3bandwidthsfile and it's broken, complain on startup */
2983 if (options->V3BandwidthsFile && !old_options) {
2984 dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL);
2988 if (options->AuthoritativeDir && !options->DirPort)
2989 REJECT("Running as authoritative directory, but no DirPort set.");
2991 if (options->AuthoritativeDir && !options->ORPort)
2992 REJECT("Running as authoritative directory, but no ORPort set.");
2994 if (options->AuthoritativeDir && options->ClientOnly)
2995 REJECT("Running as authoritative directory, but ClientOnly also set.");
2997 if (options->FetchDirInfoExtraEarly && !options->FetchDirInfoEarly)
2998 REJECT("FetchDirInfoExtraEarly requires that you also set "
2999 "FetchDirInfoEarly");
3001 if (options->ConnLimit <= 0) {
3002 tor_asprintf(msg,
3003 "ConnLimit must be greater than 0, but was set to %d",
3004 options->ConnLimit);
3005 return -1;
3008 if (validate_ports_csv(options->FirewallPorts, "FirewallPorts", msg) < 0)
3009 return -1;
3011 if (validate_ports_csv(options->LongLivedPorts, "LongLivedPorts", msg) < 0)
3012 return -1;
3014 if (validate_ports_csv(options->RejectPlaintextPorts,
3015 "RejectPlaintextPorts", msg) < 0)
3016 return -1;
3018 if (validate_ports_csv(options->WarnPlaintextPorts,
3019 "WarnPlaintextPorts", msg) < 0)
3020 return -1;
3022 if (options->FascistFirewall && !options->ReachableAddresses) {
3023 if (options->FirewallPorts && smartlist_len(options->FirewallPorts)) {
3024 /* We already have firewall ports set, so migrate them to
3025 * ReachableAddresses, which will set ReachableORAddresses and
3026 * ReachableDirAddresses if they aren't set explicitly. */
3027 smartlist_t *instead = smartlist_create();
3028 config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
3029 new_line->key = tor_strdup("ReachableAddresses");
3030 /* If we're configured with the old format, we need to prepend some
3031 * open ports. */
3032 SMARTLIST_FOREACH(options->FirewallPorts, const char *, portno,
3034 int p = atoi(portno);
3035 char *s;
3036 if (p<0) continue;
3037 s = tor_malloc(16);
3038 tor_snprintf(s, 16, "*:%d", p);
3039 smartlist_add(instead, s);
3041 new_line->value = smartlist_join_strings(instead,",",0,NULL);
3042 /* These have been deprecated since 0.1.1.5-alpha-cvs */
3043 log(LOG_NOTICE, LD_CONFIG,
3044 "Converting FascistFirewall and FirewallPorts "
3045 "config options to new format: \"ReachableAddresses %s\"",
3046 new_line->value);
3047 options->ReachableAddresses = new_line;
3048 SMARTLIST_FOREACH(instead, char *, cp, tor_free(cp));
3049 smartlist_free(instead);
3050 } else {
3051 /* We do not have FirewallPorts set, so add 80 to
3052 * ReachableDirAddresses, and 443 to ReachableORAddresses. */
3053 if (!options->ReachableDirAddresses) {
3054 config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
3055 new_line->key = tor_strdup("ReachableDirAddresses");
3056 new_line->value = tor_strdup("*:80");
3057 options->ReachableDirAddresses = new_line;
3058 log(LOG_NOTICE, LD_CONFIG, "Converting FascistFirewall config option "
3059 "to new format: \"ReachableDirAddresses *:80\"");
3061 if (!options->ReachableORAddresses) {
3062 config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
3063 new_line->key = tor_strdup("ReachableORAddresses");
3064 new_line->value = tor_strdup("*:443");
3065 options->ReachableORAddresses = new_line;
3066 log(LOG_NOTICE, LD_CONFIG, "Converting FascistFirewall config option "
3067 "to new format: \"ReachableORAddresses *:443\"");
3072 for (i=0; i<3; i++) {
3073 config_line_t **linep =
3074 (i==0) ? &options->ReachableAddresses :
3075 (i==1) ? &options->ReachableORAddresses :
3076 &options->ReachableDirAddresses;
3077 if (!*linep)
3078 continue;
3079 /* We need to end with a reject *:*, not an implicit accept *:* */
3080 for (;;) {
3081 if (!strcmp((*linep)->value, "reject *:*")) /* already there */
3082 break;
3083 linep = &((*linep)->next);
3084 if (!*linep) {
3085 *linep = tor_malloc_zero(sizeof(config_line_t));
3086 (*linep)->key = tor_strdup(
3087 (i==0) ? "ReachableAddresses" :
3088 (i==1) ? "ReachableORAddresses" :
3089 "ReachableDirAddresses");
3090 (*linep)->value = tor_strdup("reject *:*");
3091 break;
3096 if ((options->ReachableAddresses ||
3097 options->ReachableORAddresses ||
3098 options->ReachableDirAddresses) &&
3099 server_mode(options))
3100 REJECT("Servers must be able to freely connect to the rest "
3101 "of the Internet, so they must not set Reachable*Addresses "
3102 "or FascistFirewall.");
3104 if (options->UseBridges &&
3105 server_mode(options))
3106 REJECT("Servers must be able to freely connect to the rest "
3107 "of the Internet, so they must not set UseBridges.");
3109 options->_AllowInvalid = 0;
3110 if (options->AllowInvalidNodes) {
3111 SMARTLIST_FOREACH(options->AllowInvalidNodes, const char *, cp, {
3112 if (!strcasecmp(cp, "entry"))
3113 options->_AllowInvalid |= ALLOW_INVALID_ENTRY;
3114 else if (!strcasecmp(cp, "exit"))
3115 options->_AllowInvalid |= ALLOW_INVALID_EXIT;
3116 else if (!strcasecmp(cp, "middle"))
3117 options->_AllowInvalid |= ALLOW_INVALID_MIDDLE;
3118 else if (!strcasecmp(cp, "introduction"))
3119 options->_AllowInvalid |= ALLOW_INVALID_INTRODUCTION;
3120 else if (!strcasecmp(cp, "rendezvous"))
3121 options->_AllowInvalid |= ALLOW_INVALID_RENDEZVOUS;
3122 else {
3123 tor_asprintf(msg,
3124 "Unrecognized value '%s' in AllowInvalidNodes", cp);
3125 return -1;
3130 if (!options->SafeLogging ||
3131 !strcasecmp(options->SafeLogging, "0")) {
3132 options->_SafeLogging = SAFELOG_SCRUB_NONE;
3133 } else if (!strcasecmp(options->SafeLogging, "relay")) {
3134 options->_SafeLogging = SAFELOG_SCRUB_RELAY;
3135 } else if (!strcasecmp(options->SafeLogging, "1")) {
3136 options->_SafeLogging = SAFELOG_SCRUB_ALL;
3137 } else {
3138 tor_asprintf(msg,
3139 "Unrecognized value '%s' in SafeLogging",
3140 escaped(options->SafeLogging));
3141 return -1;
3144 if (compute_publishserverdescriptor(options) < 0) {
3145 tor_asprintf(msg, "Unrecognized value in PublishServerDescriptor");
3146 return -1;
3149 if ((options->BridgeRelay
3150 || options->_PublishServerDescriptor & BRIDGE_AUTHORITY)
3151 && (options->_PublishServerDescriptor
3152 & (V1_AUTHORITY|V2_AUTHORITY|V3_AUTHORITY))) {
3153 REJECT("Bridges are not supposed to publish router descriptors to the "
3154 "directory authorities. Please correct your "
3155 "PublishServerDescriptor line.");
3158 if (options->MinUptimeHidServDirectoryV2 < 0) {
3159 log_warn(LD_CONFIG, "MinUptimeHidServDirectoryV2 option must be at "
3160 "least 0 seconds. Changing to 0.");
3161 options->MinUptimeHidServDirectoryV2 = 0;
3164 if (options->RendPostPeriod < MIN_REND_POST_PERIOD) {
3165 log_warn(LD_CONFIG, "RendPostPeriod option is too short; "
3166 "raising to %d seconds.", MIN_REND_POST_PERIOD);
3167 options->RendPostPeriod = MIN_REND_POST_PERIOD;
3170 if (options->RendPostPeriod > MAX_DIR_PERIOD) {
3171 log_warn(LD_CONFIG, "RendPostPeriod is too large; clipping to %ds.",
3172 MAX_DIR_PERIOD);
3173 options->RendPostPeriod = MAX_DIR_PERIOD;
3176 if (options->MaxCircuitDirtiness < MIN_MAX_CIRCUIT_DIRTINESS) {
3177 log_warn(LD_CONFIG, "MaxCircuitDirtiness option is too short; "
3178 "raising to %d seconds.", MIN_MAX_CIRCUIT_DIRTINESS);
3179 options->MaxCircuitDirtiness = MIN_MAX_CIRCUIT_DIRTINESS;
3182 if (options->CircuitStreamTimeout &&
3183 options->CircuitStreamTimeout < MIN_CIRCUIT_STREAM_TIMEOUT) {
3184 log_warn(LD_CONFIG, "CircuitStreamTimeout option is too short; "
3185 "raising to %d seconds.", MIN_CIRCUIT_STREAM_TIMEOUT);
3186 options->CircuitStreamTimeout = MIN_CIRCUIT_STREAM_TIMEOUT;
3189 if (options->KeepalivePeriod < 1)
3190 REJECT("KeepalivePeriod option must be positive.");
3192 if (ensure_bandwidth_cap(&options->BandwidthRate,
3193 "BandwidthRate", msg) < 0)
3194 return -1;
3195 if (ensure_bandwidth_cap(&options->BandwidthBurst,
3196 "BandwidthBurst", msg) < 0)
3197 return -1;
3198 if (ensure_bandwidth_cap(&options->MaxAdvertisedBandwidth,
3199 "MaxAdvertisedBandwidth", msg) < 0)
3200 return -1;
3201 if (ensure_bandwidth_cap(&options->RelayBandwidthRate,
3202 "RelayBandwidthRate", msg) < 0)
3203 return -1;
3204 if (ensure_bandwidth_cap(&options->RelayBandwidthBurst,
3205 "RelayBandwidthBurst", msg) < 0)
3206 return -1;
3207 if (ensure_bandwidth_cap(&options->PerConnBWRate,
3208 "PerConnBWRate", msg) < 0)
3209 return -1;
3210 if (ensure_bandwidth_cap(&options->PerConnBWBurst,
3211 "PerConnBWBurst", msg) < 0)
3212 return -1;
3214 if (server_mode(options)) {
3215 if (options->BandwidthRate < ROUTER_REQUIRED_MIN_BANDWIDTH) {
3216 tor_asprintf(msg,
3217 "BandwidthRate is set to %d bytes/second. "
3218 "For servers, it must be at least %d.",
3219 (int)options->BandwidthRate,
3220 ROUTER_REQUIRED_MIN_BANDWIDTH);
3221 return -1;
3222 } else if (options->MaxAdvertisedBandwidth <
3223 ROUTER_REQUIRED_MIN_BANDWIDTH/2) {
3224 tor_asprintf(msg,
3225 "MaxAdvertisedBandwidth is set to %d bytes/second. "
3226 "For servers, it must be at least %d.",
3227 (int)options->MaxAdvertisedBandwidth,
3228 ROUTER_REQUIRED_MIN_BANDWIDTH/2);
3229 return -1;
3231 if (options->RelayBandwidthRate &&
3232 options->RelayBandwidthRate < ROUTER_REQUIRED_MIN_BANDWIDTH) {
3233 tor_asprintf(msg,
3234 "RelayBandwidthRate is set to %d bytes/second. "
3235 "For servers, it must be at least %d.",
3236 (int)options->RelayBandwidthRate,
3237 ROUTER_REQUIRED_MIN_BANDWIDTH);
3238 return -1;
3242 if (options->RelayBandwidthRate && !options->RelayBandwidthBurst)
3243 options->RelayBandwidthBurst = options->RelayBandwidthRate;
3245 if (options->RelayBandwidthRate > options->RelayBandwidthBurst)
3246 REJECT("RelayBandwidthBurst must be at least equal "
3247 "to RelayBandwidthRate.");
3249 if (options->BandwidthRate > options->BandwidthBurst)
3250 REJECT("BandwidthBurst must be at least equal to BandwidthRate.");
3252 /* if they set relaybandwidth* really high but left bandwidth*
3253 * at the default, raise the defaults. */
3254 if (options->RelayBandwidthRate > options->BandwidthRate)
3255 options->BandwidthRate = options->RelayBandwidthRate;
3256 if (options->RelayBandwidthBurst > options->BandwidthBurst)
3257 options->BandwidthBurst = options->RelayBandwidthBurst;
3259 if (accounting_parse_options(options, 1)<0)
3260 REJECT("Failed to parse accounting options. See logs for details.");
3262 if (options->HttpProxy) { /* parse it now */
3263 if (tor_addr_port_parse(options->HttpProxy,
3264 &options->HttpProxyAddr, &options->HttpProxyPort) < 0)
3265 REJECT("HttpProxy failed to parse or resolve. Please fix.");
3266 if (options->HttpProxyPort == 0) { /* give it a default */
3267 options->HttpProxyPort = 80;
3271 if (options->HttpProxyAuthenticator) {
3272 if (strlen(options->HttpProxyAuthenticator) >= 48)
3273 REJECT("HttpProxyAuthenticator is too long (>= 48 chars).");
3276 if (options->HttpsProxy) { /* parse it now */
3277 if (tor_addr_port_parse(options->HttpsProxy,
3278 &options->HttpsProxyAddr, &options->HttpsProxyPort) <0)
3279 REJECT("HttpsProxy failed to parse or resolve. Please fix.");
3280 if (options->HttpsProxyPort == 0) { /* give it a default */
3281 options->HttpsProxyPort = 443;
3285 if (options->HttpsProxyAuthenticator) {
3286 if (strlen(options->HttpsProxyAuthenticator) >= 48)
3287 REJECT("HttpsProxyAuthenticator is too long (>= 48 chars).");
3290 if (options->Socks4Proxy) { /* parse it now */
3291 if (tor_addr_port_parse(options->Socks4Proxy,
3292 &options->Socks4ProxyAddr,
3293 &options->Socks4ProxyPort) <0)
3294 REJECT("Socks4Proxy failed to parse or resolve. Please fix.");
3295 if (options->Socks4ProxyPort == 0) { /* give it a default */
3296 options->Socks4ProxyPort = 1080;
3300 if (options->Socks5Proxy) { /* parse it now */
3301 if (tor_addr_port_parse(options->Socks5Proxy,
3302 &options->Socks5ProxyAddr,
3303 &options->Socks5ProxyPort) <0)
3304 REJECT("Socks5Proxy failed to parse or resolve. Please fix.");
3305 if (options->Socks5ProxyPort == 0) { /* give it a default */
3306 options->Socks5ProxyPort = 1080;
3310 if (options->Socks4Proxy && options->Socks5Proxy)
3311 REJECT("You cannot specify both Socks4Proxy and SOCKS5Proxy");
3313 if (options->Socks5ProxyUsername) {
3314 size_t len;
3316 len = strlen(options->Socks5ProxyUsername);
3317 if (len < 1 || len > 255)
3318 REJECT("Socks5ProxyUsername must be between 1 and 255 characters.");
3320 if (!options->Socks5ProxyPassword)
3321 REJECT("Socks5ProxyPassword must be included with Socks5ProxyUsername.");
3323 len = strlen(options->Socks5ProxyPassword);
3324 if (len < 1 || len > 255)
3325 REJECT("Socks5ProxyPassword must be between 1 and 255 characters.");
3326 } else if (options->Socks5ProxyPassword)
3327 REJECT("Socks5ProxyPassword must be included with Socks5ProxyUsername.");
3329 if (options->HashedControlPassword) {
3330 smartlist_t *sl = decode_hashed_passwords(options->HashedControlPassword);
3331 if (!sl) {
3332 REJECT("Bad HashedControlPassword: wrong length or bad encoding");
3333 } else {
3334 SMARTLIST_FOREACH(sl, char*, cp, tor_free(cp));
3335 smartlist_free(sl);
3339 if (options->HashedControlSessionPassword) {
3340 smartlist_t *sl = decode_hashed_passwords(
3341 options->HashedControlSessionPassword);
3342 if (!sl) {
3343 REJECT("Bad HashedControlSessionPassword: wrong length or bad encoding");
3344 } else {
3345 SMARTLIST_FOREACH(sl, char*, cp, tor_free(cp));
3346 smartlist_free(sl);
3350 if (options->ControlListenAddress) {
3351 int all_are_local = 1;
3352 config_line_t *ln;
3353 for (ln = options->ControlListenAddress; ln; ln = ln->next) {
3354 if (strcmpstart(ln->value, "127."))
3355 all_are_local = 0;
3357 if (!all_are_local) {
3358 if (!options->HashedControlPassword &&
3359 !options->HashedControlSessionPassword &&
3360 !options->CookieAuthentication) {
3361 log_warn(LD_CONFIG,
3362 "You have a ControlListenAddress set to accept "
3363 "unauthenticated connections from a non-local address. "
3364 "This means that programs not running on your computer "
3365 "can reconfigure your Tor, without even having to guess a "
3366 "password. That's so bad that I'm closing your ControlPort "
3367 "for you. If you need to control your Tor remotely, try "
3368 "enabling authentication and using a tool like stunnel or "
3369 "ssh to encrypt remote access.");
3370 options->ControlPort = 0;
3371 } else {
3372 log_warn(LD_CONFIG, "You have a ControlListenAddress set to accept "
3373 "connections from a non-local address. This means that "
3374 "programs not running on your computer can reconfigure your "
3375 "Tor. That's pretty bad, since the controller "
3376 "protocol isn't encrypted! Maybe you should just listen on "
3377 "127.0.0.1 and use a tool like stunnel or ssh to encrypt "
3378 "remote connections to your control port.");
3383 if (options->ControlPort && !options->HashedControlPassword &&
3384 !options->HashedControlSessionPassword &&
3385 !options->CookieAuthentication) {
3386 log_warn(LD_CONFIG, "ControlPort is open, but no authentication method "
3387 "has been configured. This means that any program on your "
3388 "computer can reconfigure your Tor. That's bad! You should "
3389 "upgrade your Tor controller as soon as possible.");
3392 if (options->UseEntryGuards && ! options->NumEntryGuards)
3393 REJECT("Cannot enable UseEntryGuards with NumEntryGuards set to 0");
3395 if (check_nickname_list(options->MyFamily, "MyFamily", msg))
3396 return -1;
3397 for (cl = options->NodeFamilies; cl; cl = cl->next) {
3398 if (check_nickname_list(cl->value, "NodeFamily", msg))
3399 return -1;
3402 if (validate_addr_policies(options, msg) < 0)
3403 return -1;
3405 if (validate_dir_authorities(options, old_options) < 0)
3406 REJECT("Directory authority line did not parse. See logs for details.");
3408 if (options->UseBridges && !options->Bridges)
3409 REJECT("If you set UseBridges, you must specify at least one bridge.");
3410 if (options->UseBridges && !options->TunnelDirConns)
3411 REJECT("If you set UseBridges, you must set TunnelDirConns.");
3412 if (options->Bridges) {
3413 for (cl = options->Bridges; cl; cl = cl->next) {
3414 if (parse_bridge_line(cl->value, 1)<0)
3415 REJECT("Bridge line did not parse. See logs for details.");
3419 if (options->ConstrainedSockets) {
3420 /* If the user wants to constrain socket buffer use, make sure the desired
3421 * limit is between MIN|MAX_TCPSOCK_BUFFER in k increments. */
3422 if (options->ConstrainedSockSize < MIN_CONSTRAINED_TCP_BUFFER ||
3423 options->ConstrainedSockSize > MAX_CONSTRAINED_TCP_BUFFER ||
3424 options->ConstrainedSockSize % 1024) {
3425 tor_asprintf(msg,
3426 "ConstrainedSockSize is invalid. Must be a value between %d and %d "
3427 "in 1024 byte increments.",
3428 MIN_CONSTRAINED_TCP_BUFFER, MAX_CONSTRAINED_TCP_BUFFER);
3429 return -1;
3431 if (options->DirPort) {
3432 /* Providing cached directory entries while system TCP buffers are scarce
3433 * will exacerbate the socket errors. Suggest that this be disabled. */
3434 COMPLAIN("You have requested constrained socket buffers while also "
3435 "serving directory entries via DirPort. It is strongly "
3436 "suggested that you disable serving directory requests when "
3437 "system TCP buffer resources are scarce.");
3441 if (options->V3AuthVoteDelay + options->V3AuthDistDelay >=
3442 options->V3AuthVotingInterval/2) {
3443 REJECT("V3AuthVoteDelay plus V3AuthDistDelay must be less than half "
3444 "V3AuthVotingInterval");
3446 if (options->V3AuthVoteDelay < MIN_VOTE_SECONDS)
3447 REJECT("V3AuthVoteDelay is way too low.");
3448 if (options->V3AuthDistDelay < MIN_DIST_SECONDS)
3449 REJECT("V3AuthDistDelay is way too low.");
3451 if (options->V3AuthNIntervalsValid < 2)
3452 REJECT("V3AuthNIntervalsValid must be at least 2.");
3454 if (options->V3AuthVotingInterval < MIN_VOTE_INTERVAL) {
3455 REJECT("V3AuthVotingInterval is insanely low.");
3456 } else if (options->V3AuthVotingInterval > 24*60*60) {
3457 REJECT("V3AuthVotingInterval is insanely high.");
3458 } else if (((24*60*60) % options->V3AuthVotingInterval) != 0) {
3459 COMPLAIN("V3AuthVotingInterval does not divide evenly into 24 hours.");
3462 if (rend_config_services(options, 1) < 0)
3463 REJECT("Failed to configure rendezvous options. See logs for details.");
3465 /* Parse client-side authorization for hidden services. */
3466 if (rend_parse_service_authorization(options, 1) < 0)
3467 REJECT("Failed to configure client authorization for hidden services. "
3468 "See logs for details.");
3470 if (parse_virtual_addr_network(options->VirtualAddrNetwork, 1, NULL)<0)
3471 return -1;
3473 if (options->PreferTunneledDirConns && !options->TunnelDirConns)
3474 REJECT("Must set TunnelDirConns if PreferTunneledDirConns is set.");
3476 if ((options->Socks4Proxy || options->Socks5Proxy) &&
3477 !options->HttpProxy && !options->PreferTunneledDirConns)
3478 REJECT("When Socks4Proxy or Socks5Proxy is configured, "
3479 "PreferTunneledDirConns and TunnelDirConns must both be "
3480 "set to 1, or HttpProxy must be configured.");
3482 if (options->AutomapHostsSuffixes) {
3483 SMARTLIST_FOREACH(options->AutomapHostsSuffixes, char *, suf,
3485 size_t len = strlen(suf);
3486 if (len && suf[len-1] == '.')
3487 suf[len-1] = '\0';
3491 if (options->TestingTorNetwork && !options->DirServers) {
3492 REJECT("TestingTorNetwork may only be configured in combination with "
3493 "a non-default set of DirServers.");
3496 /*XXXX022 checking for defaults manually like this is a bit fragile.*/
3498 /* Keep changes to hard-coded values synchronous to man page and default
3499 * values table. */
3500 if (options->TestingV3AuthInitialVotingInterval != 30*60 &&
3501 !options->TestingTorNetwork) {
3502 REJECT("TestingV3AuthInitialVotingInterval may only be changed in testing "
3503 "Tor networks!");
3504 } else if (options->TestingV3AuthInitialVotingInterval < MIN_VOTE_INTERVAL) {
3505 REJECT("TestingV3AuthInitialVotingInterval is insanely low.");
3506 } else if (((30*60) % options->TestingV3AuthInitialVotingInterval) != 0) {
3507 REJECT("TestingV3AuthInitialVotingInterval does not divide evenly into "
3508 "30 minutes.");
3511 if (options->TestingV3AuthInitialVoteDelay != 5*60 &&
3512 !options->TestingTorNetwork) {
3513 REJECT("TestingV3AuthInitialVoteDelay may only be changed in testing "
3514 "Tor networks!");
3515 } else if (options->TestingV3AuthInitialVoteDelay < MIN_VOTE_SECONDS) {
3516 REJECT("TestingV3AuthInitialVoteDelay is way too low.");
3519 if (options->TestingV3AuthInitialDistDelay != 5*60 &&
3520 !options->TestingTorNetwork) {
3521 REJECT("TestingV3AuthInitialDistDelay may only be changed in testing "
3522 "Tor networks!");
3523 } else if (options->TestingV3AuthInitialDistDelay < MIN_DIST_SECONDS) {
3524 REJECT("TestingV3AuthInitialDistDelay is way too low.");
3527 if (options->TestingV3AuthInitialVoteDelay +
3528 options->TestingV3AuthInitialDistDelay >=
3529 options->TestingV3AuthInitialVotingInterval/2) {
3530 REJECT("TestingV3AuthInitialVoteDelay plus TestingV3AuthInitialDistDelay "
3531 "must be less than half TestingV3AuthInitialVotingInterval");
3534 if (options->TestingAuthDirTimeToLearnReachability != 30*60 &&
3535 !options->TestingTorNetwork) {
3536 REJECT("TestingAuthDirTimeToLearnReachability may only be changed in "
3537 "testing Tor networks!");
3538 } else if (options->TestingAuthDirTimeToLearnReachability < 0) {
3539 REJECT("TestingAuthDirTimeToLearnReachability must be non-negative.");
3540 } else if (options->TestingAuthDirTimeToLearnReachability > 2*60*60) {
3541 COMPLAIN("TestingAuthDirTimeToLearnReachability is insanely high.");
3544 if (options->TestingEstimatedDescriptorPropagationTime != 10*60 &&
3545 !options->TestingTorNetwork) {
3546 REJECT("TestingEstimatedDescriptorPropagationTime may only be changed in "
3547 "testing Tor networks!");
3548 } else if (options->TestingEstimatedDescriptorPropagationTime < 0) {
3549 REJECT("TestingEstimatedDescriptorPropagationTime must be non-negative.");
3550 } else if (options->TestingEstimatedDescriptorPropagationTime > 60*60) {
3551 COMPLAIN("TestingEstimatedDescriptorPropagationTime is insanely high.");
3554 if (options->TestingTorNetwork) {
3555 log_warn(LD_CONFIG, "TestingTorNetwork is set. This will make your node "
3556 "almost unusable in the public Tor network, and is "
3557 "therefore only advised if you are building a "
3558 "testing Tor network!");
3561 if (options->AccelName && !options->HardwareAccel)
3562 options->HardwareAccel = 1;
3563 if (options->AccelDir && !options->AccelName)
3564 REJECT("Can't use hardware crypto accelerator dir without engine name.");
3566 return 0;
3567 #undef REJECT
3568 #undef COMPLAIN
3571 /** Helper: return true iff s1 and s2 are both NULL, or both non-NULL
3572 * equal strings. */
3573 static int
3574 opt_streq(const char *s1, const char *s2)
3576 if (!s1 && !s2)
3577 return 1;
3578 else if (s1 && s2 && !strcmp(s1,s2))
3579 return 1;
3580 else
3581 return 0;
3584 /** Check if any of the previous options have changed but aren't allowed to. */
3585 static int
3586 options_transition_allowed(or_options_t *old, or_options_t *new_val,
3587 char **msg)
3589 if (!old)
3590 return 0;
3592 if (!opt_streq(old->PidFile, new_val->PidFile)) {
3593 *msg = tor_strdup("PidFile is not allowed to change.");
3594 return -1;
3597 if (old->RunAsDaemon != new_val->RunAsDaemon) {
3598 *msg = tor_strdup("While Tor is running, changing RunAsDaemon "
3599 "is not allowed.");
3600 return -1;
3603 if (strcmp(old->DataDirectory,new_val->DataDirectory)!=0) {
3604 tor_asprintf(msg,
3605 "While Tor is running, changing DataDirectory "
3606 "(\"%s\"->\"%s\") is not allowed.",
3607 old->DataDirectory, new_val->DataDirectory);
3608 return -1;
3611 if (!opt_streq(old->User, new_val->User)) {
3612 *msg = tor_strdup("While Tor is running, changing User is not allowed.");
3613 return -1;
3616 if ((old->HardwareAccel != new_val->HardwareAccel)
3617 || !opt_streq(old->AccelName, new_val->AccelName)
3618 || !opt_streq(old->AccelDir, new_val->AccelDir)) {
3619 *msg = tor_strdup("While Tor is running, changing OpenSSL hardware "
3620 "acceleration engine is not allowed.");
3621 return -1;
3624 if (old->TestingTorNetwork != new_val->TestingTorNetwork) {
3625 *msg = tor_strdup("While Tor is running, changing TestingTorNetwork "
3626 "is not allowed.");
3627 return -1;
3630 if (old->CellStatistics != new_val->CellStatistics ||
3631 old->DirReqStatistics != new_val->DirReqStatistics ||
3632 old->EntryStatistics != new_val->EntryStatistics ||
3633 old->ExitPortStatistics != new_val->ExitPortStatistics) {
3634 *msg = tor_strdup("While Tor is running, changing either "
3635 "CellStatistics, DirReqStatistics, EntryStatistics, "
3636 "or ExitPortStatistics is not allowed.");
3637 return -1;
3640 if (old->DisableAllSwap != new_val->DisableAllSwap) {
3641 *msg = tor_strdup("While Tor is running, changing DisableAllSwap "
3642 "is not allowed.");
3643 return -1;
3646 return 0;
3649 /** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
3650 * will require us to rotate the CPU and DNS workers; else return 0. */
3651 static int
3652 options_transition_affects_workers(or_options_t *old_options,
3653 or_options_t *new_options)
3655 if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) ||
3656 old_options->NumCpus != new_options->NumCpus ||
3657 old_options->ORPort != new_options->ORPort ||
3658 old_options->ServerDNSSearchDomains !=
3659 new_options->ServerDNSSearchDomains ||
3660 old_options->SafeLogging != new_options->SafeLogging ||
3661 old_options->ClientOnly != new_options->ClientOnly ||
3662 !config_lines_eq(old_options->Logs, new_options->Logs))
3663 return 1;
3665 /* Check whether log options match. */
3667 /* Nothing that changed matters. */
3668 return 0;
3671 /** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
3672 * will require us to generate a new descriptor; else return 0. */
3673 static int
3674 options_transition_affects_descriptor(or_options_t *old_options,
3675 or_options_t *new_options)
3677 /* XXX We can be smarter here. If your DirPort isn't being
3678 * published and you just turned it off, no need to republish. Etc. */
3679 if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) ||
3680 !opt_streq(old_options->Nickname,new_options->Nickname) ||
3681 !opt_streq(old_options->Address,new_options->Address) ||
3682 !config_lines_eq(old_options->ExitPolicy,new_options->ExitPolicy) ||
3683 old_options->ExitPolicyRejectPrivate !=
3684 new_options->ExitPolicyRejectPrivate ||
3685 old_options->ORPort != new_options->ORPort ||
3686 old_options->DirPort != new_options->DirPort ||
3687 old_options->ClientOnly != new_options->ClientOnly ||
3688 old_options->NoPublish != new_options->NoPublish ||
3689 old_options->_PublishServerDescriptor !=
3690 new_options->_PublishServerDescriptor ||
3691 get_effective_bwrate(old_options) != get_effective_bwrate(new_options) ||
3692 get_effective_bwburst(old_options) !=
3693 get_effective_bwburst(new_options) ||
3694 !opt_streq(old_options->ContactInfo, new_options->ContactInfo) ||
3695 !opt_streq(old_options->MyFamily, new_options->MyFamily) ||
3696 !opt_streq(old_options->AccountingStart, new_options->AccountingStart) ||
3697 old_options->AccountingMax != new_options->AccountingMax)
3698 return 1;
3700 return 0;
3703 #ifdef MS_WINDOWS
3704 /** Return the directory on windows where we expect to find our application
3705 * data. */
3706 static char *
3707 get_windows_conf_root(void)
3709 static int is_set = 0;
3710 static char path[MAX_PATH+1];
3711 WCHAR wpath[MAX_PATH] = {0};
3713 LPITEMIDLIST idl;
3714 IMalloc *m;
3715 HRESULT result;
3717 if (is_set)
3718 return path;
3720 /* Find X:\documents and settings\username\application data\ .
3721 * We would use SHGetSpecialFolder path, but that wasn't added until IE4.
3723 #ifdef ENABLE_LOCAL_APPDATA
3724 #define APPDATA_PATH CSIDL_LOCAL_APPDATA
3725 #else
3726 #define APPDATA_PATH CSIDL_APPDATA
3727 #endif
3728 if (!SUCCEEDED(SHGetSpecialFolderLocation(NULL, APPDATA_PATH, &idl))) {
3729 getcwd(path,MAX_PATH);
3730 is_set = 1;
3731 log_warn(LD_CONFIG,
3732 "I couldn't find your application data folder: are you "
3733 "running an ancient version of Windows 95? Defaulting to \"%s\"",
3734 path);
3735 return path;
3737 /* Convert the path from an "ID List" (whatever that is!) to a path. */
3738 result = SHGetPathFromIDListW(idl, wpath);
3739 wcstombs(path,wpath,MAX_PATH);
3741 /* Now we need to free the memory that the path-idl was stored in. In
3742 * typical Windows fashion, we can't just call 'free()' on it. */
3743 SHGetMalloc(&m);
3744 if (m) {
3745 m->lpVtbl->Free(m, idl);
3746 m->lpVtbl->Release(m);
3748 if (!SUCCEEDED(result)) {
3749 return NULL;
3751 strlcat(path,"\\tor",MAX_PATH);
3752 is_set = 1;
3753 return path;
3755 #endif
3757 /** Return the default location for our torrc file. */
3758 static const char *
3759 get_default_conf_file(void)
3761 #ifdef MS_WINDOWS
3762 static char path[MAX_PATH+1];
3763 strlcpy(path, get_windows_conf_root(), MAX_PATH);
3764 strlcat(path,"\\torrc",MAX_PATH);
3765 return path;
3766 #else
3767 return (CONFDIR "/torrc");
3768 #endif
3771 /** Verify whether lst is a string containing valid-looking comma-separated
3772 * nicknames, or NULL. Return 0 on success. Warn and return -1 on failure.
3774 static int
3775 check_nickname_list(const char *lst, const char *name, char **msg)
3777 int r = 0;
3778 smartlist_t *sl;
3780 if (!lst)
3781 return 0;
3782 sl = smartlist_create();
3784 smartlist_split_string(sl, lst, ",",
3785 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0);
3787 SMARTLIST_FOREACH(sl, const char *, s,
3789 if (!is_legal_nickname_or_hexdigest(s)) {
3790 tor_asprintf(msg, "Invalid nickname '%s' in %s line", s, name);
3791 r = -1;
3792 break;
3795 SMARTLIST_FOREACH(sl, char *, s, tor_free(s));
3796 smartlist_free(sl);
3797 return r;
3800 /** Learn config file name from command line arguments, or use the default */
3801 static char *
3802 find_torrc_filename(int argc, char **argv,
3803 int *using_default_torrc, int *ignore_missing_torrc)
3805 char *fname=NULL;
3806 int i;
3808 for (i = 1; i < argc; ++i) {
3809 if (i < argc-1 && !strcmp(argv[i],"-f")) {
3810 if (fname) {
3811 log(LOG_WARN, LD_CONFIG, "Duplicate -f options on command line.");
3812 tor_free(fname);
3814 fname = expand_filename(argv[i+1]);
3815 *using_default_torrc = 0;
3816 ++i;
3817 } else if (!strcmp(argv[i],"--ignore-missing-torrc")) {
3818 *ignore_missing_torrc = 1;
3822 if (*using_default_torrc) {
3823 /* didn't find one, try CONFDIR */
3824 const char *dflt = get_default_conf_file();
3825 if (dflt && file_status(dflt) == FN_FILE) {
3826 fname = tor_strdup(dflt);
3827 } else {
3828 #ifndef MS_WINDOWS
3829 char *fn;
3830 fn = expand_filename("~/.torrc");
3831 if (fn && file_status(fn) == FN_FILE) {
3832 fname = fn;
3833 } else {
3834 tor_free(fn);
3835 fname = tor_strdup(dflt);
3837 #else
3838 fname = tor_strdup(dflt);
3839 #endif
3842 return fname;
3845 /** Load torrc from disk, setting torrc_fname if successful */
3846 static char *
3847 load_torrc_from_disk(int argc, char **argv)
3849 char *fname=NULL;
3850 char *cf = NULL;
3851 int using_default_torrc = 1;
3852 int ignore_missing_torrc = 0;
3854 fname = find_torrc_filename(argc, argv,
3855 &using_default_torrc, &ignore_missing_torrc);
3856 tor_assert(fname);
3857 log(LOG_DEBUG, LD_CONFIG, "Opening config file \"%s\"", fname);
3859 tor_free(torrc_fname);
3860 torrc_fname = fname;
3862 /* Open config file */
3863 if (file_status(fname) != FN_FILE ||
3864 !(cf = read_file_to_str(fname,0,NULL))) {
3865 if (using_default_torrc == 1 || ignore_missing_torrc ) {
3866 log(LOG_NOTICE, LD_CONFIG, "Configuration file \"%s\" not present, "
3867 "using reasonable defaults.", fname);
3868 tor_free(fname); /* sets fname to NULL */
3869 torrc_fname = NULL;
3870 cf = tor_strdup("");
3871 } else {
3872 log(LOG_WARN, LD_CONFIG,
3873 "Unable to open configuration file \"%s\".", fname);
3874 goto err;
3878 return cf;
3879 err:
3880 tor_free(fname);
3881 torrc_fname = NULL;
3882 return NULL;
3885 /** Read a configuration file into <b>options</b>, finding the configuration
3886 * file location based on the command line. After loading the file
3887 * call options_init_from_string() to load the config.
3888 * Return 0 if success, -1 if failure. */
3890 options_init_from_torrc(int argc, char **argv)
3892 char *cf=NULL;
3893 int i, retval, command;
3894 static char **backup_argv;
3895 static int backup_argc;
3896 char *command_arg = NULL;
3897 char *errmsg=NULL;
3899 if (argv) { /* first time we're called. save command line args */
3900 backup_argv = argv;
3901 backup_argc = argc;
3902 } else { /* we're reloading. need to clean up old options first. */
3903 argv = backup_argv;
3904 argc = backup_argc;
3906 if (argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1],"--help"))) {
3907 print_usage();
3908 exit(0);
3910 if (argc > 1 && !strcmp(argv[1], "--list-torrc-options")) {
3911 /* For documenting validating whether we've documented everything. */
3912 list_torrc_options();
3913 exit(0);
3916 if (argc > 1 && (!strcmp(argv[1],"--version"))) {
3917 printf("Tor version %s.\n",get_version());
3918 exit(0);
3920 if (argc > 1 && (!strcmp(argv[1],"--digests"))) {
3921 printf("Tor version %s.\n",get_version());
3922 printf("%s", libor_get_digests());
3923 printf("%s", tor_get_digests());
3924 exit(0);
3927 /* Go through command-line variables */
3928 if (!global_cmdline_options) {
3929 /* Or we could redo the list every time we pass this place.
3930 * It does not really matter */
3931 if (config_get_commandlines(argc, argv, &global_cmdline_options) < 0) {
3932 goto err;
3936 command = CMD_RUN_TOR;
3937 for (i = 1; i < argc; ++i) {
3938 if (!strcmp(argv[i],"--list-fingerprint")) {
3939 command = CMD_LIST_FINGERPRINT;
3940 } else if (!strcmp(argv[i],"--hash-password")) {
3941 command = CMD_HASH_PASSWORD;
3942 command_arg = tor_strdup( (i < argc-1) ? argv[i+1] : "");
3943 ++i;
3944 } else if (!strcmp(argv[i],"--verify-config")) {
3945 command = CMD_VERIFY_CONFIG;
3949 if (command == CMD_HASH_PASSWORD) {
3950 cf = tor_strdup("");
3951 } else {
3952 cf = load_torrc_from_disk(argc, argv);
3953 if (!cf)
3954 goto err;
3957 retval = options_init_from_string(cf, command, command_arg, &errmsg);
3958 tor_free(cf);
3959 if (retval < 0)
3960 goto err;
3962 return 0;
3964 err:
3965 if (errmsg) {
3966 log(LOG_WARN,LD_CONFIG,"%s", errmsg);
3967 tor_free(errmsg);
3969 return -1;
3972 /** Load the options from the configuration in <b>cf</b>, validate
3973 * them for consistency and take actions based on them.
3975 * Return 0 if success, negative on error:
3976 * * -1 for general errors.
3977 * * -2 for failure to parse/validate,
3978 * * -3 for transition not allowed
3979 * * -4 for error while setting the new options
3981 setopt_err_t
3982 options_init_from_string(const char *cf,
3983 int command, const char *command_arg,
3984 char **msg)
3986 or_options_t *oldoptions, *newoptions;
3987 config_line_t *cl;
3988 int retval;
3989 setopt_err_t err = SETOPT_ERR_MISC;
3990 tor_assert(msg);
3992 oldoptions = global_options; /* get_options unfortunately asserts if
3993 this is the first time we run*/
3995 newoptions = tor_malloc_zero(sizeof(or_options_t));
3996 newoptions->_magic = OR_OPTIONS_MAGIC;
3997 options_init(newoptions);
3998 newoptions->command = command;
3999 newoptions->command_arg = command_arg;
4001 /* get config lines, assign them */
4002 retval = config_get_lines(cf, &cl);
4003 if (retval < 0) {
4004 err = SETOPT_ERR_PARSE;
4005 goto err;
4007 retval = config_assign(&options_format, newoptions, cl, 0, 0, msg);
4008 config_free_lines(cl);
4009 if (retval < 0) {
4010 err = SETOPT_ERR_PARSE;
4011 goto err;
4014 /* Go through command-line variables too */
4015 retval = config_assign(&options_format, newoptions,
4016 global_cmdline_options, 0, 0, msg);
4017 if (retval < 0) {
4018 err = SETOPT_ERR_PARSE;
4019 goto err;
4022 /* If this is a testing network configuration, change defaults
4023 * for a list of dependent config options, re-initialize newoptions
4024 * with the new defaults, and assign all options to it second time. */
4025 if (newoptions->TestingTorNetwork) {
4026 /* XXXX this is a bit of a kludge. perhaps there's a better way to do
4027 * this? We could, for example, make the parsing algorithm do two passes
4028 * over the configuration. If it finds any "suite" options like
4029 * TestingTorNetwork, it could change the defaults before its second pass.
4030 * Not urgent so long as this seems to work, but at any sign of trouble,
4031 * let's clean it up. -NM */
4033 /* Change defaults. */
4034 int i;
4035 for (i = 0; testing_tor_network_defaults[i].name; ++i) {
4036 config_var_t *new_var = &testing_tor_network_defaults[i];
4037 config_var_t *old_var =
4038 config_find_option(&options_format, new_var->name);
4039 tor_assert(new_var);
4040 tor_assert(old_var);
4041 old_var->initvalue = new_var->initvalue;
4044 /* Clear newoptions and re-initialize them with new defaults. */
4045 config_free(&options_format, newoptions);
4046 newoptions = tor_malloc_zero(sizeof(or_options_t));
4047 newoptions->_magic = OR_OPTIONS_MAGIC;
4048 options_init(newoptions);
4049 newoptions->command = command;
4050 newoptions->command_arg = command_arg;
4052 /* Assign all options a second time. */
4053 retval = config_get_lines(cf, &cl);
4054 if (retval < 0) {
4055 err = SETOPT_ERR_PARSE;
4056 goto err;
4058 retval = config_assign(&options_format, newoptions, cl, 0, 0, msg);
4059 config_free_lines(cl);
4060 if (retval < 0) {
4061 err = SETOPT_ERR_PARSE;
4062 goto err;
4064 retval = config_assign(&options_format, newoptions,
4065 global_cmdline_options, 0, 0, msg);
4066 if (retval < 0) {
4067 err = SETOPT_ERR_PARSE;
4068 goto err;
4072 /* Validate newoptions */
4073 if (options_validate(oldoptions, newoptions, 0, msg) < 0) {
4074 err = SETOPT_ERR_PARSE; /*XXX make this a separate return value.*/
4075 goto err;
4078 if (options_transition_allowed(oldoptions, newoptions, msg) < 0) {
4079 err = SETOPT_ERR_TRANSITION;
4080 goto err;
4083 if (set_options(newoptions, msg)) {
4084 err = SETOPT_ERR_SETTING;
4085 goto err; /* frees and replaces old options */
4088 return SETOPT_OK;
4090 err:
4091 config_free(&options_format, newoptions);
4092 if (*msg) {
4093 char *old_msg = *msg;
4094 tor_asprintf(msg, "Failed to parse/validate config: %s", old_msg);
4095 tor_free(old_msg);
4097 return err;
4100 /** Return the location for our configuration file.
4102 const char *
4103 get_torrc_fname(void)
4105 if (torrc_fname)
4106 return torrc_fname;
4107 else
4108 return get_default_conf_file();
4111 /** Adjust the address map based on the MapAddress elements in the
4112 * configuration <b>options</b>
4114 static void
4115 config_register_addressmaps(or_options_t *options)
4117 smartlist_t *elts;
4118 config_line_t *opt;
4119 char *from, *to;
4121 addressmap_clear_configured();
4122 elts = smartlist_create();
4123 for (opt = options->AddressMap; opt; opt = opt->next) {
4124 smartlist_split_string(elts, opt->value, NULL,
4125 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
4126 if (smartlist_len(elts) >= 2) {
4127 from = smartlist_get(elts,0);
4128 to = smartlist_get(elts,1);
4129 if (address_is_invalid_destination(to, 1)) {
4130 log_warn(LD_CONFIG,
4131 "Skipping invalid argument '%s' to MapAddress", to);
4132 } else {
4133 addressmap_register(from, tor_strdup(to), 0, ADDRMAPSRC_TORRC);
4134 if (smartlist_len(elts)>2) {
4135 log_warn(LD_CONFIG,"Ignoring extra arguments to MapAddress.");
4138 } else {
4139 log_warn(LD_CONFIG,"MapAddress '%s' has too few arguments. Ignoring.",
4140 opt->value);
4142 SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp));
4143 smartlist_clear(elts);
4145 smartlist_free(elts);
4149 * Initialize the logs based on the configuration file.
4151 static int
4152 options_init_logs(or_options_t *options, int validate_only)
4154 config_line_t *opt;
4155 int ok;
4156 smartlist_t *elts;
4157 int daemon =
4158 #ifdef MS_WINDOWS
4160 #else
4161 options->RunAsDaemon;
4162 #endif
4164 ok = 1;
4165 elts = smartlist_create();
4167 for (opt = options->Logs; opt; opt = opt->next) {
4168 log_severity_list_t *severity;
4169 const char *cfg = opt->value;
4170 severity = tor_malloc_zero(sizeof(log_severity_list_t));
4171 if (parse_log_severity_config(&cfg, severity) < 0) {
4172 log_warn(LD_CONFIG, "Couldn't parse log levels in Log option 'Log %s'",
4173 opt->value);
4174 ok = 0; goto cleanup;
4177 smartlist_split_string(elts, cfg, NULL,
4178 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
4180 if (smartlist_len(elts) == 0)
4181 smartlist_add(elts, tor_strdup("stdout"));
4183 if (smartlist_len(elts) == 1 &&
4184 (!strcasecmp(smartlist_get(elts,0), "stdout") ||
4185 !strcasecmp(smartlist_get(elts,0), "stderr"))) {
4186 int err = smartlist_len(elts) &&
4187 !strcasecmp(smartlist_get(elts,0), "stderr");
4188 if (!validate_only) {
4189 if (daemon) {
4190 log_warn(LD_CONFIG,
4191 "Can't log to %s with RunAsDaemon set; skipping stdout",
4192 err?"stderr":"stdout");
4193 } else {
4194 add_stream_log(severity, err?"<stderr>":"<stdout>",
4195 fileno(err?stderr:stdout));
4198 goto cleanup;
4200 if (smartlist_len(elts) == 1 &&
4201 !strcasecmp(smartlist_get(elts,0), "syslog")) {
4202 #ifdef HAVE_SYSLOG_H
4203 if (!validate_only) {
4204 add_syslog_log(severity);
4206 #else
4207 log_warn(LD_CONFIG, "Syslog is not supported on this system. Sorry.");
4208 #endif
4209 goto cleanup;
4212 if (smartlist_len(elts) == 2 &&
4213 !strcasecmp(smartlist_get(elts,0), "file")) {
4214 if (!validate_only) {
4215 if (add_file_log(severity, smartlist_get(elts, 1)) < 0) {
4216 log_warn(LD_CONFIG, "Couldn't open file for 'Log %s': %s",
4217 opt->value, strerror(errno));
4218 ok = 0;
4221 goto cleanup;
4224 log_warn(LD_CONFIG, "Bad syntax on file Log option 'Log %s'",
4225 opt->value);
4226 ok = 0; goto cleanup;
4228 cleanup:
4229 SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp));
4230 smartlist_clear(elts);
4231 tor_free(severity);
4233 smartlist_free(elts);
4235 return ok?0:-1;
4238 /** Read the contents of a Bridge line from <b>line</b>. Return 0
4239 * if the line is well-formed, and -1 if it isn't. If
4240 * <b>validate_only</b> is 0, and the line is well-formed, then add
4241 * the bridge described in the line to our internal bridge list. */
4242 static int
4243 parse_bridge_line(const char *line, int validate_only)
4245 smartlist_t *items = NULL;
4246 int r;
4247 char *addrport=NULL, *fingerprint=NULL;
4248 tor_addr_t addr;
4249 uint16_t port = 0;
4250 char digest[DIGEST_LEN];
4252 items = smartlist_create();
4253 smartlist_split_string(items, line, NULL,
4254 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
4255 if (smartlist_len(items) < 1) {
4256 log_warn(LD_CONFIG, "Too few arguments to Bridge line.");
4257 goto err;
4259 addrport = smartlist_get(items, 0);
4260 smartlist_del_keeporder(items, 0);
4261 if (tor_addr_port_parse(addrport, &addr, &port)<0) {
4262 log_warn(LD_CONFIG, "Error parsing Bridge address '%s'", addrport);
4263 goto err;
4265 if (!port) {
4266 log_info(LD_CONFIG,
4267 "Bridge address '%s' has no port; using default port 443.",
4268 addrport);
4269 port = 443;
4272 if (smartlist_len(items)) {
4273 fingerprint = smartlist_join_strings(items, "", 0, NULL);
4274 if (strlen(fingerprint) != HEX_DIGEST_LEN) {
4275 log_warn(LD_CONFIG, "Key digest for Bridge is wrong length.");
4276 goto err;
4278 if (base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN)<0) {
4279 log_warn(LD_CONFIG, "Unable to decode Bridge key digest.");
4280 goto err;
4284 if (!validate_only) {
4285 log_debug(LD_DIR, "Bridge at %s:%d (%s)", fmt_addr(&addr),
4286 (int)port,
4287 fingerprint ? fingerprint : "no key listed");
4288 bridge_add_from_config(&addr, port, fingerprint ? digest : NULL);
4291 r = 0;
4292 goto done;
4294 err:
4295 r = -1;
4297 done:
4298 SMARTLIST_FOREACH(items, char*, s, tor_free(s));
4299 smartlist_free(items);
4300 tor_free(addrport);
4301 tor_free(fingerprint);
4302 return r;
4305 /** Read the contents of a DirServer line from <b>line</b>. If
4306 * <b>validate_only</b> is 0, and the line is well-formed, and it
4307 * shares any bits with <b>required_type</b> or <b>required_type</b>
4308 * is 0, then add the dirserver described in the line (minus whatever
4309 * bits it's missing) as a valid authority. Return 0 on success,
4310 * or -1 if the line isn't well-formed or if we can't add it. */
4311 static int
4312 parse_dir_server_line(const char *line, authority_type_t required_type,
4313 int validate_only)
4315 smartlist_t *items = NULL;
4316 int r;
4317 char *addrport=NULL, *address=NULL, *nickname=NULL, *fingerprint=NULL;
4318 uint16_t dir_port = 0, or_port = 0;
4319 char digest[DIGEST_LEN];
4320 char v3_digest[DIGEST_LEN];
4321 authority_type_t type = V2_AUTHORITY;
4322 int is_not_hidserv_authority = 0, is_not_v2_authority = 0;
4324 items = smartlist_create();
4325 smartlist_split_string(items, line, NULL,
4326 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
4327 if (smartlist_len(items) < 1) {
4328 log_warn(LD_CONFIG, "No arguments on DirServer line.");
4329 goto err;
4332 if (is_legal_nickname(smartlist_get(items, 0))) {
4333 nickname = smartlist_get(items, 0);
4334 smartlist_del_keeporder(items, 0);
4337 while (smartlist_len(items)) {
4338 char *flag = smartlist_get(items, 0);
4339 if (TOR_ISDIGIT(flag[0]))
4340 break;
4341 if (!strcasecmp(flag, "v1")) {
4342 type |= (V1_AUTHORITY | HIDSERV_AUTHORITY);
4343 } else if (!strcasecmp(flag, "hs")) {
4344 type |= HIDSERV_AUTHORITY;
4345 } else if (!strcasecmp(flag, "no-hs")) {
4346 is_not_hidserv_authority = 1;
4347 } else if (!strcasecmp(flag, "bridge")) {
4348 type |= BRIDGE_AUTHORITY;
4349 } else if (!strcasecmp(flag, "no-v2")) {
4350 is_not_v2_authority = 1;
4351 } else if (!strcasecmpstart(flag, "orport=")) {
4352 int ok;
4353 char *portstring = flag + strlen("orport=");
4354 or_port = (uint16_t) tor_parse_long(portstring, 10, 1, 65535, &ok, NULL);
4355 if (!ok)
4356 log_warn(LD_CONFIG, "Invalid orport '%s' on DirServer line.",
4357 portstring);
4358 } else if (!strcasecmpstart(flag, "v3ident=")) {
4359 char *idstr = flag + strlen("v3ident=");
4360 if (strlen(idstr) != HEX_DIGEST_LEN ||
4361 base16_decode(v3_digest, DIGEST_LEN, idstr, HEX_DIGEST_LEN)<0) {
4362 log_warn(LD_CONFIG, "Bad v3 identity digest '%s' on DirServer line",
4363 flag);
4364 } else {
4365 type |= V3_AUTHORITY;
4367 } else {
4368 log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirServer line",
4369 flag);
4371 tor_free(flag);
4372 smartlist_del_keeporder(items, 0);
4374 if (is_not_hidserv_authority)
4375 type &= ~HIDSERV_AUTHORITY;
4376 if (is_not_v2_authority)
4377 type &= ~V2_AUTHORITY;
4379 if (smartlist_len(items) < 2) {
4380 log_warn(LD_CONFIG, "Too few arguments to DirServer line.");
4381 goto err;
4383 addrport = smartlist_get(items, 0);
4384 smartlist_del_keeporder(items, 0);
4385 if (parse_addr_port(LOG_WARN, addrport, &address, NULL, &dir_port)<0) {
4386 log_warn(LD_CONFIG, "Error parsing DirServer address '%s'", addrport);
4387 goto err;
4389 if (!dir_port) {
4390 log_warn(LD_CONFIG, "Missing port in DirServer address '%s'",addrport);
4391 goto err;
4394 fingerprint = smartlist_join_strings(items, "", 0, NULL);
4395 if (strlen(fingerprint) != HEX_DIGEST_LEN) {
4396 log_warn(LD_CONFIG, "Key digest for DirServer is wrong length %d.",
4397 (int)strlen(fingerprint));
4398 goto err;
4400 if (!strcmp(fingerprint, "E623F7625FBE0C87820F11EC5F6D5377ED816294")) {
4401 /* a known bad fingerprint. refuse to use it. We can remove this
4402 * clause once Tor 0.1.2.17 is obsolete. */
4403 log_warn(LD_CONFIG, "Dangerous dirserver line. To correct, erase your "
4404 "torrc file (%s), or reinstall Tor and use the default torrc.",
4405 get_torrc_fname());
4406 goto err;
4408 if (base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN)<0) {
4409 log_warn(LD_CONFIG, "Unable to decode DirServer key digest.");
4410 goto err;
4413 if (!validate_only && (!required_type || required_type & type)) {
4414 if (required_type)
4415 type &= required_type; /* pare down what we think of them as an
4416 * authority for. */
4417 log_debug(LD_DIR, "Trusted %d dirserver at %s:%d (%s)", (int)type,
4418 address, (int)dir_port, (char*)smartlist_get(items,0));
4419 if (!add_trusted_dir_server(nickname, address, dir_port, or_port,
4420 digest, v3_digest, type))
4421 goto err;
4424 r = 0;
4425 goto done;
4427 err:
4428 r = -1;
4430 done:
4431 SMARTLIST_FOREACH(items, char*, s, tor_free(s));
4432 smartlist_free(items);
4433 tor_free(addrport);
4434 tor_free(address);
4435 tor_free(nickname);
4436 tor_free(fingerprint);
4437 return r;
4440 /** Adjust the value of options->DataDirectory, or fill it in if it's
4441 * absent. Return 0 on success, -1 on failure. */
4442 static int
4443 normalize_data_directory(or_options_t *options)
4445 #ifdef MS_WINDOWS
4446 char *p;
4447 if (options->DataDirectory)
4448 return 0; /* all set */
4449 p = tor_malloc(MAX_PATH);
4450 strlcpy(p,get_windows_conf_root(),MAX_PATH);
4451 options->DataDirectory = p;
4452 return 0;
4453 #else
4454 const char *d = options->DataDirectory;
4455 if (!d)
4456 d = "~/.tor";
4458 if (strncmp(d,"~/",2) == 0) {
4459 char *fn = expand_filename(d);
4460 if (!fn) {
4461 log_warn(LD_CONFIG,"Failed to expand filename \"%s\".", d);
4462 return -1;
4464 if (!options->DataDirectory && !strcmp(fn,"/.tor")) {
4465 /* If our homedir is /, we probably don't want to use it. */
4466 /* Default to LOCALSTATEDIR/tor which is probably closer to what we
4467 * want. */
4468 log_warn(LD_CONFIG,
4469 "Default DataDirectory is \"~/.tor\". This expands to "
4470 "\"%s\", which is probably not what you want. Using "
4471 "\"%s"PATH_SEPARATOR"tor\" instead", fn, LOCALSTATEDIR);
4472 tor_free(fn);
4473 fn = tor_strdup(LOCALSTATEDIR PATH_SEPARATOR "tor");
4475 tor_free(options->DataDirectory);
4476 options->DataDirectory = fn;
4478 return 0;
4479 #endif
4482 /** Check and normalize the value of options->DataDirectory; return 0 if it
4483 * is sane, -1 otherwise. */
4484 static int
4485 validate_data_directory(or_options_t *options)
4487 if (normalize_data_directory(options) < 0)
4488 return -1;
4489 tor_assert(options->DataDirectory);
4490 if (strlen(options->DataDirectory) > (512-128)) {
4491 log_warn(LD_CONFIG, "DataDirectory is too long.");
4492 return -1;
4494 return 0;
4497 /** This string must remain the same forevermore. It is how we
4498 * recognize that the torrc file doesn't need to be backed up. */
4499 #define GENERATED_FILE_PREFIX "# This file was generated by Tor; " \
4500 "if you edit it, comments will not be preserved"
4501 /** This string can change; it tries to give the reader an idea
4502 * that editing this file by hand is not a good plan. */
4503 #define GENERATED_FILE_COMMENT "# The old torrc file was renamed " \
4504 "to torrc.orig.1 or similar, and Tor will ignore it"
4506 /** Save a configuration file for the configuration in <b>options</b>
4507 * into the file <b>fname</b>. If the file already exists, and
4508 * doesn't begin with GENERATED_FILE_PREFIX, rename it. Otherwise
4509 * replace it. Return 0 on success, -1 on failure. */
4510 static int
4511 write_configuration_file(const char *fname, or_options_t *options)
4513 char *old_val=NULL, *new_val=NULL, *new_conf=NULL;
4514 int rename_old = 0, r;
4516 tor_assert(fname);
4518 switch (file_status(fname)) {
4519 case FN_FILE:
4520 old_val = read_file_to_str(fname, 0, NULL);
4521 if (strcmpstart(old_val, GENERATED_FILE_PREFIX)) {
4522 rename_old = 1;
4524 tor_free(old_val);
4525 break;
4526 case FN_NOENT:
4527 break;
4528 case FN_ERROR:
4529 case FN_DIR:
4530 default:
4531 log_warn(LD_CONFIG,
4532 "Config file \"%s\" is not a file? Failing.", fname);
4533 return -1;
4536 if (!(new_conf = options_dump(options, 1))) {
4537 log_warn(LD_BUG, "Couldn't get configuration string");
4538 goto err;
4541 tor_asprintf(&new_val, "%s\n%s\n\n%s",
4542 GENERATED_FILE_PREFIX, GENERATED_FILE_COMMENT, new_conf);
4544 if (rename_old) {
4545 int i = 1;
4546 size_t fn_tmp_len = strlen(fname)+32;
4547 char *fn_tmp;
4548 tor_assert(fn_tmp_len > strlen(fname)); /*check for overflow*/
4549 fn_tmp = tor_malloc(fn_tmp_len);
4550 while (1) {
4551 if (tor_snprintf(fn_tmp, fn_tmp_len, "%s.orig.%d", fname, i)<0) {
4552 log_warn(LD_BUG, "tor_snprintf failed inexplicably");
4553 tor_free(fn_tmp);
4554 goto err;
4556 if (file_status(fn_tmp) == FN_NOENT)
4557 break;
4558 ++i;
4560 log_notice(LD_CONFIG, "Renaming old configuration file to \"%s\"", fn_tmp);
4561 if (rename(fname, fn_tmp) < 0) {
4562 log_warn(LD_FS,
4563 "Couldn't rename configuration file \"%s\" to \"%s\": %s",
4564 fname, fn_tmp, strerror(errno));
4565 tor_free(fn_tmp);
4566 goto err;
4568 tor_free(fn_tmp);
4571 if (write_str_to_file(fname, new_val, 0) < 0)
4572 goto err;
4574 r = 0;
4575 goto done;
4576 err:
4577 r = -1;
4578 done:
4579 tor_free(new_val);
4580 tor_free(new_conf);
4581 return r;
4585 * Save the current configuration file value to disk. Return 0 on
4586 * success, -1 on failure.
4589 options_save_current(void)
4591 /* This fails if we can't write to our configuration file.
4593 * If we try falling back to datadirectory or something, we have a better
4594 * chance of saving the configuration, but a better chance of doing
4595 * something the user never expected. */
4596 return write_configuration_file(get_torrc_fname(), get_options());
4599 /** Mapping from a unit name to a multiplier for converting that unit into a
4600 * base unit. */
4601 struct unit_table_t {
4602 const char *unit;
4603 uint64_t multiplier;
4606 /** Table to map the names of memory units to the number of bytes they
4607 * contain. */
4608 static struct unit_table_t memory_units[] = {
4609 { "", 1 },
4610 { "b", 1<< 0 },
4611 { "byte", 1<< 0 },
4612 { "bytes", 1<< 0 },
4613 { "kb", 1<<10 },
4614 { "kbyte", 1<<10 },
4615 { "kbytes", 1<<10 },
4616 { "kilobyte", 1<<10 },
4617 { "kilobytes", 1<<10 },
4618 { "m", 1<<20 },
4619 { "mb", 1<<20 },
4620 { "mbyte", 1<<20 },
4621 { "mbytes", 1<<20 },
4622 { "megabyte", 1<<20 },
4623 { "megabytes", 1<<20 },
4624 { "gb", 1<<30 },
4625 { "gbyte", 1<<30 },
4626 { "gbytes", 1<<30 },
4627 { "gigabyte", 1<<30 },
4628 { "gigabytes", 1<<30 },
4629 { "tb", U64_LITERAL(1)<<40 },
4630 { "terabyte", U64_LITERAL(1)<<40 },
4631 { "terabytes", U64_LITERAL(1)<<40 },
4632 { NULL, 0 },
4635 /** Table to map the names of time units to the number of seconds they
4636 * contain. */
4637 static struct unit_table_t time_units[] = {
4638 { "", 1 },
4639 { "second", 1 },
4640 { "seconds", 1 },
4641 { "minute", 60 },
4642 { "minutes", 60 },
4643 { "hour", 60*60 },
4644 { "hours", 60*60 },
4645 { "day", 24*60*60 },
4646 { "days", 24*60*60 },
4647 { "week", 7*24*60*60 },
4648 { "weeks", 7*24*60*60 },
4649 { NULL, 0 },
4652 /** Parse a string <b>val</b> containing a number, zero or more
4653 * spaces, and an optional unit string. If the unit appears in the
4654 * table <b>u</b>, then multiply the number by the unit multiplier.
4655 * On success, set *<b>ok</b> to 1 and return this product.
4656 * Otherwise, set *<b>ok</b> to 0.
4658 static uint64_t
4659 config_parse_units(const char *val, struct unit_table_t *u, int *ok)
4661 uint64_t v = 0;
4662 double d = 0;
4663 int use_float = 0;
4664 char *cp;
4666 tor_assert(ok);
4668 v = tor_parse_uint64(val, 10, 0, UINT64_MAX, ok, &cp);
4669 if (!*ok || (cp && *cp == '.')) {
4670 d = tor_parse_double(val, 0, UINT64_MAX, ok, &cp);
4671 if (!*ok)
4672 goto done;
4673 use_float = 1;
4676 if (!cp) {
4677 *ok = 1;
4678 v = use_float ? DBL_TO_U64(d) : v;
4679 goto done;
4682 cp = (char*) eat_whitespace(cp);
4684 for ( ;u->unit;++u) {
4685 if (!strcasecmp(u->unit, cp)) {
4686 if (use_float)
4687 v = u->multiplier * d;
4688 else
4689 v *= u->multiplier;
4690 *ok = 1;
4691 goto done;
4694 log_warn(LD_CONFIG, "Unknown unit '%s'.", cp);
4695 *ok = 0;
4696 done:
4698 if (*ok)
4699 return v;
4700 else
4701 return 0;
4704 /** Parse a string in the format "number unit", where unit is a unit of
4705 * information (byte, KB, M, etc). On success, set *<b>ok</b> to true
4706 * and return the number of bytes specified. Otherwise, set
4707 * *<b>ok</b> to false and return 0. */
4708 static uint64_t
4709 config_parse_memunit(const char *s, int *ok)
4711 uint64_t u = config_parse_units(s, memory_units, ok);
4712 return u;
4715 /** Parse a string in the format "number unit", where unit is a unit of time.
4716 * On success, set *<b>ok</b> to true and return the number of seconds in
4717 * the provided interval. Otherwise, set *<b>ok</b> to 0 and return -1.
4719 static int
4720 config_parse_interval(const char *s, int *ok)
4722 uint64_t r;
4723 r = config_parse_units(s, time_units, ok);
4724 if (!ok)
4725 return -1;
4726 if (r > INT_MAX) {
4727 log_warn(LD_CONFIG, "Interval '%s' is too long", s);
4728 *ok = 0;
4729 return -1;
4731 return (int)r;
4735 * Initialize the libevent library.
4737 static void
4738 init_libevent(void)
4740 const char *badness=NULL;
4742 configure_libevent_logging();
4743 /* If the kernel complains that some method (say, epoll) doesn't
4744 * exist, we don't care about it, since libevent will cope.
4746 suppress_libevent_log_msg("Function not implemented");
4748 tor_check_libevent_header_compatibility();
4750 tor_libevent_initialize();
4752 suppress_libevent_log_msg(NULL);
4754 tor_check_libevent_version(tor_libevent_get_method(),
4755 get_options()->ORPort != 0,
4756 &badness);
4757 if (badness) {
4758 const char *v = tor_libevent_get_version_str();
4759 const char *m = tor_libevent_get_method();
4760 control_event_general_status(LOG_WARN,
4761 "BAD_LIBEVENT VERSION=%s METHOD=%s BADNESS=%s RECOVERED=NO",
4762 v, m, badness);
4766 /** Return the persistent state struct for this Tor. */
4767 or_state_t *
4768 get_or_state(void)
4770 tor_assert(global_state);
4771 return global_state;
4774 /** Return a newly allocated string holding a filename relative to the data
4775 * directory. If <b>sub1</b> is present, it is the first path component after
4776 * the data directory. If <b>sub2</b> is also present, it is the second path
4777 * component after the data directory. If <b>suffix</b> is present, it
4778 * is appended to the filename.
4780 * Examples:
4781 * get_datadir_fname2_suffix("a", NULL, NULL) -> $DATADIR/a
4782 * get_datadir_fname2_suffix("a", NULL, ".tmp") -> $DATADIR/a.tmp
4783 * get_datadir_fname2_suffix("a", "b", ".tmp") -> $DATADIR/a/b/.tmp
4784 * get_datadir_fname2_suffix("a", "b", NULL) -> $DATADIR/a/b
4786 * Note: Consider using the get_datadir_fname* macros in or.h.
4788 char *
4789 options_get_datadir_fname2_suffix(or_options_t *options,
4790 const char *sub1, const char *sub2,
4791 const char *suffix)
4793 char *fname = NULL;
4794 size_t len;
4795 tor_assert(options);
4796 tor_assert(options->DataDirectory);
4797 tor_assert(sub1 || !sub2); /* If sub2 is present, sub1 must be present. */
4798 len = strlen(options->DataDirectory);
4799 if (sub1) {
4800 len += strlen(sub1)+1;
4801 if (sub2)
4802 len += strlen(sub2)+1;
4804 if (suffix)
4805 len += strlen(suffix);
4806 len++;
4807 fname = tor_malloc(len);
4808 if (sub1) {
4809 if (sub2) {
4810 tor_snprintf(fname, len, "%s"PATH_SEPARATOR"%s"PATH_SEPARATOR"%s",
4811 options->DataDirectory, sub1, sub2);
4812 } else {
4813 tor_snprintf(fname, len, "%s"PATH_SEPARATOR"%s",
4814 options->DataDirectory, sub1);
4816 } else {
4817 strlcpy(fname, options->DataDirectory, len);
4819 if (suffix)
4820 strlcat(fname, suffix, len);
4821 return fname;
4824 /** Return 0 if every setting in <b>state</b> is reasonable, and a
4825 * permissible transition from <b>old_state</b>. Else warn and return -1.
4826 * Should have no side effects, except for normalizing the contents of
4827 * <b>state</b>.
4829 /* XXX from_setconf is here because of bug 238 */
4830 static int
4831 or_state_validate(or_state_t *old_state, or_state_t *state,
4832 int from_setconf, char **msg)
4834 /* We don't use these; only options do. Still, we need to match that
4835 * signature. */
4836 (void) from_setconf;
4837 (void) old_state;
4839 if (entry_guards_parse_state(state, 0, msg)<0)
4840 return -1;
4842 return 0;
4845 /** Replace the current persistent state with <b>new_state</b> */
4846 static int
4847 or_state_set(or_state_t *new_state)
4849 char *err = NULL;
4850 int ret = 0;
4851 tor_assert(new_state);
4852 config_free(&state_format, global_state);
4853 global_state = new_state;
4854 if (entry_guards_parse_state(global_state, 1, &err)<0) {
4855 log_warn(LD_GENERAL,"%s",err);
4856 tor_free(err);
4857 ret = -1;
4859 if (rep_hist_load_state(global_state, &err)<0) {
4860 log_warn(LD_GENERAL,"Unparseable bandwidth history state: %s",err);
4861 tor_free(err);
4862 ret = -1;
4864 if (circuit_build_times_parse_state(&circ_times, global_state, &err) < 0) {
4865 log_warn(LD_GENERAL,"%s",err);
4866 tor_free(err);
4867 ret = -1;
4869 return ret;
4873 * Save a broken state file to a backup location.
4875 static void
4876 or_state_save_broken(char *fname)
4878 int i;
4879 file_status_t status;
4880 size_t len = strlen(fname)+16;
4881 char *fname2 = tor_malloc(len);
4882 for (i = 0; i < 100; ++i) {
4883 tor_snprintf(fname2, len, "%s.%d", fname, i);
4884 status = file_status(fname2);
4885 if (status == FN_NOENT)
4886 break;
4888 if (i == 100) {
4889 log_warn(LD_BUG, "Unable to parse state in \"%s\"; too many saved bad "
4890 "state files to move aside. Discarding the old state file.",
4891 fname);
4892 unlink(fname);
4893 } else {
4894 log_warn(LD_BUG, "Unable to parse state in \"%s\". Moving it aside "
4895 "to \"%s\". This could be a bug in Tor; please tell "
4896 "the developers.", fname, fname2);
4897 if (rename(fname, fname2) < 0) {
4898 log_warn(LD_BUG, "Weirdly, I couldn't even move the state aside. The "
4899 "OS gave an error of %s", strerror(errno));
4902 tor_free(fname2);
4905 /** Reload the persistent state from disk, generating a new state as needed.
4906 * Return 0 on success, less than 0 on failure.
4908 static int
4909 or_state_load(void)
4911 or_state_t *new_state = NULL;
4912 char *contents = NULL, *fname;
4913 char *errmsg = NULL;
4914 int r = -1, badstate = 0;
4916 fname = get_datadir_fname("state");
4917 switch (file_status(fname)) {
4918 case FN_FILE:
4919 if (!(contents = read_file_to_str(fname, 0, NULL))) {
4920 log_warn(LD_FS, "Unable to read state file \"%s\"", fname);
4921 goto done;
4923 break;
4924 case FN_NOENT:
4925 break;
4926 case FN_ERROR:
4927 case FN_DIR:
4928 default:
4929 log_warn(LD_GENERAL,"State file \"%s\" is not a file? Failing.", fname);
4930 goto done;
4932 new_state = tor_malloc_zero(sizeof(or_state_t));
4933 new_state->_magic = OR_STATE_MAGIC;
4934 config_init(&state_format, new_state);
4935 if (contents) {
4936 config_line_t *lines=NULL;
4937 int assign_retval;
4938 if (config_get_lines(contents, &lines)<0)
4939 goto done;
4940 assign_retval = config_assign(&state_format, new_state,
4941 lines, 0, 0, &errmsg);
4942 config_free_lines(lines);
4943 if (assign_retval<0)
4944 badstate = 1;
4945 if (errmsg) {
4946 log_warn(LD_GENERAL, "%s", errmsg);
4947 tor_free(errmsg);
4951 if (!badstate && or_state_validate(NULL, new_state, 1, &errmsg) < 0)
4952 badstate = 1;
4954 if (errmsg) {
4955 log_warn(LD_GENERAL, "%s", errmsg);
4956 tor_free(errmsg);
4959 if (badstate && !contents) {
4960 log_warn(LD_BUG, "Uh oh. We couldn't even validate our own default state."
4961 " This is a bug in Tor.");
4962 goto done;
4963 } else if (badstate && contents) {
4964 or_state_save_broken(fname);
4966 tor_free(contents);
4967 config_free(&state_format, new_state);
4969 new_state = tor_malloc_zero(sizeof(or_state_t));
4970 new_state->_magic = OR_STATE_MAGIC;
4971 config_init(&state_format, new_state);
4972 } else if (contents) {
4973 log_info(LD_GENERAL, "Loaded state from \"%s\"", fname);
4974 } else {
4975 log_info(LD_GENERAL, "Initialized state");
4977 if (or_state_set(new_state) == -1) {
4978 or_state_save_broken(fname);
4980 new_state = NULL;
4981 if (!contents) {
4982 global_state->next_write = 0;
4983 or_state_save(time(NULL));
4985 r = 0;
4987 done:
4988 tor_free(fname);
4989 tor_free(contents);
4990 if (new_state)
4991 config_free(&state_format, new_state);
4993 return r;
4996 /** Write the persistent state to disk. Return 0 for success, <0 on failure. */
4998 or_state_save(time_t now)
5000 char *state, *contents;
5001 char tbuf[ISO_TIME_LEN+1];
5002 char *fname;
5004 tor_assert(global_state);
5006 if (global_state->next_write > now)
5007 return 0;
5009 /* Call everything else that might dirty the state even more, in order
5010 * to avoid redundant writes. */
5011 entry_guards_update_state(global_state);
5012 rep_hist_update_state(global_state);
5013 circuit_build_times_update_state(&circ_times, global_state);
5014 if (accounting_is_enabled(get_options()))
5015 accounting_run_housekeeping(now);
5017 tor_free(global_state->TorVersion);
5018 tor_asprintf(&global_state->TorVersion, "Tor %s", get_version());
5020 state = config_dump(&state_format, global_state, 1, 0);
5021 format_local_iso_time(tbuf, time(NULL));
5022 tor_asprintf(&contents,
5023 "# Tor state file last generated on %s local time\n"
5024 "# Other times below are in GMT\n"
5025 "# You *do not* need to edit this file.\n\n%s",
5026 tbuf, state);
5027 tor_free(state);
5028 fname = get_datadir_fname("state");
5029 if (write_str_to_file(fname, contents, 0)<0) {
5030 log_warn(LD_FS, "Unable to write state to file \"%s\"", fname);
5031 global_state->LastWritten = -1;
5032 tor_free(fname);
5033 tor_free(contents);
5034 return -1;
5037 global_state->LastWritten = time(NULL);
5038 log_info(LD_GENERAL, "Saved state to \"%s\"", fname);
5039 tor_free(fname);
5040 tor_free(contents);
5042 global_state->next_write = TIME_MAX;
5043 return 0;
5046 /** Given a file name check to see whether the file exists but has not been
5047 * modified for a very long time. If so, remove it. */
5048 void
5049 remove_file_if_very_old(const char *fname, time_t now)
5051 #define VERY_OLD_FILE_AGE (28*24*60*60)
5052 struct stat st;
5054 if (stat(fname, &st)==0 && st.st_mtime < now-VERY_OLD_FILE_AGE) {
5055 char buf[ISO_TIME_LEN+1];
5056 format_local_iso_time(buf, st.st_mtime);
5057 log_notice(LD_GENERAL, "Obsolete file %s hasn't been modified since %s. "
5058 "Removing it.", fname, buf);
5059 unlink(fname);
5063 /** Helper to implement GETINFO functions about configuration variables (not
5064 * their values). Given a "config/names" question, set *<b>answer</b> to a
5065 * new string describing the supported configuration variables and their
5066 * types. */
5068 getinfo_helper_config(control_connection_t *conn,
5069 const char *question, char **answer,
5070 const char **errmsg)
5072 (void) conn;
5073 (void) errmsg;
5074 if (!strcmp(question, "config/names")) {
5075 smartlist_t *sl = smartlist_create();
5076 int i;
5077 for (i = 0; _option_vars[i].name; ++i) {
5078 config_var_t *var = &_option_vars[i];
5079 const char *type;
5080 char *line;
5081 switch (var->type) {
5082 case CONFIG_TYPE_STRING: type = "String"; break;
5083 case CONFIG_TYPE_FILENAME: type = "Filename"; break;
5084 case CONFIG_TYPE_UINT: type = "Integer"; break;
5085 case CONFIG_TYPE_INTERVAL: type = "TimeInterval"; break;
5086 case CONFIG_TYPE_MEMUNIT: type = "DataSize"; break;
5087 case CONFIG_TYPE_DOUBLE: type = "Float"; break;
5088 case CONFIG_TYPE_BOOL: type = "Boolean"; break;
5089 case CONFIG_TYPE_ISOTIME: type = "Time"; break;
5090 case CONFIG_TYPE_ROUTERSET: type = "RouterList"; break;
5091 case CONFIG_TYPE_CSV: type = "CommaList"; break;
5092 case CONFIG_TYPE_LINELIST: type = "LineList"; break;
5093 case CONFIG_TYPE_LINELIST_S: type = "Dependant"; break;
5094 case CONFIG_TYPE_LINELIST_V: type = "Virtual"; break;
5095 default:
5096 case CONFIG_TYPE_OBSOLETE:
5097 type = NULL; break;
5099 if (!type)
5100 continue;
5101 tor_asprintf(&line, "%s %s\n",var->name,type);
5102 smartlist_add(sl, line);
5104 *answer = smartlist_join_strings(sl, "", 0, NULL);
5105 SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
5106 smartlist_free(sl);
5108 return 0;