r12122@Kushana: nickm | 2007-02-02 10:41:39 -0500
[tor.git] / src / or / config.c
blob7d7e788f0a9784b6bf039d72fcea28e214c1942e
1 /* Copyright (c) 2001 Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2007, Roger Dingledine, Nick Mathewson. */
4 /* See LICENSE for licensing information */
5 /* $Id$ */
6 const char config_c_id[] = \
7 "$Id$";
9 /**
10 * \file config.c
11 * \brief Code to parse and interpret configuration files.
12 **/
14 #include "or.h"
15 #ifdef MS_WINDOWS
16 #include <shlobj.h>
17 #endif
18 #include "../common/aes.h"
20 /** Enumeration of types which option values can take */
21 typedef enum config_type_t {
22 CONFIG_TYPE_STRING = 0, /**< An arbitrary string. */
23 CONFIG_TYPE_UINT, /**< A non-negative integer less than MAX_INT */
24 CONFIG_TYPE_INTERVAL, /**< A number of seconds, with optional units*/
25 CONFIG_TYPE_MEMUNIT, /**< A number of bytes, with optional units*/
26 CONFIG_TYPE_DOUBLE, /**< A floating-point value */
27 CONFIG_TYPE_BOOL, /**< A boolean value, expressed as 0 or 1. */
28 CONFIG_TYPE_ISOTIME, /**< An ISO-formated time relative to GMT. */
29 CONFIG_TYPE_CSV, /**< A list of strings, separated by commas and
30 * optional whitespace. */
31 CONFIG_TYPE_LINELIST, /**< Uninterpreted config lines */
32 CONFIG_TYPE_LINELIST_S, /**< Uninterpreted, context-sensitive config lines,
33 * mixed with other keywords. */
34 CONFIG_TYPE_LINELIST_V, /**< Catch-all "virtual" option to summarize
35 * context-sensitive config lines when fetching.
37 CONFIG_TYPE_OBSOLETE, /**< Obsolete (ignored) option. */
38 } config_type_t;
40 /** An abbreviation for a configuration option allowed on the command line. */
41 typedef struct config_abbrev_t {
42 const char *abbreviated;
43 const char *full;
44 int commandline_only;
45 int warn;
46 } config_abbrev_t;
48 /* Handy macro for declaring "In the config file or on the command line,
49 * you can abbreviate <b>tok</b>s as <b>tok</b>". */
50 #define PLURAL(tok) { #tok, #tok "s", 0, 0 }
52 /* A list of command-line abbreviations. */
53 static config_abbrev_t _option_abbrevs[] = {
54 PLURAL(ExitNode),
55 PLURAL(EntryNode),
56 PLURAL(ExcludeNode),
57 PLURAL(FirewallPort),
58 PLURAL(LongLivedPort),
59 PLURAL(HiddenServiceNode),
60 PLURAL(HiddenServiceExcludeNode),
61 PLURAL(NumCpu),
62 PLURAL(RendNode),
63 PLURAL(RendExcludeNode),
64 PLURAL(StrictEntryNode),
65 PLURAL(StrictExitNode),
66 { "l", "Log", 1, 0},
67 { "AllowUnverifiedNodes", "AllowInvalidNodes", 0, 0},
68 { "BandwidthRateBytes", "BandwidthRate", 0, 0},
69 { "BandwidthBurstBytes", "BandwidthBurst", 0, 0},
70 { "DirFetchPostPeriod", "StatusFetchPeriod", 0, 0},
71 { "MaxConn", "ConnLimit", 0, 1},
72 { "ORBindAddress", "ORListenAddress", 0, 0},
73 { "DirBindAddress", "DirListenAddress", 0, 0},
74 { "SocksBindAddress", "SocksListenAddress", 0, 0},
75 { "UseHelperNodes", "UseEntryGuards", 0, 0},
76 { "NumHelperNodes", "NumEntryGuards", 0, 0},
77 { "UseEntryNodes", "UseEntryGuards", 0, 0},
78 { "NumEntryNodes", "NumEntryGuards", 0, 0},
79 { "ResolvConf", "ServerDNSResolvConfFile", 0, 1},
80 { "SearchDomains", "ServerDNSSearchDomains", 0, 1},
81 { NULL, NULL, 0, 0},
83 /* A list of state-file abbreviations, for compatibility. */
84 static config_abbrev_t _state_abbrevs[] = {
85 { "AccountingBytesReadInterval", "AccountingBytesReadInInterval", 0, 0 },
86 { "HelperNode", "EntryGuard", 0, 0 },
87 { "HelperNodeDownSince", "EntryGuardDownSince", 0, 0 },
88 { "HelperNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 },
89 { "EntryNode", "EntryGuard", 0, 0 },
90 { "EntryNodeDownSince", "EntryGuardDownSince", 0, 0 },
91 { "EntryNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 },
92 { NULL, NULL, 0, 0},
94 #undef PLURAL
96 /** A variable allowed in the configuration file or on the command line. */
97 typedef struct config_var_t {
98 const char *name; /**< The full keyword (case insensitive). */
99 config_type_t type; /**< How to interpret the type and turn it into a
100 * value. */
101 off_t var_offset; /**< Offset of the corresponding member of or_options_t. */
102 const char *initvalue; /**< String (or null) describing initial value. */
103 } config_var_t;
105 #define STRUCT_VAR_P(st, off) \
106 ((void*) ( ((char*)st) + off ) )
108 /** An entry for config_vars: "The option <b>name</b> has type
109 * CONFIG_TYPE_<b>conftype</b>, and corresponds to
110 * or_options_t.<b>member</b>"
112 #define VAR(name,conftype,member,initvalue) \
113 { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_options_t, member), \
114 initvalue }
115 /** An entry for config_vars: "The option <b>name</b> is obsolete." */
116 #define OBSOLETE(name) { name, CONFIG_TYPE_OBSOLETE, 0, NULL }
118 /** Array of configuration options. Until we disallow nonstandard
119 * abbreviations, order is significant, since the first matching option will
120 * be chosen first.
122 static config_var_t _option_vars[] = {
123 OBSOLETE("AccountingMaxKB"),
124 VAR("AccountingMax", MEMUNIT, AccountingMax, "0 bytes"),
125 VAR("AccountingStart", STRING, AccountingStart, NULL),
126 VAR("Address", STRING, Address, NULL),
127 VAR("__AllDirActionsPrivate",BOOL, AllDirActionsPrivate, "0"),
128 VAR("AllowInvalidNodes", CSV, AllowInvalidNodes,
129 "middle,rendezvous"),
130 VAR("AllowNonRFC953Hostnames", BOOL, AllowNonRFC953Hostnames, "0"),
131 VAR("AssumeReachable", BOOL, AssumeReachable, "0"),
132 VAR("AuthDirBadExit", LINELIST, AuthDirBadExit, NULL),
133 VAR("AuthDirInvalid", LINELIST, AuthDirInvalid, NULL),
134 VAR("AuthDirReject", LINELIST, AuthDirReject, NULL),
135 VAR("AuthDirRejectUnlisted",BOOL, AuthDirRejectUnlisted,"0"),
136 VAR("AuthDirListBadExits", BOOL, AuthDirListBadExits, "0"),
137 VAR("AuthoritativeDirectory",BOOL, AuthoritativeDir, "0"),
138 VAR("AvoidDiskWrites", BOOL, AvoidDiskWrites, "0"),
139 VAR("BandwidthBurst", MEMUNIT, BandwidthBurst, "6 MB"),
140 VAR("BandwidthRate", MEMUNIT, BandwidthRate, "3 MB"),
141 VAR("CircuitBuildTimeout", INTERVAL, CircuitBuildTimeout, "1 minute"),
142 VAR("CircuitIdleTimeout", INTERVAL, CircuitIdleTimeout, "1 hour"),
143 VAR("ClientOnly", BOOL, ClientOnly, "0"),
144 VAR("ConnLimit", UINT, ConnLimit, "1000"),
145 VAR("ContactInfo", STRING, ContactInfo, NULL),
146 VAR("ControlListenAddress",LINELIST, ControlListenAddress, NULL),
147 VAR("ControlPort", UINT, ControlPort, "0"),
148 VAR("CookieAuthentication",BOOL, CookieAuthentication, "0"),
149 VAR("DataDirectory", STRING, DataDirectory, NULL),
150 OBSOLETE("DebugLogFile"),
151 VAR("DirAllowPrivateAddresses",BOOL, DirAllowPrivateAddresses, NULL),
152 VAR("DirListenAddress", LINELIST, DirListenAddress, NULL),
153 OBSOLETE("DirFetchPeriod"),
154 VAR("DirPolicy", LINELIST, DirPolicy, NULL),
155 VAR("DirPort", UINT, DirPort, "0"),
156 OBSOLETE("DirPostPeriod"),
157 VAR("DirServer", LINELIST, DirServers, NULL),
158 VAR("EnforceDistinctSubnets", BOOL, EnforceDistinctSubnets,"1"),
159 VAR("EntryNodes", STRING, EntryNodes, NULL),
160 VAR("ExcludeNodes", STRING, ExcludeNodes, NULL),
161 VAR("ExitNodes", STRING, ExitNodes, NULL),
162 VAR("ExitPolicy", LINELIST, ExitPolicy, NULL),
163 VAR("ExitPolicyRejectPrivate", BOOL, ExitPolicyRejectPrivate, "1"),
164 VAR("FascistFirewall", BOOL, FascistFirewall, "0"),
165 VAR("FirewallPorts", CSV, FirewallPorts, ""),
166 VAR("FastFirstHopPK", BOOL, FastFirstHopPK, "1"),
167 VAR("FetchServerDescriptors",BOOL, FetchServerDescriptors,"1"),
168 VAR("FetchHidServDescriptors",BOOL, FetchHidServDescriptors, "1"),
169 VAR("FetchUselessDescriptors",BOOL, FetchUselessDescriptors, "0"),
170 VAR("Group", STRING, Group, NULL),
171 VAR("HardwareAccel", BOOL, HardwareAccel, "0"),
172 VAR("HashedControlPassword",STRING, HashedControlPassword, NULL),
173 VAR("HiddenServiceDir", LINELIST_S, RendConfigLines, NULL),
174 VAR("HiddenServiceExcludeNodes", LINELIST_S, RendConfigLines, NULL),
175 VAR("HiddenServiceNodes", LINELIST_S, RendConfigLines, NULL),
176 VAR("HiddenServiceOptions",LINELIST_V, RendConfigLines, NULL),
177 VAR("HiddenServicePort", LINELIST_S, RendConfigLines, NULL),
178 VAR("HSAuthoritativeDir", BOOL, HSAuthoritativeDir, "0"),
179 VAR("HttpProxy", STRING, HttpProxy, NULL),
180 VAR("HttpProxyAuthenticator",STRING, HttpProxyAuthenticator,NULL),
181 VAR("HttpsProxy", STRING, HttpsProxy, NULL),
182 VAR("HttpsProxyAuthenticator",STRING,HttpsProxyAuthenticator,NULL),
183 OBSOLETE("IgnoreVersion"),
184 VAR("KeepalivePeriod", INTERVAL, KeepalivePeriod, "5 minutes"),
185 VAR("Log", LINELIST, Logs, NULL),
186 OBSOLETE("LinkPadding"),
187 OBSOLETE("LogLevel"),
188 OBSOLETE("LogFile"),
189 VAR("LongLivedPorts", CSV, LongLivedPorts,
190 "21,22,706,1863,5050,5190,5222,5223,6667,6697,8300"),
191 VAR("MapAddress", LINELIST, AddressMap, NULL),
192 VAR("MaxAdvertisedBandwidth",MEMUNIT,MaxAdvertisedBandwidth,"128 TB"),
193 VAR("MaxCircuitDirtiness", INTERVAL, MaxCircuitDirtiness, "10 minutes"),
194 VAR("MaxOnionsPending", UINT, MaxOnionsPending, "100"),
195 OBSOLETE("MonthlyAccountingStart"),
196 VAR("MyFamily", STRING, MyFamily, NULL),
197 VAR("NewCircuitPeriod", INTERVAL, NewCircuitPeriod, "30 seconds"),
198 VAR("NamingAuthoritativeDirectory",BOOL, NamingAuthoritativeDir, "0"),
199 VAR("NatdListenAddress", LINELIST, NatdListenAddress, NULL),
200 VAR("NatdPort", UINT, NatdPort, "0"),
201 VAR("Nickname", STRING, Nickname, NULL),
202 VAR("NoPublish", BOOL, NoPublish, "0"),
203 VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
204 VAR("NumCpus", UINT, NumCpus, "1"),
205 VAR("NumEntryGuards", UINT, NumEntryGuards, "3"),
206 VAR("ORListenAddress", LINELIST, ORListenAddress, NULL),
207 VAR("ORPort", UINT, ORPort, "0"),
208 VAR("OutboundBindAddress", STRING, OutboundBindAddress, NULL),
209 /* XXXX012 mark this obsolete? Warn if it's set? */
210 VAR("PathlenCoinWeight", DOUBLE, PathlenCoinWeight, "0.3"),
211 VAR("PidFile", STRING, PidFile, NULL),
212 VAR("PreferTunneledDirConns", BOOL, PreferTunneledDirConns, "0"),
213 VAR("ProtocolWarnings", BOOL, ProtocolWarnings, "0"),
214 VAR("PublishServerDescriptor",BOOL, PublishServerDescriptor,"1"),
215 VAR("PublishHidServDescriptors",BOOL,PublishHidServDescriptors, "1"),
216 VAR("ReachableAddresses", LINELIST, ReachableAddresses, NULL),
217 VAR("ReachableDirAddresses",LINELIST,ReachableDirAddresses,NULL),
218 VAR("ReachableORAddresses",LINELIST, ReachableORAddresses, NULL),
219 VAR("RecommendedVersions", LINELIST, RecommendedVersions, NULL),
220 VAR("RecommendedClientVersions", LINELIST, RecommendedClientVersions, NULL),
221 VAR("RecommendedServerVersions", LINELIST, RecommendedServerVersions, NULL),
222 VAR("RedirectExit", LINELIST, RedirectExit, NULL),
223 /* XXXX012 These aren't implemented. Take them out for now? */
224 VAR("RelayBandwidthBurst", MEMUNIT, RelayBandwidthBurst, "0"),
225 VAR("RelayBandwidthRate", MEMUNIT, RelayBandwidthRate, "0"),
226 VAR("RendExcludeNodes", STRING, RendExcludeNodes, NULL),
227 VAR("RendNodes", STRING, RendNodes, NULL),
228 VAR("RendPostPeriod", INTERVAL, RendPostPeriod, "1 hour"),
229 VAR("RephistTrackTime", INTERVAL, RephistTrackTime, "24 hours"),
230 OBSOLETE("RouterFile"),
231 VAR("RunAsDaemon", BOOL, RunAsDaemon, "0"),
232 VAR("RunTesting", BOOL, RunTesting, "0"),
233 VAR("SafeLogging", BOOL, SafeLogging, "1"),
234 VAR("SafeSocks", BOOL, SafeSocks, "0"),
235 VAR("ServerDNSAllowNonRFC953Hostnames",
236 BOOL, ServerDNSAllowNonRFC953Hostnames, "0"),
237 VAR("ServerDNSDetectHijacking",BOOL, ServerDNSDetectHijacking,"1"),
238 VAR("ServerDNSResolvConfFile", STRING, ServerDNSResolvConfFile, NULL),
239 VAR("ServerDNSSearchDomains", BOOL, ServerDNSSearchDomains, "0"),
240 VAR("ServerDNSTestAddresses", CSV, ServerDNSTestAddresses,
241 "www.google.com,www.mit.edu,www.yahoo.com,www.slashdot.org"),
242 VAR("ShutdownWaitLength", INTERVAL, ShutdownWaitLength, "30 seconds"),
243 VAR("SocksListenAddress", LINELIST, SocksListenAddress, NULL),
244 VAR("SocksPolicy", LINELIST, SocksPolicy, NULL),
245 VAR("SocksPort", UINT, SocksPort, "9050"),
246 VAR("SocksTimeout", INTERVAL, SocksTimeout, "2 minutes"),
247 OBSOLETE("StatusFetchPeriod"),
248 VAR("StrictEntryNodes", BOOL, StrictEntryNodes, "0"),
249 VAR("StrictExitNodes", BOOL, StrictExitNodes, "0"),
250 OBSOLETE("SysLog"),
251 VAR("TestSocks", BOOL, TestSocks, "0"),
252 VAR("TestVia", STRING, TestVia, NULL),
253 VAR("TrackHostExits", CSV, TrackHostExits, NULL),
254 VAR("TrackHostExitsExpire",INTERVAL, TrackHostExitsExpire, "30 minutes"),
255 OBSOLETE("TrafficShaping"),
256 VAR("TransListenAddress", LINELIST, TransListenAddress, NULL),
257 VAR("TransPort", UINT, TransPort, "0"),
258 VAR("TunnelDirConns", BOOL, TunnelDirConns, "0"),
259 VAR("UseEntryGuards", BOOL, UseEntryGuards, "1"),
260 VAR("User", STRING, User, NULL),
261 VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"),
262 VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"),
263 VAR("VirtualAddrNetwork", STRING, VirtualAddrNetwork, "127.192.0.0/10"),
264 VAR("__LeaveStreamsUnattached", BOOL,LeaveStreamsUnattached, "0"),
265 { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
267 #undef VAR
269 #define VAR(name,conftype,member,initvalue) \
270 { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_state_t, member), \
271 initvalue }
272 static config_var_t _state_vars[] = {
273 VAR("AccountingBytesReadInInterval", MEMUNIT,
274 AccountingBytesReadInInterval, NULL),
275 VAR("AccountingBytesWrittenInInterval", MEMUNIT,
276 AccountingBytesWrittenInInterval, NULL),
277 VAR("AccountingExpectedUsage", MEMUNIT, AccountingExpectedUsage, NULL),
278 VAR("AccountingIntervalStart", ISOTIME, AccountingIntervalStart, NULL),
279 VAR("AccountingSecondsActive", INTERVAL, AccountingSecondsActive, NULL),
280 VAR("EntryGuard", LINELIST_S, EntryGuards, NULL),
281 VAR("EntryGuardDownSince", LINELIST_S, EntryGuards, NULL),
282 VAR("EntryGuardUnlistedSince", LINELIST_S, EntryGuards, NULL),
283 VAR("EntryGuards", LINELIST_V, EntryGuards, NULL),
285 VAR("BWHistoryReadEnds", ISOTIME, BWHistoryReadEnds, NULL),
286 VAR("BWHistoryReadInterval", UINT, BWHistoryReadInterval, "900"),
287 VAR("BWHistoryReadValues", CSV, BWHistoryReadValues, ""),
288 VAR("BWHistoryWriteEnds", ISOTIME, BWHistoryWriteEnds, NULL),
289 VAR("BWHistoryWriteInterval", UINT, BWHistoryWriteInterval, "900"),
290 VAR("BWHistoryWriteValues", CSV, BWHistoryWriteValues, ""),
292 VAR("TorVersion", STRING, TorVersion, NULL),
294 VAR("LastRotatedOnionKey", ISOTIME, LastRotatedOnionKey, NULL),
295 VAR("LastWritten", ISOTIME, LastWritten, NULL),
297 { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
300 #undef VAR
301 #undef OBSOLETE
303 /** Represents an English description of a configuration variable; used when
304 * generating configuration file comments. */
305 typedef struct config_var_description_t {
306 const char *name;
307 const char *description;
308 } config_var_description_t;
310 static config_var_description_t options_description[] = {
311 /* ==== general options */
312 { "AvoidDiskWrites", "If non-zero, try to write to disk less frequently than"
313 " we would otherwise." },
314 { "BandwidthRate", "A token bucket limits the average incoming bandwidth on "
315 "this node to the specified number of bytes per second." },
316 { "BandwidthBurst", "Limit the maximum token buffer size (also known as "
317 "burst) to the given number of bytes." },
318 { "ConnLimit", "Maximum number of simultaneous sockets allowed." },
319 /* ControlListenAddress */
320 { "ControlPort", "If set, Tor will accept connections from the same machine "
321 "(localhost only) on this port, and allow those connections to control "
322 "the Tor process using the Tor Control Protocol (described in"
323 "control-spec.txt).", },
324 { "CookieAuthentication", "If this option is set to 1, don't allow any "
325 "connections to the control port except when the connecting process "
326 "can read a file that Tor creates in its data directory." },
327 { "DataDirectory", "Store working data, state, keys, and caches here." },
328 { "DirServer", "Tor only trusts directories signed with one of these "
329 "servers' keys. Used to override the standard list of directory "
330 "authorities." },
331 /* { "FastFirstHopPK", "" }, */
332 /* FetchServerDescriptors, FetchHidServDescriptors,
333 * FetchUselessDescriptors */
334 { "Group", "On startup, setgid to this group." },
335 { "HardwareAccel", "If set, Tor tries to use hardware crypto accelerators "
336 "when it can." },
337 /* HashedControlPassword */
338 { "HTTPProxy", "Force Tor to make all HTTP directory requests through this "
339 "host:port (or host:80 if port is not set)." },
340 { "HTTPProxyAuthenticator", "A username:password pair to be used with "
341 "HTTPProxy." },
342 { "HTTPSProxy", "Force Tor to make all TLS (SSL) connectinos through this "
343 "host:port (or host:80 if port is not set)." },
344 { "HTTPSProxyAuthenticator", "A username:password pair to be used with "
345 "HTTPSProxy." },
346 { "KeepalivePeriod", "Send a padding cell every N seconds to keep firewalls "
347 "from closing our connections while Tor is not in use." },
348 { "Log", "Where to send logging messages. Format is "
349 "minSeverity[-maxSeverity] (stderr|stdout|syslog|file FILENAME)." },
350 { "OutboundBindAddress", "Make all outbound connections originate from the "
351 "provided IP address (only useful for multiple network interfaces)." },
352 { "PIDFile", "On startup, write our PID to this file. On clean shutdown, "
353 "remove the file." },
354 { "PreferTunneledDirConns", "If non-zero, avoid directory servers that "
355 "don't support tunneled conncetions." },
356 /* PreferTunneledDirConns */
357 /* ProtocolWarnings */
358 /* RephistTrackTime */
359 { "RunAsDaemon", "If set, Tor forks and daemonizes to the background when "
360 "started. Unix only." },
361 { "SafeLogging", "If set to 0, Tor logs potentially sensitive strings "
362 "rather than replacing them with the string [scrubbed]." },
363 { "TunnelDirConns", "If non-zero, when a directory server we contact "
364 "supports it, we will build a one-hop circuit and make an encrypted "
365 "connection via its ORPort." },
366 { "User", "On startup, setuid to this user" },
368 /* ==== client options */
369 { "AllowInvalidNodes", "Where on our circuits should Tor allow servers "
370 "that the directory authorities haven't called \"valid\"?" },
371 { "AllowNonRFC953Hostnames", "If set to 1, we don't automatically reject "
372 "hostnames for having invalid characters." },
373 /* CircuitBuildTimeout, CircuitIdleTimeout */
374 { "ClientOnly", "If set to 1, Tor will under no circumstances run as a "
375 "server, even if ORPort is enabled." },
376 { "EntryNodes", "A list of preferred entry nodes to use for the first hop "
377 "in circuits, when possible." },
378 /* { "EnforceDistinctSubnets" , "" }, */
379 { "ExitNodes", "A list of preferred nodes to use for the last hop in "
380 "circuits, when possible." },
381 { "ExcludeNodes", "A list of nodes never to use when building a circuit." },
382 { "FascistFirewall", "If set, Tor will only create outgoing connections to "
383 "servers running on the ports listed in FirewallPorts." },
384 { "FirewallPorts", "A list of ports that we can connect to. Only used "
385 "when FascistFirewall is set." },
386 { "LongLivedPorts", "A list of ports for services that tend to require "
387 "high-uptime connections." },
388 { "MapAddress", "Force Tor to treat all requests for one address as if "
389 "they were for another." },
390 { "NewCircuitPeriod", "Force Tor to consider whether to build a new circuit "
391 "every NUM seconds." },
392 { "MaxCircuitDirtiness", "Do not attach new streams to a circuit that has "
393 "been used more than this many seconds ago." },
394 /* NatdPort, NatdListenAddress */
395 { "NodeFamily", "A list of servers that constitute a 'family' and should "
396 "never be used in the same circuit." },
397 { "NumEntryGuards", "How many entry guards should we keep at a time?" },
398 /* PathlenCoinWeight */
399 { "ReachableAddresses", "Addresses we can connect to, as IP/bits:port-port. "
400 "By default, we assume all addresses are reachable." },
401 /* reachablediraddresses, reachableoraddresses. */
402 { "RendNodes", "A list of preferred nodes to use for a rendezvous point, "
403 "when possible." },
404 { "RendExcludenodes", "A list of nodes never to use as rendezvous points." },
405 /* SafeSOCKS */
406 { "SOCKSPort", "The port where we listen for SOCKS connections from "
407 "applications." },
408 { "SOCKSListenAddress", "Bind to this address to listen to connections from "
409 "SOCKS-speaking applications." },
410 { "SOCKSPolicy", "Set an entry policy to limit which addresses can connect "
411 "to the SOCKSPort." },
412 /* SocksTimeout */
413 { "StrictExitNodes", "If set, Tor will fail to operate when none of the "
414 "configured ExitNodes can be used." },
415 { "StrictEntryNodes", "If set, Tor will fail to operate when none of the "
416 "configured EntryNodes can be used." },
417 /* TestSocks */
418 { "TrackHostsExit", "Hosts and domains which should, if possible, be "
419 "accessed from the same exit node each time we connect to them." },
420 { "TrackHostsExitExpire", "Time after which we forget which exit we were "
421 "using to connect to hosts in TrackHostsExit." },
422 /* "TransPort", "TransListenAddress */
423 { "UseEntryGuards", "Set to 0 if we want to pick from the whole set of "
424 "servers for the first position in each circuit, rather than picking a "
425 "set of 'Guards' to prevent profiling attacks." },
427 /* === server options */
428 { "Address", "The advertised (external) address we should use." },
429 /* Accounting* options. */
430 /* AssumeReachable */
431 { "ContactInfo", "Administrative contact information to advertise for this "
432 "server." },
433 { "ExitPolicy", "Address/port ranges for which to accept or reject outgoing "
434 "connections on behalf of Tor users." },
435 /* { "ExitPolicyRejectPrivate, "" }, */
436 { "MaxAdvertisedBandwidth", "If set, we will not advertise more than this "
437 "amount of bandwidth for our bandwidth rate, regardless of how much "
438 "bandwidth we actually detect." },
439 { "MaxOnionsPending", "Reject new attempts to extend circuits when we "
440 "already have this many pending." },
441 { "MyFamily", "Declare a list of other servers as belonging to the same "
442 "family as this one, so that clients will not use two from the same "
443 "family in the same circuit." },
444 { "Nickname", "Set the server nickname." },
445 { "NoPublish", "{DEPRECATED}" },
446 { "NumCPUs", "How many processes to use at once for public-key crypto." },
447 { "ORPort", "Advertise this port to listen for connections from Tor clients "
448 "and servers." },
449 { "ORListenAddress", "Bind to this address to listen for connections from "
450 "clients and servers, instead of the default 0.0.0.0:ORPort." },
451 { "PublishServerDescriptors", "Set to 0 in order to keep the server from "
452 "uploading info to the directory authorities." },
453 /*{ "RedirectExit", "When an outgoing connection tries to connect to a "
454 *"given address, redirect it to another address instead." },
456 /* ServerDNS: DetectHijacking, ResolvConfFile, SearchDomains */
457 { "ShutdownWaitLength", "Wait this long for clients to finish when "
458 "shutting down because of a SIGINT." },
459 /* { "TestVia", } */
461 /* === directory cache options */
462 { "DirPort", "Serve directory information from this port, and act as a "
463 "directory cache." },
464 { "DirListenAddress", "Bind to this address to listen for connections from "
465 "clients and servers, instead of the default 0.0.0.0:DirPort." },
466 { "DirPolicy", "Set a policy to limit who can connect to the directory "
467 "port" },
469 /* Authority options: AuthDirBadExit, AuthDirInvalid, AuthDirReject,
470 * AuthDirRejectUnlisted, AuthDirListBadExits, AuthoritativeDirectory,
471 * DirAllowPrivateAddresses, HSAuthoritativeDir,
472 * NamingAuthoritativeDirectory, RecommendedVersions,
473 * RecommendedClientVersions, RecommendedServerVersions, RendPostPeriod,
474 * RunTesting, V1AuthoritativeDirectory, VersioningAuthoritativeDirectory, */
476 /* Hidden service options: HiddenService: dir,excludenodes, nodes,
477 * options, port. PublishHidServDescriptor */
479 /* Nonpersistent options: __LeaveStreamsUnattached, __AllDirActionsPrivate */
480 { NULL, NULL },
483 static config_var_description_t state_description[] = {
484 { "AccountingBytesReadInInterval",
485 "How many bytes have we read in this accounting period?" },
486 { "AccountingBytesWrittenInInterval",
487 "How many bytes have we written in this accounting period?" },
488 { "AccountingExpectedUsage",
489 "How many bytes did we expect to use per minute? (0 for no estimate.)" },
490 { "AccountingIntervalStart", "When did this accounting period begin?" },
491 { "AccountingSecondsActive", "How long have we been awake in this period?" },
493 { "BWHistoryReadEnds", "When does the last-recorded read-interval end?" },
494 { "BWHistoryReadInterval", "How long is each read-interval (in seconds)?" },
495 { "BWHistoryReadValues", "Number of bytes read in each interval." },
496 { "BWHistoryWriteEnds", "When does the last-recorded write-interval end?" },
497 { "BWHistoryWriteInterval", "How long is each write-interval (in seconds)?"},
498 { "BWHistoryWriteValues", "Number of bytes written in each interval." },
500 { "EntryGuard", "One of the nodes we have chosen as a fixed entry" },
501 { "EntryGuardDownSince",
502 "The last entry guard has been unreachable since this time." },
503 { "EntryGuardUnlistedSince",
504 "The last entry guard has been unusable since this time." },
505 { "LastRotatedOnionKey",
506 "The last time at which we changed the medium-term private key used for "
507 "building circuits." },
508 { "LastWritten", "When was this state file last regenerated?" },
510 { "TorVersion", "Which version of Tor generated this state file?" },
511 { NULL, NULL },
514 typedef int (*validate_fn_t)(void*,void*,int,char**);
516 /** Information on the keys, value types, key-to-struct-member mappings,
517 * variable descriptions, validation functions, and abbreviations for a
518 * configuration or storage format. */
519 typedef struct {
520 size_t size;
521 uint32_t magic;
522 off_t magic_offset;
523 config_abbrev_t *abbrevs;
524 config_var_t *vars;
525 validate_fn_t validate_fn;
526 config_var_description_t *descriptions;
527 /** If present, extra is a LINELIST variable for unrecognized
528 * lines. Otherwise, unrecognized lines are an error. */
529 config_var_t *extra;
530 } config_format_t;
532 #define CHECK(fmt, cfg) do { \
533 tor_assert(fmt && cfg); \
534 tor_assert((fmt)->magic == \
535 *(uint32_t*)STRUCT_VAR_P(cfg,fmt->magic_offset)); \
536 } while (0)
538 static void config_line_append(config_line_t **lst,
539 const char *key, const char *val);
540 static void option_clear(config_format_t *fmt, or_options_t *options,
541 config_var_t *var);
542 static void option_reset(config_format_t *fmt, or_options_t *options,
543 config_var_t *var, int use_defaults);
544 static void config_free(config_format_t *fmt, void *options);
545 static int option_is_same(config_format_t *fmt,
546 or_options_t *o1, or_options_t *o2,
547 const char *name);
548 static or_options_t *options_dup(config_format_t *fmt, or_options_t *old);
549 static int options_validate(or_options_t *old_options, or_options_t *options,
550 int from_setconf, char **msg);
551 static int options_act_reversible(or_options_t *old_options, char **msg);
552 static int options_act(or_options_t *old_options);
553 static int options_transition_allowed(or_options_t *old, or_options_t *new,
554 char **msg);
555 static int options_transition_affects_workers(or_options_t *old_options,
556 or_options_t *new_options);
557 static int options_transition_affects_descriptor(or_options_t *old_options,
558 or_options_t *new_options);
559 static int check_nickname_list(const char *lst, const char *name, char **msg);
560 static void config_register_addressmaps(or_options_t *options);
562 static int parse_dir_server_line(const char *line, int validate_only);
563 static int parse_redirect_line(smartlist_t *result,
564 config_line_t *line, char **msg);
565 static int parse_log_severity_range(const char *range, int *min_out,
566 int *max_out);
567 static int validate_data_directory(or_options_t *options);
568 static int write_configuration_file(const char *fname, or_options_t *options);
569 static config_line_t *get_assigned_option(config_format_t *fmt,
570 or_options_t *options, const char *key);
571 static void config_init(config_format_t *fmt, void *options);
572 static int or_state_validate(or_state_t *old_options, or_state_t *options,
573 int from_setconf, char **msg);
575 static uint64_t config_parse_memunit(const char *s, int *ok);
576 static int config_parse_interval(const char *s, int *ok);
577 static void print_svn_version(void);
578 static void init_libevent(void);
579 static int opt_streq(const char *s1, const char *s2);
580 /** Versions of libevent. */
581 typedef enum {
582 /* Note: we compare these, so it's important that "old" precede everything,
583 * and that "other" come last. */
584 LE_OLD=0, LE_10C, LE_10D, LE_10E, LE_11, LE_11A, LE_11B, LE_12, LE_12A,
585 LE_OTHER
586 } le_version_t;
587 static le_version_t decode_libevent_version(void);
588 #if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
589 static void check_libevent_version(const char *m, int server);
590 #endif
592 /*static*/ or_options_t *options_new(void);
594 #define OR_OPTIONS_MAGIC 9090909
596 static config_format_t options_format = {
597 sizeof(or_options_t),
598 OR_OPTIONS_MAGIC,
599 STRUCT_OFFSET(or_options_t, _magic),
600 _option_abbrevs,
601 _option_vars,
602 (validate_fn_t)options_validate,
603 options_description,
604 NULL
607 #define OR_STATE_MAGIC 0x57A73f57
609 static config_var_t state_extra_var = {
610 "__extra", CONFIG_TYPE_LINELIST, STRUCT_OFFSET(or_state_t, ExtraLines), NULL
613 static config_format_t state_format = {
614 sizeof(or_state_t),
615 OR_STATE_MAGIC,
616 STRUCT_OFFSET(or_state_t, _magic),
617 _state_abbrevs,
618 _state_vars,
619 (validate_fn_t)or_state_validate,
620 state_description,
621 &state_extra_var,
625 * Functions to read and write the global options pointer.
628 /** Command-line and config-file options. */
629 static or_options_t *global_options = NULL;
630 /** Name of most recently read torrc file. */
631 static char *torrc_fname = NULL;
632 /** Persistent serialized state. */
633 static or_state_t *global_state = NULL;
635 /** Allocate an empty configuration object of a given format type. */
636 static void *
637 config_alloc(config_format_t *fmt)
639 void *opts = tor_malloc_zero(fmt->size);
640 *(uint32_t*)STRUCT_VAR_P(opts, fmt->magic_offset) = fmt->magic;
641 CHECK(fmt, opts);
642 return opts;
645 /** Return the currently configured options. */
646 or_options_t *
647 get_options(void)
649 tor_assert(global_options);
650 return global_options;
653 /** Change the current global options to contain <b>new_val</b> instead of
654 * their current value; take action based on the new value; free the old value
655 * as necessary.
658 set_options(or_options_t *new_val, char **msg)
660 or_options_t *old_options = global_options;
661 global_options = new_val;
662 /* Note that we pass the *old* options below, for comparison. It
663 * pulls the new options directly out of global_options. */
664 if (options_act_reversible(old_options, msg)<0) {
665 tor_assert(*msg);
666 global_options = old_options;
667 return -1;
669 if (options_act(old_options) < 0) { /* acting on the options failed. die. */
670 log_err(LD_BUG,
671 "Acting on config options left us in a broken state. Dying.");
672 exit(1);
674 if (old_options)
675 config_free(&options_format, old_options);
677 return 0;
680 /** Release all memory and resources held by global configuration structures.
682 void
683 config_free_all(void)
685 if (global_options) {
686 config_free(&options_format, global_options);
687 global_options = NULL;
689 if (global_state) {
690 config_free(&state_format, global_state);
691 global_state = NULL;
693 tor_free(torrc_fname);
696 /** If options->SafeLogging is on, return a not very useful string,
697 * else return address.
699 const char *
700 safe_str(const char *address)
702 if (get_options()->SafeLogging)
703 return "[scrubbed]";
704 else
705 return address;
708 /** Equivalent to escaped(safe_str(address)). See reentrancy note on
709 * escaped(): don't use this outside the main thread, or twice in the same
710 * log statement. */
711 const char *
712 escaped_safe_str(const char *address)
714 if (get_options()->SafeLogging)
715 return "[scrubbed]";
716 else
717 return escaped(address);
720 /** Add the default directory servers directly into the trusted dir list. */
721 static void
722 add_default_trusted_dirservers(void)
724 int i;
725 const char *dirservers[] = {
726 /* eventually we should mark moria1 as "v1only" */
727 "moria1 v1 orport=9001 18.244.0.188:9031 "
728 "FFCB 46DB 1339 DA84 674C 70D7 CB58 6434 C437 0441",
729 "moria2 v1 orport=443 18.244.0.114:80 "
730 "719B E45D E224 B607 C537 07D0 E214 3E2D 423E 74CF",
731 "tor26 v1 orport=443 86.59.21.38:80 "
732 "847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D",
733 "lefkada orport=443 140.247.60.64:80 "
734 "38D4 F5FC F7B1 0232 28B8 95EA 56ED E7D5 CCDC AF32",
735 "dizum 194.109.206.212:80 "
736 "7EA6 EAD6 FD83 083C 538F 4403 8BBF A077 587D D755",
737 NULL
739 for (i=0; dirservers[i]; i++)
740 parse_dir_server_line(dirservers[i], 0);
743 /** Fetch the active option list, and take actions based on it. All of the
744 * things we do should survive being done repeatedly. If present,
745 * <b>old_options</b> contains the previous value of the options.
747 * Return 0 if all goes well, return -1 if things went badly.
749 static int
750 options_act_reversible(or_options_t *old_options, char **msg)
752 smartlist_t *new_listeners = smartlist_create();
753 smartlist_t *replaced_listeners = smartlist_create();
754 static int libevent_initialized = 0;
755 or_options_t *options = get_options();
756 int running_tor = options->command == CMD_RUN_TOR;
757 int set_conn_limit = 0;
758 int r = -1;
759 int logs_marked = 0;
761 if (running_tor && options->RunAsDaemon) {
762 /* No need to roll back, since you can't change the value. */
763 start_daemon();
766 /* Setuid/setgid as appropriate */
767 if (options->User || options->Group) {
768 if (switch_id(options->User, options->Group) != 0) {
769 /* No need to roll back, since you can't change the value. */
770 *msg = tor_strdup("Problem with User or Group value. "
771 "See logs for details.");
772 goto done;
776 /* Set up libevent. */
777 if (running_tor && !libevent_initialized) {
778 init_libevent();
779 libevent_initialized = 1;
782 /* Ensure data directory is private; create if possible. */
783 if (check_private_dir(options->DataDirectory, CPD_CREATE)<0) {
784 char buf[1024];
785 int tmp = tor_snprintf(buf, sizeof(buf),
786 "Couldn't access/create private data directory \"%s\"",
787 options->DataDirectory);
788 *msg = tor_strdup(tmp >= 0 ? buf : "internal error");
789 goto done;
790 /* No need to roll back, since you can't change the value. */
793 /* Bail out at this point if we're not going to be a client or server:
794 * we don't run Tor itself. */
795 if (options->command != CMD_RUN_TOR)
796 goto commit;
798 options->_ConnLimit =
799 set_max_file_descriptors((unsigned)options->ConnLimit, MAXCONNECTIONS);
800 if (options->_ConnLimit < 0) {
801 *msg = tor_strdup("Problem with ConnLimit value. See logs for details.");
802 goto rollback;
804 set_conn_limit = 1;
806 if (retry_all_listeners(0, replaced_listeners, new_listeners) < 0) {
807 *msg = tor_strdup("Failed to bind one of the listener ports.");
808 goto rollback;
811 mark_logs_temp(); /* Close current logs once new logs are open. */
812 logs_marked = 1;
813 if (options_init_logs(options, 0)<0) { /* Configure the log(s) */
814 *msg = tor_strdup("Failed to init Log options. See logs for details.");
815 goto rollback;
818 commit:
819 r = 0;
820 if (logs_marked) {
821 close_temp_logs();
822 add_callback_log(LOG_ERR, LOG_ERR, control_event_logmsg);
823 control_adjust_event_log_severity();
825 SMARTLIST_FOREACH(replaced_listeners, connection_t *, conn,
827 log_notice(LD_NET, "Closing old %s on %s:%d",
828 conn_type_to_string(conn->type), conn->address, conn->port);
829 connection_close_immediate(conn);
830 connection_mark_for_close(conn);
832 goto done;
834 rollback:
835 r = -1;
836 tor_assert(*msg);
838 if (logs_marked) {
839 rollback_log_changes();
840 control_adjust_event_log_severity();
843 if (set_conn_limit && old_options)
844 set_max_file_descriptors((unsigned)old_options->ConnLimit,MAXCONNECTIONS);
846 SMARTLIST_FOREACH(new_listeners, connection_t *, conn,
848 log_notice(LD_NET, "Closing partially-constructed listener %s on %s:%d",
849 conn_type_to_string(conn->type), conn->address, conn->port);
850 connection_close_immediate(conn);
851 connection_mark_for_close(conn);
854 done:
855 smartlist_free(new_listeners);
856 smartlist_free(replaced_listeners);
857 return r;
860 /** Fetch the active option list, and take actions based on it. All of the
861 * things we do should survive being done repeatedly. If present,
862 * <b>old_options</b> contains the previous value of the options.
864 * Return 0 if all goes well, return -1 if it's time to die.
866 * Note: We haven't moved all the "act on new configuration" logic
867 * here yet. Some is still in do_hup() and other places.
869 static int
870 options_act(or_options_t *old_options)
872 config_line_t *cl;
873 char *fn;
874 size_t len;
875 or_options_t *options = get_options();
876 int running_tor = options->command == CMD_RUN_TOR;
877 char *msg;
879 clear_trusted_dir_servers();
880 if (options->DirServers) {
881 for (cl = options->DirServers; cl; cl = cl->next) {
882 if (parse_dir_server_line(cl->value, 0)<0) {
883 log_err(LD_BUG,
884 "Bug: Previously validated DirServer line could not be added!");
885 return -1;
888 } else {
889 add_default_trusted_dirservers();
892 if (running_tor && rend_config_services(options, 0)<0) {
893 log_err(LD_BUG,
894 "Bug: Previously validated hidden services line could not be added!");
895 return -1;
898 if (running_tor) {
899 len = strlen(options->DataDirectory)+32;
900 fn = tor_malloc(len);
901 tor_snprintf(fn, len, "%s/cached-status", options->DataDirectory);
902 if (check_private_dir(fn, CPD_CREATE) != 0) {
903 log_err(LD_CONFIG,
904 "Couldn't access/create private data directory \"%s\"", fn);
905 tor_free(fn);
906 return -1;
908 tor_free(fn);
911 /* Load state */
912 if (! global_state)
913 if (or_state_load())
914 return -1;
916 /* Bail out at this point if we're not going to be a client or server:
917 * we want to not fork, and to log stuff to stderr. */
918 if (options->command != CMD_RUN_TOR)
919 return 0;
922 smartlist_t *sl = smartlist_create();
923 char *errmsg = NULL;
924 for (cl = options->RedirectExit; cl; cl = cl->next) {
925 if (parse_redirect_line(sl, cl, &errmsg)<0) {
926 log_warn(LD_CONFIG, "%s", errmsg);
927 tor_free(errmsg);
928 return -1;
931 set_exit_redirects(sl);
934 /* Finish backgrounding the process */
935 if (running_tor && options->RunAsDaemon) {
936 /* We may be calling this for the n'th time (on SIGHUP), but it's safe. */
937 finish_daemon(options->DataDirectory);
940 /* Write our pid to the pid file. If we do not have write permissions we
941 * will log a warning */
942 if (running_tor && options->PidFile)
943 write_pidfile(options->PidFile);
945 /* Register addressmap directives */
946 config_register_addressmaps(options);
947 parse_virtual_addr_network(options->VirtualAddrNetwork, 0, &msg);
949 /* Update address policies. */
950 policies_parse_from_options(options);
952 init_cookie_authentication(options->CookieAuthentication);
954 /* reload keys as needed for rendezvous services. */
955 if (rend_service_load_keys()<0) {
956 log_err(LD_GENERAL,"Error loading rendezvous service keys");
957 return -1;
960 /* Set up accounting */
961 if (accounting_parse_options(options, 0)<0) {
962 log_err(LD_CONFIG,"Error in accounting options");
963 return -1;
965 if (accounting_is_enabled(options))
966 configure_accounting(time(NULL));
968 if (!running_tor)
969 return 0;
971 /* Check for transitions that need action. */
972 if (old_options) {
973 if (options->UseEntryGuards && !old_options->UseEntryGuards) {
974 log_info(LD_CIRC,
975 "Switching to entry guards; abandoning previous circuits");
976 circuit_mark_all_unused_circs();
977 circuit_expire_all_dirty_circs();
980 if (options_transition_affects_workers(old_options, options)) {
981 log_info(LD_GENERAL,
982 "Worker-related options changed. Rotating workers.");
983 if (server_mode(options) && !server_mode(old_options)) {
984 if (init_keys() < 0) {
985 log_err(LD_BUG,"Error initializing keys; exiting");
986 return -1;
988 ip_address_changed(0);
989 if (has_completed_circuit || !any_predicted_circuits(time(NULL)))
990 inform_testing_reachability();
992 cpuworkers_rotate();
993 if (dns_reset())
994 return -1;
996 #ifdef USE_EVENTDNS
997 else {
998 if (dns_reset())
999 return -1;
1001 #endif
1004 /* Check if we need to parse and add the EntryNodes config option. */
1005 if (options->EntryNodes &&
1006 (!old_options ||
1007 !opt_streq(old_options->EntryNodes, options->EntryNodes)))
1008 entry_nodes_should_be_added();
1010 /* Since our options changed, we might need to regenerate and upload our
1011 * server descriptor.
1013 if (!old_options ||
1014 options_transition_affects_descriptor(old_options, options))
1015 mark_my_descriptor_dirty();
1017 return 0;
1021 * Functions to parse config options
1024 /** If <b>option</b> is an official abbreviation for a longer option,
1025 * return the longer option. Otherwise return <b>option</b>.
1026 * If <b>command_line</b> is set, apply all abbreviations. Otherwise, only
1027 * apply abbreviations that work for the config file and the command line.
1028 * If <b>warn_obsolete</b> is set, warn about deprecated names. */
1029 static const char *
1030 expand_abbrev(config_format_t *fmt, const char *option, int command_line,
1031 int warn_obsolete)
1033 int i;
1034 if (! fmt->abbrevs)
1035 return option;
1036 for (i=0; fmt->abbrevs[i].abbreviated; ++i) {
1037 /* Abbreviations are casei. */
1038 if (!strcasecmp(option,fmt->abbrevs[i].abbreviated) &&
1039 (command_line || !fmt->abbrevs[i].commandline_only)) {
1040 if (warn_obsolete && fmt->abbrevs[i].warn) {
1041 log_warn(LD_CONFIG,
1042 "The configuration option '%s' is deprecated; "
1043 "use '%s' instead.",
1044 fmt->abbrevs[i].abbreviated,
1045 fmt->abbrevs[i].full);
1047 return fmt->abbrevs[i].full;
1050 return option;
1053 /** Helper: Read a list of configuration options from the command line.
1054 * If successful, put them in *<b>result</b> and return 0, and return
1055 * -1 and leave *<b>result</b> alone. */
1056 static int
1057 config_get_commandlines(int argc, char **argv, config_line_t **result)
1059 config_line_t *front = NULL;
1060 config_line_t **new = &front;
1061 char *s;
1062 int i = 1;
1064 while (i < argc) {
1065 if (!strcmp(argv[i],"-f") ||
1066 !strcmp(argv[i],"--hash-password")) {
1067 i += 2; /* command-line option with argument. ignore them. */
1068 continue;
1069 } else if (!strcmp(argv[i],"--list-fingerprint") ||
1070 !strcmp(argv[i],"--verify-config")) {
1071 i += 1; /* command-line option. ignore it. */
1072 continue;
1073 } else if (!strcmp(argv[i],"--nt-service") ||
1074 !strcmp(argv[i],"-nt-service")) {
1075 i += 1;
1076 continue;
1078 if (i == argc-1) {
1079 log_warn(LD_CONFIG,"Command-line option '%s' with no value. Failing.",
1080 argv[i]);
1081 config_free_lines(front);
1082 return -1;
1085 *new = tor_malloc_zero(sizeof(config_line_t));
1086 s = argv[i];
1088 while (*s == '-')
1089 s++;
1091 (*new)->key = tor_strdup(expand_abbrev(&options_format, s, 1, 1));
1092 (*new)->value = tor_strdup(argv[i+1]);
1093 (*new)->next = NULL;
1094 log(LOG_DEBUG, LD_CONFIG, "Commandline: parsed keyword '%s', value '%s'",
1095 (*new)->key, (*new)->value);
1097 new = &((*new)->next);
1098 i += 2;
1100 *result = front;
1101 return 0;
1104 /** Helper: allocate a new configuration option mapping 'key' to 'val',
1105 * append it to *<b>lst</b>. */
1106 static void
1107 config_line_append(config_line_t **lst,
1108 const char *key,
1109 const char *val)
1111 config_line_t *newline;
1113 newline = tor_malloc(sizeof(config_line_t));
1114 newline->key = tor_strdup(key);
1115 newline->value = tor_strdup(val);
1116 newline->next = NULL;
1117 while (*lst)
1118 lst = &((*lst)->next);
1120 (*lst) = newline;
1123 /** Helper: parse the config string and strdup into key/value
1124 * strings. Set *result to the list, or NULL if parsing the string
1125 * failed. Return 0 on success, -1 on failure. Warn and ignore any
1126 * misformatted lines. Modifies the contents of <b>string</b>. */
1128 config_get_lines(char *string, config_line_t **result)
1130 config_line_t *list = NULL, **next;
1131 char *k, *v;
1133 next = &list;
1134 do {
1135 string = parse_line_from_str(string, &k, &v);
1136 if (!string) {
1137 config_free_lines(list);
1138 return -1;
1140 if (k && v) {
1141 /* This list can get long, so we keep a pointer to the end of it
1142 * rather than using config_line_append over and over and getting n^2
1143 * performance. This is the only really long list. */
1144 *next = tor_malloc(sizeof(config_line_t));
1145 (*next)->key = tor_strdup(k);
1146 (*next)->value = tor_strdup(v);
1147 (*next)->next = NULL;
1148 next = &((*next)->next);
1150 } while (*string);
1152 *result = list;
1153 return 0;
1157 * Free all the configuration lines on the linked list <b>front</b>.
1159 void
1160 config_free_lines(config_line_t *front)
1162 config_line_t *tmp;
1164 while (front) {
1165 tmp = front;
1166 front = tmp->next;
1168 tor_free(tmp->key);
1169 tor_free(tmp->value);
1170 tor_free(tmp);
1174 /** Return the description for a given configuration variable, or NULL if no
1175 * description exists. */
1176 static const char *
1177 config_find_description(config_format_t *fmt, const char *name)
1179 int i;
1180 for (i=0; fmt->descriptions[i].name; ++i) {
1181 if (!strcasecmp(name, fmt->descriptions[i].name))
1182 return fmt->descriptions[i].description;
1184 return NULL;
1187 /** If <b>key</b> is a configuration option, return the corresponding
1188 * config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation,
1189 * warn, and return the corresponding config_var_t. Otherwise return NULL.
1191 static config_var_t *
1192 config_find_option(config_format_t *fmt, const char *key)
1194 int i;
1195 size_t keylen = strlen(key);
1196 if (!keylen)
1197 return NULL; /* if they say "--" on the commandline, it's not an option */
1198 /* First, check for an exact (case-insensitive) match */
1199 for (i=0; fmt->vars[i].name; ++i) {
1200 if (!strcasecmp(key, fmt->vars[i].name)) {
1201 return &fmt->vars[i];
1204 /* If none, check for an abbreviated match */
1205 for (i=0; fmt->vars[i].name; ++i) {
1206 if (!strncasecmp(key, fmt->vars[i].name, keylen)) {
1207 log_warn(LD_CONFIG, "The abbreviation '%s' is deprecated. "
1208 "Please use '%s' instead",
1209 key, fmt->vars[i].name);
1210 return &fmt->vars[i];
1213 /* Okay, unrecognized option */
1214 return NULL;
1218 * Functions to assign config options.
1221 /** <b>c</b>-\>key is known to be a real key. Update <b>options</b>
1222 * with <b>c</b>-\>value and return 0, or return -1 if bad value.
1224 * Called from config_assign_line() and option_reset().
1226 static int
1227 config_assign_value(config_format_t *fmt, or_options_t *options,
1228 config_line_t *c, char **msg)
1230 int i, r, ok;
1231 char buf[1024];
1232 config_var_t *var;
1233 void *lvalue;
1235 CHECK(fmt, options);
1237 var = config_find_option(fmt, c->key);
1238 tor_assert(var);
1240 lvalue = STRUCT_VAR_P(options, var->var_offset);
1242 switch (var->type) {
1244 case CONFIG_TYPE_UINT:
1245 i = tor_parse_long(c->value, 10, 0, INT_MAX, &ok, NULL);
1246 if (!ok) {
1247 r = tor_snprintf(buf, sizeof(buf),
1248 "Int keyword '%s %s' is malformed or out of bounds.",
1249 c->key, c->value);
1250 *msg = tor_strdup(r >= 0 ? buf : "internal error");
1251 return -1;
1253 *(int *)lvalue = i;
1254 break;
1256 case CONFIG_TYPE_INTERVAL: {
1257 i = config_parse_interval(c->value, &ok);
1258 if (!ok) {
1259 r = tor_snprintf(buf, sizeof(buf),
1260 "Interval '%s %s' is malformed or out of bounds.",
1261 c->key, c->value);
1262 *msg = tor_strdup(r >= 0 ? buf : "internal error");
1263 return -1;
1265 *(int *)lvalue = i;
1266 break;
1269 case CONFIG_TYPE_MEMUNIT: {
1270 uint64_t u64 = config_parse_memunit(c->value, &ok);
1271 if (!ok) {
1272 r = tor_snprintf(buf, sizeof(buf),
1273 "Value '%s %s' is malformed or out of bounds.",
1274 c->key, c->value);
1275 *msg = tor_strdup(r >= 0 ? buf : "internal error");
1276 return -1;
1278 *(uint64_t *)lvalue = u64;
1279 break;
1282 case CONFIG_TYPE_BOOL:
1283 i = tor_parse_long(c->value, 10, 0, 1, &ok, NULL);
1284 if (!ok) {
1285 r = tor_snprintf(buf, sizeof(buf),
1286 "Boolean '%s %s' expects 0 or 1.",
1287 c->key, c->value);
1288 *msg = tor_strdup(r >= 0 ? buf : "internal error");
1289 return -1;
1291 *(int *)lvalue = i;
1292 break;
1294 case CONFIG_TYPE_STRING:
1295 tor_free(*(char **)lvalue);
1296 *(char **)lvalue = tor_strdup(c->value);
1297 break;
1299 case CONFIG_TYPE_DOUBLE:
1300 *(double *)lvalue = atof(c->value);
1301 break;
1303 case CONFIG_TYPE_ISOTIME:
1304 if (parse_iso_time(c->value, (time_t *)lvalue)) {
1305 r = tor_snprintf(buf, sizeof(buf),
1306 "Invalid time '%s' for keyword '%s'", c->value, c->key);
1307 *msg = tor_strdup(r >= 0 ? buf : "internal error");
1308 return -1;
1310 break;
1312 case CONFIG_TYPE_CSV:
1313 if (*(smartlist_t**)lvalue) {
1314 SMARTLIST_FOREACH(*(smartlist_t**)lvalue, char *, cp, tor_free(cp));
1315 smartlist_clear(*(smartlist_t**)lvalue);
1316 } else {
1317 *(smartlist_t**)lvalue = smartlist_create();
1320 smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",",
1321 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
1322 break;
1324 case CONFIG_TYPE_LINELIST:
1325 case CONFIG_TYPE_LINELIST_S:
1326 config_line_append((config_line_t**)lvalue, c->key, c->value);
1327 break;
1329 case CONFIG_TYPE_OBSOLETE:
1330 log_warn(LD_CONFIG, "Skipping obsolete configuration option '%s'", c->key);
1331 break;
1332 case CONFIG_TYPE_LINELIST_V:
1333 r = tor_snprintf(buf, sizeof(buf),
1334 "You may not provide a value for virtual option '%s'", c->key);
1335 *msg = tor_strdup(r >= 0 ? buf : "internal error");
1336 return -1;
1337 default:
1338 tor_assert(0);
1339 break;
1341 return 0;
1344 /** If <b>c</b> is a syntactically valid configuration line, update
1345 * <b>options</b> with its value and return 0. Otherwise return -1 for bad
1346 * key, -2 for bad value.
1348 * If <b>clear_first</b> is set, clear the value first. Then if
1349 * <b>use_defaults</b> is set, set the value to the default.
1351 * Called from config_assign().
1353 static int
1354 config_assign_line(config_format_t *fmt, or_options_t *options,
1355 config_line_t *c, int use_defaults,
1356 int clear_first, char **msg)
1358 config_var_t *var;
1360 CHECK(fmt, options);
1362 var = config_find_option(fmt, c->key);
1363 if (!var) {
1364 if (fmt->extra) {
1365 void *lvalue = STRUCT_VAR_P(options, fmt->extra->var_offset);
1366 log_info(LD_CONFIG,
1367 "Found unrecognized option '%s'; saving it.", c->key);
1368 config_line_append((config_line_t**)lvalue, c->key, c->value);
1369 return 0;
1370 } else {
1371 char buf[1024];
1372 int tmp = tor_snprintf(buf, sizeof(buf),
1373 "Unknown option '%s'. Failing.", c->key);
1374 *msg = tor_strdup(tmp >= 0 ? buf : "internal error");
1375 return -1;
1378 /* Put keyword into canonical case. */
1379 if (strcmp(var->name, c->key)) {
1380 tor_free(c->key);
1381 c->key = tor_strdup(var->name);
1384 if (!strlen(c->value)) {
1385 /* reset or clear it, then return */
1386 if (!clear_first) {
1387 if (var->type == CONFIG_TYPE_LINELIST ||
1388 var->type == CONFIG_TYPE_LINELIST_S) {
1389 /* We got an empty linelist from the torrc or commandline.
1390 As a special case, call this an error. Warn and ignore. */
1391 log_warn(LD_CONFIG,
1392 "Linelist option '%s' has no value. Skipping.", c->key);
1393 } else { /* not already cleared */
1394 option_reset(fmt, options, var, use_defaults);
1397 return 0;
1400 if (config_assign_value(fmt, options, c, msg) < 0)
1401 return -2;
1402 return 0;
1405 /** Restore the option named <b>key</b> in options to its default value.
1406 * Called from config_assign(). */
1407 static void
1408 config_reset_line(config_format_t *fmt, or_options_t *options,
1409 const char *key, int use_defaults)
1411 config_var_t *var;
1413 CHECK(fmt, options);
1415 var = config_find_option(fmt, key);
1416 if (!var)
1417 return; /* give error on next pass. */
1419 option_reset(fmt, options, var, use_defaults);
1422 /** Return true iff key is a valid configuration option. */
1424 option_is_recognized(const char *key)
1426 config_var_t *var = config_find_option(&options_format, key);
1427 return (var != NULL);
1430 /** Return the canonical name of a configuration option. */
1431 const char *
1432 option_get_canonical_name(const char *key)
1434 config_var_t *var = config_find_option(&options_format, key);
1435 return var->name;
1438 /** Return a canonicalized list of the options assigned for key.
1440 config_line_t *
1441 option_get_assignment(or_options_t *options, const char *key)
1443 return get_assigned_option(&options_format, options, key);
1446 static config_line_t *
1447 config_lines_dup(const config_line_t *inp)
1449 config_line_t *result = NULL;
1450 config_line_t **next_out = &result;
1451 while (inp) {
1452 *next_out = tor_malloc(sizeof(config_line_t));
1453 (*next_out)->key = tor_strdup(inp->key);
1454 (*next_out)->value = tor_strdup(inp->value);
1455 inp = inp->next;
1456 next_out = &((*next_out)->next);
1458 (*next_out) = NULL;
1459 return result;
1462 static config_line_t *
1463 get_assigned_option(config_format_t *fmt, or_options_t *options,
1464 const char *key)
1466 config_var_t *var;
1467 const void *value;
1468 char buf[32];
1469 config_line_t *result;
1470 tor_assert(options && key);
1472 CHECK(fmt, options);
1474 var = config_find_option(fmt, key);
1475 if (!var) {
1476 log_warn(LD_CONFIG, "Unknown option '%s'. Failing.", key);
1477 return NULL;
1479 value = STRUCT_VAR_P(options, var->var_offset);
1481 result = tor_malloc_zero(sizeof(config_line_t));
1482 result->key = tor_strdup(var->name);
1483 switch (var->type)
1485 case CONFIG_TYPE_STRING:
1486 if (*(char**)value) {
1487 result->value = tor_strdup(*(char**)value);
1488 } else {
1489 tor_free(result->key);
1490 tor_free(result);
1491 return NULL;
1493 break;
1494 case CONFIG_TYPE_ISOTIME:
1495 if (*(time_t*)value) {
1496 result->value = tor_malloc(ISO_TIME_LEN+1);
1497 format_iso_time(result->value, *(time_t*)value);
1498 } else {
1499 tor_free(result->key);
1500 tor_free(result);
1502 break;
1503 case CONFIG_TYPE_INTERVAL:
1504 case CONFIG_TYPE_UINT:
1505 /* This means every or_options_t uint or bool element
1506 * needs to be an int. Not, say, a uint16_t or char. */
1507 tor_snprintf(buf, sizeof(buf), "%d", *(int*)value);
1508 result->value = tor_strdup(buf);
1509 break;
1510 case CONFIG_TYPE_MEMUNIT:
1511 tor_snprintf(buf, sizeof(buf), U64_FORMAT,
1512 U64_PRINTF_ARG(*(uint64_t*)value));
1513 result->value = tor_strdup(buf);
1514 break;
1515 case CONFIG_TYPE_DOUBLE:
1516 tor_snprintf(buf, sizeof(buf), "%f", *(double*)value);
1517 result->value = tor_strdup(buf);
1518 break;
1519 case CONFIG_TYPE_BOOL:
1520 result->value = tor_strdup(*(int*)value ? "1" : "0");
1521 break;
1522 case CONFIG_TYPE_CSV:
1523 if (*(smartlist_t**)value)
1524 result->value =
1525 smartlist_join_strings(*(smartlist_t**)value, ",", 0, NULL);
1526 else
1527 result->value = tor_strdup("");
1528 break;
1529 case CONFIG_TYPE_OBSOLETE:
1530 log_warn(LD_CONFIG,
1531 "You asked me for the value of an obsolete config option '%s'.",
1532 key);
1533 tor_free(result->key);
1534 tor_free(result);
1535 return NULL;
1536 case CONFIG_TYPE_LINELIST_S:
1537 log_warn(LD_CONFIG,
1538 "Can't return context-sensitive '%s' on its own", key);
1539 tor_free(result->key);
1540 tor_free(result);
1541 return NULL;
1542 case CONFIG_TYPE_LINELIST:
1543 case CONFIG_TYPE_LINELIST_V:
1544 tor_free(result->key);
1545 tor_free(result);
1546 return config_lines_dup(*(const config_line_t**)value);
1547 default:
1548 tor_free(result->key);
1549 tor_free(result);
1550 log_warn(LD_BUG,"Bug: unknown type %d for known key '%s'",
1551 var->type, key);
1552 return NULL;
1555 return result;
1558 /** Iterate through the linked list of requested options <b>list</b>.
1559 * For each item, convert as appropriate and assign to <b>options</b>.
1560 * If an item is unrecognized, set *msg and return -1 immediately,
1561 * else return 0 for success.
1563 * If <b>clear_first</b>, interpret config options as replacing (not
1564 * extending) their previous values. If <b>clear_first</b> is set,
1565 * then <b>use_defaults</b> to decide if you set to defaults after
1566 * clearing, or make the value 0 or NULL.
1568 * Here are the use cases:
1569 * 1. A non-empty AllowInvalid line in your torrc. Appends to current
1570 * if linelist, replaces current if csv.
1571 * 2. An empty AllowInvalid line in your torrc. Should clear it.
1572 * 3. "RESETCONF AllowInvalid" sets it to default.
1573 * 4. "SETCONF AllowInvalid" makes it NULL.
1574 * 5. "SETCONF AllowInvalid=foo" clears it and sets it to "foo".
1576 * Use_defaults Clear_first
1577 * 0 0 "append"
1578 * 1 0 undefined, don't use
1579 * 0 1 "set to null first"
1580 * 1 1 "set to defaults first"
1581 * Return 0 on success, -1 on bad key, -2 on bad value.
1583 * As an additional special case, if a LINELIST config option has
1584 * no value and clear_first is 0, then warn and ignore it.
1588 There are three call cases for config_assign() currently.
1590 Case one: Torrc entry
1591 options_init_from_torrc() calls config_assign(0, 0)
1592 calls config_assign_line(0, 0).
1593 if value is empty, calls option_reset(0) and returns.
1594 calls config_assign_value(), appends.
1596 Case two: setconf
1597 options_trial_assign() calls config_assign(0, 1)
1598 calls config_reset_line(0)
1599 calls option_reset(0)
1600 calls option_clear().
1601 calls config_assign_line(0, 1).
1602 if value is empty, returns.
1603 calls config_assign_value(), appends.
1605 Case three: resetconf
1606 options_trial_assign() calls config_assign(1, 1)
1607 calls config_reset_line(1)
1608 calls option_reset(1)
1609 calls option_clear().
1610 calls config_assign_value(default)
1611 calls config_assign_line(1, 1).
1612 returns.
1614 static int
1615 config_assign(config_format_t *fmt, void *options, config_line_t *list,
1616 int use_defaults, int clear_first, char **msg)
1618 config_line_t *p;
1620 CHECK(fmt, options);
1622 /* pass 1: normalize keys */
1623 for (p = list; p; p = p->next) {
1624 const char *full = expand_abbrev(fmt, p->key, 0, 1);
1625 if (strcmp(full,p->key)) {
1626 tor_free(p->key);
1627 p->key = tor_strdup(full);
1631 /* pass 2: if we're reading from a resetting source, clear all
1632 * mentioned config options, and maybe set to their defaults. */
1633 if (clear_first) {
1634 for (p = list; p; p = p->next)
1635 config_reset_line(fmt, options, p->key, use_defaults);
1638 /* pass 3: assign. */
1639 while (list) {
1640 int r;
1641 if ((r=config_assign_line(fmt, options, list, use_defaults,
1642 clear_first, msg)))
1643 return r;
1644 list = list->next;
1646 return 0;
1649 /** Try assigning <b>list</b> to the global options. You do this by duping
1650 * options, assigning list to the new one, then validating it. If it's
1651 * ok, then throw out the old one and stick with the new one. Else,
1652 * revert to old and return failure. Return 0 on success, -1 on bad
1653 * keys, -2 on bad values, -3 on bad transition, and -4 on failed-to-set.
1655 * If not success, point *<b>msg</b> to a newly allocated string describing
1656 * what went wrong.
1659 options_trial_assign(config_line_t *list, int use_defaults,
1660 int clear_first, char **msg)
1662 int r;
1663 or_options_t *trial_options = options_dup(&options_format, get_options());
1665 if ((r=config_assign(&options_format, trial_options,
1666 list, use_defaults, clear_first, msg)) < 0) {
1667 config_free(&options_format, trial_options);
1668 return r;
1671 if (options_validate(get_options(), trial_options, 1, msg) < 0) {
1672 config_free(&options_format, trial_options);
1673 return -2;
1676 if (options_transition_allowed(get_options(), trial_options, msg) < 0) {
1677 config_free(&options_format, trial_options);
1678 return -3;
1681 if (set_options(trial_options, msg)<0) {
1682 config_free(&options_format, trial_options);
1683 return -4;
1686 /* we liked it. put it in place. */
1687 return 0;
1690 /** Reset config option <b>var</b> to 0, 0.0, NULL, or the equivalent.
1691 * Called from option_reset() and config_free(). */
1692 static void
1693 option_clear(config_format_t *fmt, or_options_t *options, config_var_t *var)
1695 void *lvalue = STRUCT_VAR_P(options, var->var_offset);
1696 (void)fmt; /* unused */
1697 switch (var->type) {
1698 case CONFIG_TYPE_STRING:
1699 tor_free(*(char**)lvalue);
1700 break;
1701 case CONFIG_TYPE_DOUBLE:
1702 *(double*)lvalue = 0.0;
1703 break;
1704 case CONFIG_TYPE_ISOTIME:
1705 *(time_t*)lvalue = 0;
1706 case CONFIG_TYPE_INTERVAL:
1707 case CONFIG_TYPE_UINT:
1708 case CONFIG_TYPE_BOOL:
1709 *(int*)lvalue = 0;
1710 break;
1711 case CONFIG_TYPE_MEMUNIT:
1712 *(uint64_t*)lvalue = 0;
1713 break;
1714 case CONFIG_TYPE_CSV:
1715 if (*(smartlist_t**)lvalue) {
1716 SMARTLIST_FOREACH(*(smartlist_t **)lvalue, char *, cp, tor_free(cp));
1717 smartlist_free(*(smartlist_t **)lvalue);
1718 *(smartlist_t **)lvalue = NULL;
1720 break;
1721 case CONFIG_TYPE_LINELIST:
1722 case CONFIG_TYPE_LINELIST_S:
1723 config_free_lines(*(config_line_t **)lvalue);
1724 *(config_line_t **)lvalue = NULL;
1725 break;
1726 case CONFIG_TYPE_LINELIST_V:
1727 /* handled by linelist_s. */
1728 break;
1729 case CONFIG_TYPE_OBSOLETE:
1730 break;
1734 /** Clear the option indexed by <b>var</b> in <b>options</b>. Then if
1735 * <b>use_defaults</b>, set it to its default value.
1736 * Called by config_init() and option_reset_line() and option_assign_line(). */
1737 static void
1738 option_reset(config_format_t *fmt, or_options_t *options,
1739 config_var_t *var, int use_defaults)
1741 config_line_t *c;
1742 char *msg = NULL;
1743 CHECK(fmt, options);
1744 option_clear(fmt, options, var); /* clear it first */
1745 if (!use_defaults)
1746 return; /* all done */
1747 if (var->initvalue) {
1748 c = tor_malloc_zero(sizeof(config_line_t));
1749 c->key = tor_strdup(var->name);
1750 c->value = tor_strdup(var->initvalue);
1751 if (config_assign_value(fmt, options, c, &msg) < 0) {
1752 log_warn(LD_BUG, "Failed to assign default: %s", msg);
1753 tor_free(msg); /* if this happens it's a bug */
1755 config_free_lines(c);
1759 /** Print a usage message for tor. */
1760 static void
1761 print_usage(void)
1763 printf(
1764 "Copyright 2001-2006 Roger Dingledine, Nick Mathewson.\n\n"
1765 "tor -f <torrc> [args]\n"
1766 "See man page for options, or http://tor.eff.org/ for documentation.\n");
1769 /** Print all non-obsolete torrc options. */
1770 static void
1771 list_torrc_options(void)
1773 int i;
1774 smartlist_t *lines = smartlist_create();
1775 for (i = 0; _option_vars[i].name; ++i) {
1776 config_var_t *var = &_option_vars[i];
1777 const char *desc;
1778 if (var->type == CONFIG_TYPE_OBSOLETE ||
1779 var->type == CONFIG_TYPE_LINELIST_V)
1780 continue;
1781 desc = config_find_description(&options_format, var->name);
1782 printf("%s\n", var->name);
1783 if (desc) {
1784 wrap_string(lines, desc, 76, " ", " ");
1785 SMARTLIST_FOREACH(lines, char *, cp, {
1786 printf("%s", cp);
1787 tor_free(cp);
1789 smartlist_clear(lines);
1794 /** Last value actually set by resolve_my_address. */
1795 static uint32_t last_resolved_addr = 0;
1797 * Based on <b>options-\>Address</b>, guess our public IP address and put it
1798 * (in host order) into *<b>addr_out</b>. If <b>hostname_out</b> is provided,
1799 * set *<b>hostname_out</b> to a new string holding the hostname we used to
1800 * get the address. Return 0 if all is well, or -1 if we can't find a suitable
1801 * public IP address.
1804 resolve_my_address(int warn_severity, or_options_t *options,
1805 uint32_t *addr_out, char **hostname_out)
1807 struct in_addr in;
1808 struct hostent *rent;
1809 char hostname[256];
1810 int explicit_ip=1;
1811 int explicit_hostname=1;
1812 int from_interface=0;
1813 char tmpbuf[INET_NTOA_BUF_LEN];
1814 const char *address = options->Address;
1815 int notice_severity = warn_severity <= LOG_NOTICE ?
1816 LOG_NOTICE : warn_severity;
1818 tor_assert(addr_out);
1820 if (address && *address) {
1821 strlcpy(hostname, address, sizeof(hostname));
1822 } else { /* then we need to guess our address */
1823 explicit_ip = 0; /* it's implicit */
1824 explicit_hostname = 0; /* it's implicit */
1826 if (gethostname(hostname, sizeof(hostname)) < 0) {
1827 log_fn(warn_severity, LD_NET,"Error obtaining local hostname");
1828 return -1;
1830 log_debug(LD_CONFIG,"Guessed local host name as '%s'",hostname);
1833 /* now we know hostname. resolve it and keep only the IP address */
1835 if (tor_inet_aton(hostname, &in) == 0) {
1836 /* then we have to resolve it */
1837 explicit_ip = 0;
1838 rent = (struct hostent *)gethostbyname(hostname);
1839 if (!rent) {
1840 uint32_t interface_ip;
1842 if (explicit_hostname) {
1843 log_fn(warn_severity, LD_CONFIG,
1844 "Could not resolve local Address '%s'. Failing.", hostname);
1845 return -1;
1847 log_fn(notice_severity, LD_CONFIG,
1848 "Could not resolve guessed local hostname '%s'. "
1849 "Trying something else.", hostname);
1850 if (get_interface_address(warn_severity, &interface_ip)) {
1851 log_fn(warn_severity, LD_CONFIG,
1852 "Could not get local interface IP address. Failing.");
1853 return -1;
1855 from_interface = 1;
1856 in.s_addr = htonl(interface_ip);
1857 tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
1858 log_fn(notice_severity, LD_CONFIG, "Learned IP address '%s' for "
1859 "local interface. Using that.", tmpbuf);
1860 strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
1861 } else {
1862 tor_assert(rent->h_length == 4);
1863 memcpy(&in.s_addr, rent->h_addr, rent->h_length);
1865 if (!explicit_hostname &&
1866 is_internal_IP(ntohl(in.s_addr), 0)) {
1867 uint32_t interface_ip;
1869 tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
1870 log_fn(notice_severity, LD_CONFIG, "Guessed local hostname '%s' "
1871 "resolves to a private IP address (%s). Trying something "
1872 "else.", hostname, tmpbuf);
1874 if (get_interface_address(warn_severity, &interface_ip)) {
1875 log_fn(warn_severity, LD_CONFIG,
1876 "Could not get local interface IP address. Too bad.");
1877 } else if (is_internal_IP(interface_ip, 0)) {
1878 struct in_addr in2;
1879 in2.s_addr = htonl(interface_ip);
1880 tor_inet_ntoa(&in2,tmpbuf,sizeof(tmpbuf));
1881 log_fn(notice_severity, LD_CONFIG,
1882 "Interface IP address '%s' is a private address too. "
1883 "Ignoring.", tmpbuf);
1884 } else {
1885 from_interface = 1;
1886 in.s_addr = htonl(interface_ip);
1887 tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
1888 log_fn(notice_severity, LD_CONFIG,
1889 "Learned IP address '%s' for local interface."
1890 " Using that.", tmpbuf);
1891 strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
1897 tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
1898 if (is_internal_IP(ntohl(in.s_addr), 0) &&
1899 options->PublishServerDescriptor) {
1900 /* make sure we're ok with publishing an internal IP */
1901 if (!options->DirServers) {
1902 /* if they are using the default dirservers, disallow internal IPs
1903 * always. */
1904 log_fn(warn_severity, LD_CONFIG,
1905 "Address '%s' resolves to private IP address '%s'. "
1906 "Tor servers that use the default DirServers must have public "
1907 "IP addresses.", hostname, tmpbuf);
1908 return -1;
1910 if (!explicit_ip) {
1911 /* even if they've set their own dirservers, require an explicit IP if
1912 * they're using an internal address. */
1913 log_fn(warn_severity, LD_CONFIG, "Address '%s' resolves to private "
1914 "IP address '%s'. Please set the Address config option to be "
1915 "the IP address you want to use.", hostname, tmpbuf);
1916 return -1;
1920 log_debug(LD_CONFIG, "Resolved Address to '%s'.", tmpbuf);
1921 *addr_out = ntohl(in.s_addr);
1922 if (last_resolved_addr && last_resolved_addr != *addr_out) {
1923 /* Leave this as a notice, regardless of the requested severity,
1924 * at least until dynamic IP address support becomes bulletproof. */
1925 log_notice(LD_NET, "Your IP address seems to have changed. Updating.");
1926 ip_address_changed(0);
1928 if (last_resolved_addr != *addr_out) {
1929 const char *method;
1930 const char *h = hostname;
1931 if (explicit_ip) {
1932 method = "CONFIGURED";
1933 h = NULL;
1934 } else if (explicit_hostname) {
1935 method = "RESOLVED";
1936 } else if (from_interface) {
1937 method = "INTERFACE";
1938 h = NULL;
1939 } else {
1940 method = "GETHOSTNAME";
1942 control_event_server_status(LOG_NOTICE,
1943 "EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s %s%s",
1944 tmpbuf, method, h?"HOSTNAME=":"", h);
1946 last_resolved_addr = *addr_out;
1947 if (hostname_out)
1948 *hostname_out = tor_strdup(hostname);
1949 return 0;
1952 /** Return true iff <b>ip</b> (in host order) is judged to be on the
1953 * same network as us, or on a private network.
1956 is_local_IP(uint32_t ip)
1958 if (is_internal_IP(ip, 0))
1959 return 1;
1960 /* Check whether ip is on the same /24 as we are. */
1961 if (get_options()->EnforceDistinctSubnets == 0)
1962 return 0;
1963 /* It's possible that this next check will hit before the first time
1964 * resolve_my_address actually succeeds. (For clients, it is likely that
1965 * resolve_my_address will never be called at all). In those cases,
1966 * last_resolved_addr will be 0, and so checking to see whether ip is on the
1967 * same /24 as last_resolved_addr will be the same as checking whether it
1968 * was on net 0, which is already done by is_internal_IP.
1970 if ((last_resolved_addr & 0xffffff00ul) == (ip & 0xffffff00ul))
1971 return 1;
1972 return 0;
1975 /** Called when we don't have a nickname set. Try to guess a good nickname
1976 * based on the hostname, and return it in a newly allocated string. If we
1977 * can't, return NULL and let the caller warn if it wants to. */
1978 static char *
1979 get_default_nickname(void)
1981 static const char * const bad_default_nicknames[] = {
1982 "localhost",
1983 NULL,
1985 char localhostname[256];
1986 char *cp, *out, *outp;
1987 int i;
1989 if (gethostname(localhostname, sizeof(localhostname)) < 0)
1990 return NULL;
1992 /* Put it in lowercase; stop at the first dot. */
1993 if ((cp = strchr(localhostname, '.')))
1994 *cp = '\0';
1995 tor_strlower(localhostname);
1997 /* Strip invalid characters. */
1998 cp = localhostname;
1999 out = outp = tor_malloc(strlen(localhostname) + 1);
2000 while (*cp) {
2001 if (strchr(LEGAL_NICKNAME_CHARACTERS, *cp))
2002 *outp++ = *cp++;
2003 else
2004 cp++;
2006 *outp = '\0';
2008 /* Enforce length. */
2009 if (strlen(out) > MAX_NICKNAME_LEN)
2010 out[MAX_NICKNAME_LEN]='\0';
2012 /* Check for dumb names. */
2013 for (i = 0; bad_default_nicknames[i]; ++i) {
2014 if (!strcmp(out, bad_default_nicknames[i])) {
2015 tor_free(out);
2016 return NULL;
2020 return out;
2023 /** Release storage held by <b>options</b> */
2024 static void
2025 config_free(config_format_t *fmt, void *options)
2027 int i;
2029 tor_assert(options);
2031 for (i=0; fmt->vars[i].name; ++i)
2032 option_clear(fmt, options, &(fmt->vars[i]));
2033 if (fmt->extra) {
2034 config_line_t **linep = STRUCT_VAR_P(options, fmt->extra->var_offset);
2035 config_free_lines(*linep);
2036 *linep = NULL;
2038 tor_free(options);
2041 /** Return true iff a and b contain identical keys and values in identical
2042 * order. */
2043 static int
2044 config_lines_eq(config_line_t *a, config_line_t *b)
2046 while (a && b) {
2047 if (strcasecmp(a->key, b->key) || strcmp(a->value, b->value))
2048 return 0;
2049 a = a->next;
2050 b = b->next;
2052 if (a || b)
2053 return 0;
2054 return 1;
2057 /** Return true iff the option <b>var</b> has the same value in <b>o1</b>
2058 * and <b>o2</b>. Must not be called for LINELIST_S or OBSOLETE options.
2060 static int
2061 option_is_same(config_format_t *fmt,
2062 or_options_t *o1, or_options_t *o2, const char *name)
2064 config_line_t *c1, *c2;
2065 int r = 1;
2066 CHECK(fmt, o1);
2067 CHECK(fmt, o2);
2069 c1 = get_assigned_option(fmt, o1, name);
2070 c2 = get_assigned_option(fmt, o2, name);
2071 r = config_lines_eq(c1, c2);
2072 config_free_lines(c1);
2073 config_free_lines(c2);
2074 return r;
2077 /** Copy storage held by <b>old</b> into a new or_options_t and return it. */
2078 static or_options_t *
2079 options_dup(config_format_t *fmt, or_options_t *old)
2081 or_options_t *newopts;
2082 int i;
2083 config_line_t *line;
2085 newopts = config_alloc(fmt);
2086 for (i=0; fmt->vars[i].name; ++i) {
2087 if (fmt->vars[i].type == CONFIG_TYPE_LINELIST_S)
2088 continue;
2089 if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE)
2090 continue;
2091 line = get_assigned_option(fmt, old, fmt->vars[i].name);
2092 if (line) {
2093 char *msg = NULL;
2094 if (config_assign(fmt, newopts, line, 0, 0, &msg) < 0) {
2095 log_err(LD_BUG, "Bug: config_get_assigned_option() generated "
2096 "something we couldn't config_assign(): %s", msg);
2097 tor_free(msg);
2098 tor_assert(0);
2101 config_free_lines(line);
2103 return newopts;
2106 /** Return a new empty or_options_t. Used for testing. */
2107 or_options_t *
2108 options_new(void)
2110 return config_alloc(&options_format);
2113 /** Set <b>options</b> to hold reasonable defaults for most options.
2114 * Each option defaults to zero. */
2115 void
2116 options_init(or_options_t *options)
2118 config_init(&options_format, options);
2121 /* Set all vars in the configuration object 'options' to their default
2122 * values. */
2123 static void
2124 config_init(config_format_t *fmt, void *options)
2126 int i;
2127 config_var_t *var;
2128 CHECK(fmt, options);
2130 for (i=0; fmt->vars[i].name; ++i) {
2131 var = &fmt->vars[i];
2132 if (!var->initvalue)
2133 continue; /* defaults to NULL or 0 */
2134 option_reset(fmt, options, var, 1);
2138 /* Allocate and return a new string holding the written-out values of the vars
2139 * in 'options'. If 'minimal', do not write out any default-valued vars.
2140 * Else, if comment_defaults, write default values as comments.
2142 static char *
2143 config_dump(config_format_t *fmt, void *options, int minimal,
2144 int comment_defaults)
2146 smartlist_t *elements;
2147 or_options_t *defaults;
2148 config_line_t *line, *assigned;
2149 char *result;
2150 int i;
2151 const char *desc;
2152 char *msg = NULL;
2154 defaults = config_alloc(fmt);
2155 config_init(fmt, defaults);
2157 /* XXX use a 1 here so we don't add a new log line while dumping */
2158 if (fmt->validate_fn(NULL,defaults, 1, &msg) < 0) {
2159 log_err(LD_BUG, "Failed to validate default config.");
2160 tor_free(msg);
2161 tor_assert(0);
2164 elements = smartlist_create();
2165 for (i=0; fmt->vars[i].name; ++i) {
2166 int comment_option = 0;
2167 if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE ||
2168 fmt->vars[i].type == CONFIG_TYPE_LINELIST_S)
2169 continue;
2170 /* Don't save 'hidden' control variables. */
2171 if (!strcmpstart(fmt->vars[i].name, "__"))
2172 continue;
2173 if (minimal && option_is_same(fmt, options, defaults, fmt->vars[i].name))
2174 continue;
2175 else if (comment_defaults &&
2176 option_is_same(fmt, options, defaults, fmt->vars[i].name))
2177 comment_option = 1;
2179 desc = config_find_description(fmt, fmt->vars[i].name);
2180 line = assigned = get_assigned_option(fmt, options, fmt->vars[i].name);
2182 if (line && desc) {
2183 /* Only dump the description if there's something to describe. */
2184 wrap_string(elements, desc, 78, "# ", "# ");
2187 for (; line; line = line->next) {
2188 size_t len = strlen(line->key) + strlen(line->value) + 5;
2189 char *tmp;
2190 tmp = tor_malloc(len);
2191 if (tor_snprintf(tmp, len, "%s%s %s\n",
2192 comment_option ? "# " : "",
2193 line->key, line->value)<0) {
2194 log_err(LD_BUG,"Internal error writing option value");
2195 tor_assert(0);
2197 smartlist_add(elements, tmp);
2199 config_free_lines(assigned);
2202 if (fmt->extra) {
2203 line = *(config_line_t**)STRUCT_VAR_P(options, fmt->extra->var_offset);
2204 for (; line; line = line->next) {
2205 size_t len = strlen(line->key) + strlen(line->value) + 3;
2206 char *tmp;
2207 tmp = tor_malloc(len);
2208 if (tor_snprintf(tmp, len, "%s %s\n", line->key, line->value)<0) {
2209 log_err(LD_BUG,"Internal error writing option value");
2210 tor_assert(0);
2212 smartlist_add(elements, tmp);
2216 result = smartlist_join_strings(elements, "", 0, NULL);
2217 SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
2218 smartlist_free(elements);
2219 config_free(fmt, defaults);
2220 return result;
2223 /** Return a string containing a possible configuration file that would give
2224 * the configuration in <b>options</b>. If <b>minimal</b> is true, do not
2225 * include options that are the same as Tor's defaults.
2227 char *
2228 options_dump(or_options_t *options, int minimal)
2230 return config_dump(&options_format, options, minimal, 0);
2233 /* Return 0 if every element of sl is a string holding a decimal
2234 * representation of a port number, or if sl is NULL.
2235 * Otherwise set *msg and return -1. */
2236 static int
2237 validate_ports_csv(smartlist_t *sl, const char *name, char **msg)
2239 int i;
2240 char buf[1024];
2241 tor_assert(name);
2243 if (!sl)
2244 return 0;
2246 SMARTLIST_FOREACH(sl, const char *, cp,
2248 i = atoi(cp);
2249 if (i < 1 || i > 65535) {
2250 int r = tor_snprintf(buf, sizeof(buf),
2251 "Port '%s' out of range in %s", cp, name);
2252 *msg = tor_strdup(r >= 0 ? buf : "internal error");
2253 return -1;
2256 return 0;
2259 /** Lowest allowable value for RendPostPeriod; if this is too low, hidden
2260 * services can overload the directory system. */
2261 #define MIN_REND_POST_PERIOD (5*60)
2263 /** Highest allowable value for RendPostPeriod. */
2264 #define MAX_DIR_PERIOD (MIN_ONION_KEY_LIFETIME/2)
2266 /** Return 0 if every setting in <b>options</b> is reasonable, and a
2267 * permissible transition from <b>old_options</b>. Else return -1.
2268 * Should have no side effects, except for normalizing the contents of
2269 * <b>options</b>.
2271 * On error, tor_strdup an error explanation into *<b>msg</b>.
2273 * XXX
2274 * If <b>from_setconf</b>, we were called by the controller, and our
2275 * Log line should stay empty. If it's 0, then give us a default log
2276 * if there are no logs defined.
2278 static int
2279 options_validate(or_options_t *old_options, or_options_t *options,
2280 int from_setconf, char **msg)
2282 int i, r;
2283 config_line_t *cl;
2284 const char *uname = get_uname();
2285 char buf[1024];
2286 #define REJECT(arg) \
2287 do { *msg = tor_strdup(arg); return -1; } while (0)
2288 #define COMPLAIN(arg) do { log(LOG_WARN, LD_CONFIG, arg); } while (0)
2290 tor_assert(msg);
2291 *msg = NULL;
2293 if (options->ORPort < 0 || options->ORPort > 65535)
2294 REJECT("ORPort option out of bounds.");
2296 if (server_mode(options) &&
2297 (!strcmpstart(uname, "Windows 95") ||
2298 !strcmpstart(uname, "Windows 98") ||
2299 !strcmpstart(uname, "Windows Me"))) {
2300 log(LOG_WARN, LD_CONFIG, "Tor is running as a server, but you are "
2301 "running %s; this probably won't work. See "
2302 "http://wiki.noreply.org/noreply/TheOnionRouter/TorFAQ#ServerOS "
2303 "for details.", uname);
2306 if (options->ORPort == 0 && options->ORListenAddress != NULL)
2307 REJECT("ORPort must be defined if ORListenAddress is defined.");
2309 if (options->DirPort == 0 && options->DirListenAddress != NULL)
2310 REJECT("DirPort must be defined if DirListenAddress is defined.");
2312 if (options->ControlPort == 0 && options->ControlListenAddress != NULL)
2313 REJECT("ControlPort must be defined if ControlListenAddress is defined.");
2315 if (options->TransPort == 0 && options->TransListenAddress != NULL)
2316 REJECT("TransPort must be defined if TransListenAddress is defined.");
2318 if (options->NatdPort == 0 && options->NatdListenAddress != NULL)
2319 REJECT("NatdPort must be defined if NatdListenAddress is defined.");
2321 /* Don't gripe about SocksPort 0 with SocksListenAddress set; a standard
2322 * configuration does this. */
2324 for (i = 0; i < 3; ++i) {
2325 int is_socks = i==0;
2326 int is_trans = i==1;
2327 config_line_t *line, *opt, *old;
2328 const char *tp;
2329 if (is_socks) {
2330 opt = options->SocksListenAddress;
2331 old = old_options ? old_options->SocksListenAddress : NULL;
2332 tp = "SOCKS proxy";
2333 } else if (is_trans) {
2334 opt = options->TransListenAddress;
2335 old = old_options ? old_options->TransListenAddress : NULL;
2336 tp = "transparent proxy";
2337 } else {
2338 opt = options->NatdListenAddress;
2339 old = old_options ? old_options->NatdListenAddress : NULL;
2340 tp = "natd proxy";
2343 for (line = opt; line; line = line->next) {
2344 char *address = NULL;
2345 uint16_t port;
2346 uint32_t addr;
2347 if (parse_addr_port(LOG_WARN, line->value, &address, &addr, &port)<0)
2348 continue; /* We'll warn about this later. */
2349 if (!is_internal_IP(addr, 1) &&
2350 (!old_options || !config_lines_eq(old, opt))) {
2351 log_warn(LD_CONFIG,
2352 "You specified a public address '%s' for a %s. Other "
2353 "people on the Internet might find your computer and use it as "
2354 "an open %s. Please don't allow this unless you have "
2355 "a good reason.", address, tp, tp);
2357 tor_free(address);
2361 if (validate_data_directory(options)<0)
2362 REJECT("Invalid DataDirectory");
2364 if (options->Nickname == NULL) {
2365 if (server_mode(options)) {
2366 if (!(options->Nickname = get_default_nickname())) {
2367 log_notice(LD_CONFIG, "Couldn't pick a nickname based on "
2368 "our hostname; using %s instead.", UNNAMED_ROUTER_NICKNAME);
2369 options->Nickname = tor_strdup(UNNAMED_ROUTER_NICKNAME);
2370 } else {
2371 log_notice(LD_CONFIG, "Choosing default nickname '%s'",
2372 options->Nickname);
2375 } else {
2376 if (!is_legal_nickname(options->Nickname)) {
2377 r = tor_snprintf(buf, sizeof(buf),
2378 "Nickname '%s' is wrong length or contains illegal characters.",
2379 options->Nickname);
2380 *msg = tor_strdup(r >= 0 ? buf : "internal error");
2381 return -1;
2385 if (server_mode(options) && !options->ContactInfo)
2386 log(LOG_NOTICE, LD_CONFIG, "Your ContactInfo config option is not set. "
2387 "Please consider setting it, so we can contact you if your server is "
2388 "misconfigured or something else goes wrong.");
2390 /* Special case on first boot if no Log options are given. */
2391 if (!options->Logs && !options->RunAsDaemon && !from_setconf)
2392 config_line_append(&options->Logs, "Log", "notice stdout");
2394 if (options_init_logs(options, 1)<0) /* Validate the log(s) */
2395 REJECT("Failed to validate Log options. See logs for details.");
2397 if (options->NoPublish) {
2398 log(LOG_WARN, LD_CONFIG,
2399 "NoPublish is obsolete. Use PublishServerDescriptor instead.");
2400 options->PublishServerDescriptor = 0;
2403 if (authdir_mode(options)) {
2404 /* confirm that our address isn't broken, so we can complain now */
2405 uint32_t tmp;
2406 if (resolve_my_address(LOG_WARN, options, &tmp, NULL) < 0)
2407 REJECT("Failed to resolve/guess local address. See logs for details.");
2410 #ifndef MS_WINDOWS
2411 if (options->RunAsDaemon && torrc_fname && path_is_relative(torrc_fname))
2412 REJECT("Can't use a relative path to torrc when RunAsDaemon is set.");
2413 #endif
2415 if (options->SocksPort < 0 || options->SocksPort > 65535)
2416 REJECT("SocksPort option out of bounds.");
2418 if (options->TransPort < 0 || options->TransPort > 65535)
2419 REJECT("TransPort option out of bounds.");
2421 if (options->NatdPort < 0 || options->NatdPort > 65535)
2422 REJECT("NatdPort option out of bounds.");
2424 if (options->SocksPort == 0 && options->TransPort == 0 &&
2425 options->NatdPort == 0 && options->ORPort == 0)
2426 REJECT("SocksPort, TransPort, NatdPort, and ORPort are all undefined? "
2427 "Quitting.");
2429 if (options->ControlPort < 0 || options->ControlPort > 65535)
2430 REJECT("ControlPort option out of bounds.");
2432 if (options->DirPort < 0 || options->DirPort > 65535)
2433 REJECT("DirPort option out of bounds.");
2435 #ifndef USE_TRANSPARENT
2436 if (options->TransPort || options->TransListenAddress)
2437 REJECT("TransPort and TransListenAddress are disabled in this build.");
2438 #endif
2440 if (options->StrictExitNodes &&
2441 (!options->ExitNodes || !strlen(options->ExitNodes)) &&
2442 (!old_options ||
2443 (old_options->StrictExitNodes != options->StrictExitNodes) ||
2444 (!opt_streq(old_options->ExitNodes, options->ExitNodes))))
2445 COMPLAIN("StrictExitNodes set, but no ExitNodes listed.");
2447 if (options->StrictEntryNodes &&
2448 (!options->EntryNodes || !strlen(options->EntryNodes)) &&
2449 (!old_options ||
2450 (old_options->StrictEntryNodes != options->StrictEntryNodes) ||
2451 (!opt_streq(old_options->EntryNodes, options->EntryNodes))))
2452 COMPLAIN("StrictEntryNodes set, but no EntryNodes listed.");
2454 if (options->AuthoritativeDir) {
2455 if (!options->ContactInfo)
2456 REJECT("Authoritative directory servers must set ContactInfo");
2457 if (options->V1AuthoritativeDir && !options->RecommendedVersions)
2458 REJECT("V1 auth dir servers must set RecommendedVersions.");
2459 if (!options->RecommendedClientVersions)
2460 options->RecommendedClientVersions =
2461 config_lines_dup(options->RecommendedVersions);
2462 if (!options->RecommendedServerVersions)
2463 options->RecommendedServerVersions =
2464 config_lines_dup(options->RecommendedVersions);
2465 if (options->VersioningAuthoritativeDir &&
2466 (!options->RecommendedClientVersions ||
2467 !options->RecommendedServerVersions))
2468 REJECT("Versioning auth dir servers must set Recommended*Versions.");
2469 if (options->UseEntryGuards) {
2470 log_info(LD_CONFIG, "Authoritative directory servers can't set "
2471 "UseEntryGuards. Disabling.");
2472 options->UseEntryGuards = 0;
2476 if (options->AuthoritativeDir && !options->DirPort)
2477 REJECT("Running as authoritative directory, but no DirPort set.");
2479 if (options->AuthoritativeDir && !options->ORPort)
2480 REJECT("Running as authoritative directory, but no ORPort set.");
2482 if (options->AuthoritativeDir && options->ClientOnly)
2483 REJECT("Running as authoritative directory, but ClientOnly also set.");
2485 if (options->ConnLimit <= 0) {
2486 r = tor_snprintf(buf, sizeof(buf),
2487 "ConnLimit must be greater than 0, but was set to %d",
2488 options->ConnLimit);
2489 *msg = tor_strdup(r >= 0 ? buf : "internal error");
2490 return -1;
2493 if (validate_ports_csv(options->FirewallPorts, "FirewallPorts", msg) < 0)
2494 return -1;
2496 if (validate_ports_csv(options->LongLivedPorts, "LongLivedPorts", msg) < 0)
2497 return -1;
2499 if (options->FascistFirewall && !options->ReachableAddresses) {
2500 if (options->FirewallPorts && smartlist_len(options->FirewallPorts)) {
2501 /* We already have firewall ports set, so migrate them to
2502 * ReachableAddresses, which will set ReachableORAddresses and
2503 * ReachableDirAddresses if they aren't set explicitly. */
2504 smartlist_t *instead = smartlist_create();
2505 config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
2506 new_line->key = tor_strdup("ReachableAddresses");
2507 /* If we're configured with the old format, we need to prepend some
2508 * open ports. */
2509 SMARTLIST_FOREACH(options->FirewallPorts, const char *, portno,
2511 int p = atoi(portno);
2512 char *s;
2513 if (p<0) continue;
2514 s = tor_malloc(16);
2515 tor_snprintf(s, 16, "*:%d", p);
2516 smartlist_add(instead, s);
2518 new_line->value = smartlist_join_strings(instead,",",0,NULL);
2519 /* These have been deprecated since 0.1.1.5-alpha-cvs */
2520 log(LOG_NOTICE, LD_CONFIG,
2521 "Converting FascistFirewall and FirewallPorts "
2522 "config options to new format: \"ReachableAddresses %s\"",
2523 new_line->value);
2524 options->ReachableAddresses = new_line;
2525 SMARTLIST_FOREACH(instead, char *, cp, tor_free(cp));
2526 smartlist_free(instead);
2527 } else {
2528 /* We do not have FirewallPorts set, so add 80 to
2529 * ReachableDirAddresses, and 443 to ReachableORAddresses. */
2530 if (!options->ReachableDirAddresses) {
2531 config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
2532 new_line->key = tor_strdup("ReachableDirAddresses");
2533 new_line->value = tor_strdup("*:80");
2534 options->ReachableDirAddresses = new_line;
2535 log(LOG_NOTICE, LD_CONFIG, "Converting FascistFirewall config option "
2536 "to new format: \"ReachableDirAddresses *:80\"");
2538 if (!options->ReachableORAddresses) {
2539 config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
2540 new_line->key = tor_strdup("ReachableORAddresses");
2541 new_line->value = tor_strdup("*:443");
2542 options->ReachableORAddresses = new_line;
2543 log(LOG_NOTICE, LD_CONFIG, "Converting FascistFirewall config option "
2544 "to new format: \"ReachableORAddresses *:443\"");
2549 for (i=0; i<3; i++) {
2550 config_line_t **linep =
2551 (i==0) ? &options->ReachableAddresses :
2552 (i==1) ? &options->ReachableORAddresses :
2553 &options->ReachableDirAddresses;
2554 if (!*linep)
2555 continue;
2556 /* We need to end with a reject *:*, not an implicit accept *:* */
2557 for (;;) {
2558 if (!strcmp((*linep)->value, "reject *:*")) /* already there */
2559 break;
2560 linep = &((*linep)->next);
2561 if (!*linep) {
2562 *linep = tor_malloc_zero(sizeof(config_line_t));
2563 (*linep)->key = tor_strdup(
2564 (i==0) ? "ReachableAddresses" :
2565 (i==1) ? "ReachableORAddresses" :
2566 "ReachableDirAddresses");
2567 (*linep)->value = tor_strdup("reject *:*");
2568 break;
2573 if ((options->ReachableAddresses ||
2574 options->ReachableORAddresses ||
2575 options->ReachableDirAddresses) &&
2576 server_mode(options))
2577 REJECT("Servers must be able to freely connect to the rest "
2578 "of the Internet, so they must not set Reachable*Addresses "
2579 "or FascistFirewall.");
2581 options->_AllowInvalid = 0;
2582 if (options->AllowInvalidNodes) {
2583 SMARTLIST_FOREACH(options->AllowInvalidNodes, const char *, cp, {
2584 if (!strcasecmp(cp, "entry"))
2585 options->_AllowInvalid |= ALLOW_INVALID_ENTRY;
2586 else if (!strcasecmp(cp, "exit"))
2587 options->_AllowInvalid |= ALLOW_INVALID_EXIT;
2588 else if (!strcasecmp(cp, "middle"))
2589 options->_AllowInvalid |= ALLOW_INVALID_MIDDLE;
2590 else if (!strcasecmp(cp, "introduction"))
2591 options->_AllowInvalid |= ALLOW_INVALID_INTRODUCTION;
2592 else if (!strcasecmp(cp, "rendezvous"))
2593 options->_AllowInvalid |= ALLOW_INVALID_RENDEZVOUS;
2594 else {
2595 r = tor_snprintf(buf, sizeof(buf),
2596 "Unrecognized value '%s' in AllowInvalidNodes", cp);
2597 *msg = tor_strdup(r >= 0 ? buf : "internal error");
2598 return -1;
2603 if (options->SocksPort >= 1 &&
2604 (options->PathlenCoinWeight < 0.0 || options->PathlenCoinWeight >= 1.0))
2605 REJECT("PathlenCoinWeight option must be >=0.0 and <1.0.");
2607 if (options->RendPostPeriod < MIN_REND_POST_PERIOD) {
2608 log(LOG_WARN,LD_CONFIG,"RendPostPeriod option must be at least %d seconds."
2609 " Clipping.", MIN_REND_POST_PERIOD);
2610 options->RendPostPeriod = MIN_REND_POST_PERIOD;
2613 if (options->RendPostPeriod > MAX_DIR_PERIOD) {
2614 log(LOG_WARN, LD_CONFIG, "RendPostPeriod is too large; clipping to %ds.",
2615 MAX_DIR_PERIOD);
2616 options->RendPostPeriod = MAX_DIR_PERIOD;
2619 if (options->KeepalivePeriod < 1)
2620 REJECT("KeepalivePeriod option must be positive.");
2622 if (options->BandwidthRate > INT_MAX) {
2623 r = tor_snprintf(buf, sizeof(buf),
2624 "BandwidthRate must be less than %d",INT_MAX);
2625 *msg = tor_strdup(r >= 0 ? buf : "internal error");
2626 return -1;
2628 if (options->BandwidthBurst > INT_MAX) {
2629 r = tor_snprintf(buf, sizeof(buf),
2630 "BandwidthBurst must be less than %d",INT_MAX);
2631 *msg = tor_strdup(r >= 0 ? buf : "internal error");
2632 return -1;
2634 if (server_mode(options) &&
2635 options->BandwidthRate < ROUTER_REQUIRED_MIN_BANDWIDTH*2) {
2636 r = tor_snprintf(buf, sizeof(buf),
2637 "BandwidthRate is set to %d bytes/second. "
2638 "For servers, it must be at least %d.",
2639 (int)options->BandwidthRate,
2640 ROUTER_REQUIRED_MIN_BANDWIDTH*2);
2641 *msg = tor_strdup(r >= 0 ? buf : "internal error");
2642 return -1;
2644 if (options->BandwidthRate > options->BandwidthBurst)
2645 REJECT("BandwidthBurst must be at least equal to BandwidthRate.");
2647 if (accounting_parse_options(options, 1)<0)
2648 REJECT("Failed to parse accounting options. See logs for details.");
2650 if (options->HttpProxy) { /* parse it now */
2651 if (parse_addr_port(LOG_WARN, options->HttpProxy, NULL,
2652 &options->HttpProxyAddr, &options->HttpProxyPort) < 0)
2653 REJECT("HttpProxy failed to parse or resolve. Please fix.");
2654 if (options->HttpProxyPort == 0) { /* give it a default */
2655 options->HttpProxyPort = 80;
2659 if (options->HttpProxyAuthenticator) {
2660 if (strlen(options->HttpProxyAuthenticator) >= 48)
2661 REJECT("HttpProxyAuthenticator is too long (>= 48 chars).");
2664 if (options->HttpsProxy) { /* parse it now */
2665 if (parse_addr_port(LOG_WARN, options->HttpsProxy, NULL,
2666 &options->HttpsProxyAddr, &options->HttpsProxyPort) <0)
2667 REJECT("HttpsProxy failed to parse or resolve. Please fix.");
2668 if (options->HttpsProxyPort == 0) { /* give it a default */
2669 options->HttpsProxyPort = 443;
2673 if (options->HttpsProxyAuthenticator) {
2674 if (strlen(options->HttpsProxyAuthenticator) >= 48)
2675 REJECT("HttpsProxyAuthenticator is too long (>= 48 chars).");
2678 if (options->HashedControlPassword) {
2679 if (decode_hashed_password(NULL, options->HashedControlPassword)<0)
2680 REJECT("Bad HashedControlPassword: wrong length or bad encoding");
2682 if (options->HashedControlPassword && options->CookieAuthentication)
2683 REJECT("Cannot set both HashedControlPassword and CookieAuthentication");
2685 if (options->UseEntryGuards && ! options->NumEntryGuards)
2686 REJECT("Cannot enable UseEntryGuards with NumEntryGuards set to 0");
2688 #ifndef USE_EVENTDNS
2689 if (options->ServerDNSResolvConfFile)
2690 log(LOG_WARN, LD_CONFIG,
2691 "ServerDNSResolvConfFile only works when eventdns support is enabled.");
2692 #endif
2694 if (check_nickname_list(options->ExitNodes, "ExitNodes", msg))
2695 return -1;
2696 if (check_nickname_list(options->EntryNodes, "EntryNodes", msg))
2697 return -1;
2698 if (check_nickname_list(options->ExcludeNodes, "ExcludeNodes", msg))
2699 return -1;
2700 if (check_nickname_list(options->RendNodes, "RendNodes", msg))
2701 return -1;
2702 if (check_nickname_list(options->RendNodes, "RendExcludeNodes", msg))
2703 return -1;
2704 if (check_nickname_list(options->TestVia, "TestVia", msg))
2705 return -1;
2706 if (check_nickname_list(options->MyFamily, "MyFamily", msg))
2707 return -1;
2708 for (cl = options->NodeFamilies; cl; cl = cl->next) {
2709 if (check_nickname_list(cl->value, "NodeFamily", msg))
2710 return -1;
2713 if (validate_addr_policies(options, msg) < 0)
2714 return -1;
2716 for (cl = options->RedirectExit; cl; cl = cl->next) {
2717 if (parse_redirect_line(NULL, cl, msg)<0)
2718 return -1;
2721 if (options->DirServers) {
2722 if (!old_options ||
2723 !config_lines_eq(options->DirServers, old_options->DirServers))
2724 COMPLAIN("You have used DirServer to specify directory authorities in "
2725 "your configuration. This is potentially dangerous: it can "
2726 "make you look different from all other Tor users, and hurt "
2727 "your anonymity. Even if you've specified the same "
2728 "authorities as Tor uses by default, the defaults could "
2729 "change in the future. Be sure you know what you're doing.");
2730 for (cl = options->DirServers; cl; cl = cl->next) {
2731 if (parse_dir_server_line(cl->value, 1)<0)
2732 REJECT("DirServer line did not parse. See logs for details.");
2736 if (rend_config_services(options, 1) < 0)
2737 REJECT("Failed to configure rendezvous options. See logs for details.");
2739 if (parse_virtual_addr_network(options->VirtualAddrNetwork, 1, NULL)<0)
2740 return -1;
2742 if (options->PreferTunneledDirConns && !options->TunnelDirConns)
2743 REJECT("Must set TunnelDirConns if PreferTunneledDirConns is set.");
2745 return 0;
2746 #undef REJECT
2747 #undef COMPLAIN
2750 /** Helper: return true iff s1 and s2 are both NULL, or both non-NULL
2751 * equal strings. */
2752 static int
2753 opt_streq(const char *s1, const char *s2)
2755 if (!s1 && !s2)
2756 return 1;
2757 else if (s1 && s2 && !strcmp(s1,s2))
2758 return 1;
2759 else
2760 return 0;
2763 /** Check if any of the previous options have changed but aren't allowed to. */
2764 static int
2765 options_transition_allowed(or_options_t *old, or_options_t *new_val,
2766 char **msg)
2768 if (!old)
2769 return 0;
2771 if (!opt_streq(old->PidFile, new_val->PidFile)) {
2772 *msg = tor_strdup("PidFile is not allowed to change.");
2773 return -1;
2776 if (old->RunAsDaemon != new_val->RunAsDaemon) {
2777 *msg = tor_strdup("While Tor is running, changing RunAsDaemon "
2778 "is not allowed.");
2779 return -1;
2782 if (strcmp(old->DataDirectory,new_val->DataDirectory)!=0) {
2783 char buf[1024];
2784 int r = tor_snprintf(buf, sizeof(buf),
2785 "While Tor is running, changing DataDirectory "
2786 "(\"%s\"->\"%s\") is not allowed.",
2787 old->DataDirectory, new_val->DataDirectory);
2788 *msg = tor_strdup(r >= 0 ? buf : "internal error");
2789 return -1;
2792 if (!opt_streq(old->User, new_val->User)) {
2793 *msg = tor_strdup("While Tor is running, changing User is not allowed.");
2794 return -1;
2797 if (!opt_streq(old->Group, new_val->Group)) {
2798 *msg = tor_strdup("While Tor is running, changing Group is not allowed.");
2799 return -1;
2802 if (old->HardwareAccel != new_val->HardwareAccel) {
2803 *msg = tor_strdup("While Tor is running, changing HardwareAccel is "
2804 "not allowed.");
2805 return -1;
2808 return 0;
2811 /** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
2812 * will require us to rotate the cpu and dns workers; else return 0. */
2813 static int
2814 options_transition_affects_workers(or_options_t *old_options,
2815 or_options_t *new_options)
2817 if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) ||
2818 old_options->NumCpus != new_options->NumCpus ||
2819 old_options->ORPort != new_options->ORPort ||
2820 old_options->ServerDNSSearchDomains !=
2821 new_options->ServerDNSSearchDomains ||
2822 old_options->SafeLogging != new_options->SafeLogging ||
2823 !config_lines_eq(old_options->Logs, new_options->Logs))
2824 return 1;
2826 /* Check whether log options match. */
2828 /* Nothing that changed matters. */
2829 return 0;
2832 /** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
2833 * will require us to generate a new descriptor; else return 0. */
2834 static int
2835 options_transition_affects_descriptor(or_options_t *old_options,
2836 or_options_t *new_options)
2838 if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) ||
2839 !opt_streq(old_options->Nickname,new_options->Nickname) ||
2840 !opt_streq(old_options->Address,new_options->Address) ||
2841 !config_lines_eq(old_options->ExitPolicy,new_options->ExitPolicy) ||
2842 old_options->ORPort != new_options->ORPort ||
2843 old_options->DirPort != new_options->DirPort ||
2844 old_options->ClientOnly != new_options->ClientOnly ||
2845 old_options->NoPublish != new_options->NoPublish ||
2846 old_options->PublishServerDescriptor !=
2847 new_options->PublishServerDescriptor ||
2848 old_options->BandwidthRate != new_options->BandwidthRate ||
2849 old_options->BandwidthBurst != new_options->BandwidthBurst ||
2850 !opt_streq(old_options->ContactInfo, new_options->ContactInfo) ||
2851 !opt_streq(old_options->MyFamily, new_options->MyFamily) ||
2852 !opt_streq(old_options->AccountingStart, new_options->AccountingStart) ||
2853 old_options->AccountingMax != new_options->AccountingMax)
2854 return 1;
2856 return 0;
2859 #ifdef MS_WINDOWS
2860 /** Return the directory on windows where we expect to find our application
2861 * data. */
2862 static char *
2863 get_windows_conf_root(void)
2865 static int is_set = 0;
2866 static char path[MAX_PATH+1];
2868 LPITEMIDLIST idl;
2869 IMalloc *m;
2870 HRESULT result;
2872 if (is_set)
2873 return path;
2875 /* Find X:\documents and settings\username\application data\ .
2876 * We would use SHGetSpecialFolder path, but that wasn't added until IE4.
2878 if (!SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA,
2879 &idl))) {
2880 GetCurrentDirectory(MAX_PATH, path);
2881 is_set = 1;
2882 log_warn(LD_CONFIG,
2883 "I couldn't find your application data folder: are you "
2884 "running an ancient version of Windows 95? Defaulting to \"%s\"",
2885 path);
2886 return path;
2888 /* Convert the path from an "ID List" (whatever that is!) to a path. */
2889 result = SHGetPathFromIDList(idl, path);
2890 /* Now we need to free the */
2891 SHGetMalloc(&m);
2892 if (m) {
2893 m->lpVtbl->Free(m, idl);
2894 m->lpVtbl->Release(m);
2896 if (!SUCCEEDED(result)) {
2897 return NULL;
2899 strlcat(path,"\\tor",MAX_PATH);
2900 is_set = 1;
2901 return path;
2903 #endif
2905 /** Return the default location for our torrc file. */
2906 static const char *
2907 get_default_conf_file(void)
2909 #ifdef MS_WINDOWS
2910 static char path[MAX_PATH+1];
2911 strlcpy(path, get_windows_conf_root(), MAX_PATH);
2912 strlcat(path,"\\torrc",MAX_PATH);
2913 return path;
2914 #else
2915 return (CONFDIR "/torrc");
2916 #endif
2919 /** Verify whether lst is a string containing valid-looking space-separated
2920 * nicknames, or NULL. Return 0 on success. Warn and return -1 on failure.
2922 static int
2923 check_nickname_list(const char *lst, const char *name, char **msg)
2925 int r = 0;
2926 smartlist_t *sl;
2928 if (!lst)
2929 return 0;
2930 sl = smartlist_create();
2931 smartlist_split_string(sl, lst, ",", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
2932 SMARTLIST_FOREACH(sl, const char *, s,
2934 if (!is_legal_nickname_or_hexdigest(s)) {
2935 char buf[1024];
2936 int tmp = tor_snprintf(buf, sizeof(buf),
2937 "Invalid nickname '%s' in %s line", s, name);
2938 *msg = tor_strdup(tmp >= 0 ? buf : "internal error");
2939 r = -1;
2940 break;
2943 SMARTLIST_FOREACH(sl, char *, s, tor_free(s));
2944 smartlist_free(sl);
2945 return r;
2948 /** Read a configuration file into <b>options</b>, finding the configuration
2949 * file location based on the command line. After loading the options,
2950 * validate them for consistency, then take actions based on them.
2951 * Return 0 if success, -1 if failure. */
2953 options_init_from_torrc(int argc, char **argv)
2955 or_options_t *oldoptions, *newoptions;
2956 config_line_t *cl;
2957 char *cf=NULL, *fname=NULL, *errmsg=NULL;
2958 int i, retval;
2959 int using_default_torrc;
2960 static char **backup_argv;
2961 static int backup_argc;
2963 if (argv) { /* first time we're called. save commandline args */
2964 backup_argv = argv;
2965 backup_argc = argc;
2966 oldoptions = NULL;
2967 } else { /* we're reloading. need to clean up old options first. */
2968 argv = backup_argv;
2969 argc = backup_argc;
2970 oldoptions = get_options();
2972 if (argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1],"--help"))) {
2973 print_usage();
2974 exit(0);
2976 if (argc > 1 && !strcmp(argv[1], "--list-torrc-options")) {
2977 /* For documenting validating whether we've documented everything. */
2978 list_torrc_options();
2979 exit(0);
2982 if (argc > 1 && (!strcmp(argv[1],"--version"))) {
2983 printf("Tor version %s.\n",VERSION);
2984 if (argc > 2 && (!strcmp(argv[2],"--version"))) {
2985 print_svn_version();
2987 exit(0);
2990 newoptions = tor_malloc_zero(sizeof(or_options_t));
2991 newoptions->_magic = OR_OPTIONS_MAGIC;
2992 options_init(newoptions);
2994 /* learn config file name */
2995 fname = NULL;
2996 using_default_torrc = 1;
2997 newoptions->command = CMD_RUN_TOR;
2998 for (i = 1; i < argc; ++i) {
2999 if (i < argc-1 && !strcmp(argv[i],"-f")) {
3000 if (fname) {
3001 log(LOG_WARN, LD_CONFIG, "Duplicate -f options on command line.");
3002 tor_free(fname);
3004 fname = tor_strdup(argv[i+1]);
3005 using_default_torrc = 0;
3006 ++i;
3007 } else if (!strcmp(argv[i],"--list-fingerprint")) {
3008 newoptions->command = CMD_LIST_FINGERPRINT;
3009 } else if (!strcmp(argv[i],"--hash-password")) {
3010 newoptions->command = CMD_HASH_PASSWORD;
3011 newoptions->command_arg = tor_strdup( (i < argc-1) ? argv[i+1] : "");
3012 ++i;
3013 } else if (!strcmp(argv[i],"--verify-config")) {
3014 newoptions->command = CMD_VERIFY_CONFIG;
3017 if (using_default_torrc) {
3018 /* didn't find one, try CONFDIR */
3019 const char *dflt = get_default_conf_file();
3020 if (dflt && file_status(dflt) == FN_FILE) {
3021 fname = tor_strdup(dflt);
3022 } else {
3023 #ifndef MS_WINDOWS
3024 char *fn;
3025 fn = expand_filename("~/.torrc");
3026 if (fn && file_status(fn) == FN_FILE) {
3027 fname = fn;
3028 } else {
3029 tor_free(fn);
3030 fname = tor_strdup(dflt);
3032 #else
3033 fname = tor_strdup(dflt);
3034 #endif
3037 tor_assert(fname);
3038 log(LOG_DEBUG, LD_CONFIG, "Opening config file \"%s\"", fname);
3040 tor_free(torrc_fname);
3041 torrc_fname = fname;
3043 /* get config lines, assign them */
3044 if (file_status(fname) != FN_FILE ||
3045 !(cf = read_file_to_str(fname,0,NULL))) {
3046 if (using_default_torrc == 1) {
3047 log(LOG_NOTICE, LD_CONFIG, "Configuration file \"%s\" not present, "
3048 "using reasonable defaults.", fname);
3049 tor_free(fname); /* sets fname to NULL */
3050 torrc_fname = NULL;
3051 } else {
3052 log(LOG_WARN, LD_CONFIG,
3053 "Unable to open configuration file \"%s\".", fname);
3054 goto err;
3056 } else { /* it opened successfully. use it. */
3057 retval = config_get_lines(cf, &cl);
3058 tor_free(cf);
3059 if (retval < 0)
3060 goto err;
3061 retval = config_assign(&options_format, newoptions, cl, 0, 0, &errmsg);
3062 config_free_lines(cl);
3063 if (retval < 0)
3064 goto err;
3067 /* Go through command-line variables too */
3068 if (config_get_commandlines(argc, argv, &cl) < 0)
3069 goto err;
3070 retval = config_assign(&options_format, newoptions, cl, 0, 0, &errmsg);
3071 config_free_lines(cl);
3072 if (retval < 0)
3073 goto err;
3075 /* Validate newoptions */
3076 if (options_validate(oldoptions, newoptions, 0, &errmsg) < 0)
3077 goto err;
3079 if (options_transition_allowed(oldoptions, newoptions, &errmsg) < 0)
3080 goto err;
3082 if (set_options(newoptions, &errmsg))
3083 goto err; /* frees and replaces old options */
3085 return 0;
3086 err:
3087 tor_free(fname);
3088 torrc_fname = NULL;
3089 config_free(&options_format, newoptions);
3090 if (errmsg) {
3091 log(LOG_WARN,LD_CONFIG,"Failed to parse/validate config: %s", errmsg);
3092 tor_free(errmsg);
3094 return -1;
3097 /** Return the location for our configuration file.
3099 const char *
3100 get_torrc_fname(void)
3102 if (torrc_fname)
3103 return torrc_fname;
3104 else
3105 return get_default_conf_file();
3108 /** Adjust the address map mased on the MapAddress elements in the
3109 * configuration <b>options</b>
3111 static void
3112 config_register_addressmaps(or_options_t *options)
3114 smartlist_t *elts;
3115 config_line_t *opt;
3116 char *from, *to;
3118 addressmap_clear_configured();
3119 elts = smartlist_create();
3120 for (opt = options->AddressMap; opt; opt = opt->next) {
3121 smartlist_split_string(elts, opt->value, NULL,
3122 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
3123 if (smartlist_len(elts) >= 2) {
3124 from = smartlist_get(elts,0);
3125 to = smartlist_get(elts,1);
3126 if (address_is_invalid_destination(to, 1)) {
3127 log_warn(LD_CONFIG,
3128 "Skipping invalid argument '%s' to MapAddress", to);
3129 } else {
3130 addressmap_register(from, tor_strdup(to), 0);
3131 if (smartlist_len(elts)>2) {
3132 log_warn(LD_CONFIG,"Ignoring extra arguments to MapAddress.");
3135 } else {
3136 log_warn(LD_CONFIG,"MapAddress '%s' has too few arguments. Ignoring.",
3137 opt->value);
3139 SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp));
3140 smartlist_clear(elts);
3142 smartlist_free(elts);
3145 /** If <b>range</b> is of the form MIN-MAX, for MIN and MAX both
3146 * recognized log severity levels, set *<b>min_out</b> to MIN and
3147 * *<b>max_out</b> to MAX and return 0. Else, if <b>range</b> is of
3148 * the form MIN, act as if MIN-err had been specified. Else, warn and
3149 * return -1.
3151 static int
3152 parse_log_severity_range(const char *range, int *min_out, int *max_out)
3154 int levelMin, levelMax;
3155 const char *cp;
3156 cp = strchr(range, '-');
3157 if (cp) {
3158 if (cp == range) {
3159 levelMin = LOG_DEBUG;
3160 } else {
3161 char *tmp_sev = tor_strndup(range, cp - range);
3162 levelMin = parse_log_level(tmp_sev);
3163 if (levelMin < 0) {
3164 log_warn(LD_CONFIG, "Unrecognized minimum log severity '%s': must be "
3165 "one of err|warn|notice|info|debug", tmp_sev);
3166 tor_free(tmp_sev);
3167 return -1;
3169 tor_free(tmp_sev);
3171 if (!*(cp+1)) {
3172 levelMax = LOG_ERR;
3173 } else {
3174 levelMax = parse_log_level(cp+1);
3175 if (levelMax < 0) {
3176 log_warn(LD_CONFIG, "Unrecognized maximum log severity '%s': must be "
3177 "one of err|warn|notice|info|debug", cp+1);
3178 return -1;
3181 } else {
3182 levelMin = parse_log_level(range);
3183 if (levelMin < 0) {
3184 log_warn(LD_CONFIG, "Unrecognized log severity '%s': must be one of "
3185 "err|warn|notice|info|debug", range);
3186 return -1;
3188 levelMax = LOG_ERR;
3191 *min_out = levelMin;
3192 *max_out = levelMax;
3194 return 0;
3198 * Initialize the logs based on the configuration file.
3201 options_init_logs(or_options_t *options, int validate_only)
3203 config_line_t *opt;
3204 int ok;
3205 smartlist_t *elts;
3206 int daemon =
3207 #ifdef MS_WINDOWS
3209 #else
3210 options->RunAsDaemon;
3211 #endif
3213 ok = 1;
3214 elts = smartlist_create();
3216 for (opt = options->Logs; opt; opt = opt->next) {
3217 int levelMin=LOG_DEBUG, levelMax=LOG_ERR;
3218 smartlist_split_string(elts, opt->value, NULL,
3219 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
3220 if (smartlist_len(elts) == 0) {
3221 log_warn(LD_CONFIG, "No arguments to Log option 'Log %s'", opt->value);
3222 ok = 0; goto cleanup;
3224 if (parse_log_severity_range(smartlist_get(elts,0), &levelMin,
3225 &levelMax)) {
3226 ok = 0; goto cleanup;
3228 if (smartlist_len(elts) < 2) { /* only loglevels were provided */
3229 if (!validate_only) {
3230 if (daemon) {
3231 log_warn(LD_CONFIG,
3232 "Can't log to stdout with RunAsDaemon set; skipping stdout");
3233 } else {
3234 add_stream_log(levelMin, levelMax, "<stdout>", stdout);
3237 goto cleanup;
3239 if (!strcasecmp(smartlist_get(elts,1), "file")) {
3240 if (smartlist_len(elts) != 3) {
3241 log_warn(LD_CONFIG, "Bad syntax on file Log option 'Log %s'",
3242 opt->value);
3243 ok = 0; goto cleanup;
3245 if (!validate_only) {
3246 if (add_file_log(levelMin, levelMax, smartlist_get(elts, 2)) < 0) {
3247 log_warn(LD_CONFIG, "Couldn't open file for 'Log %s'", opt->value);
3248 ok = 0;
3251 goto cleanup;
3253 if (smartlist_len(elts) != 2) {
3254 log_warn(LD_CONFIG, "Wrong number of arguments on Log option 'Log %s'",
3255 opt->value);
3256 ok = 0; goto cleanup;
3258 if (!strcasecmp(smartlist_get(elts,1), "stdout")) {
3259 if (daemon) {
3260 log_warn(LD_CONFIG, "Can't log to stdout with RunAsDaemon set.");
3261 ok = 0; goto cleanup;
3263 if (!validate_only) {
3264 add_stream_log(levelMin, levelMax, "<stdout>", stdout);
3266 } else if (!strcasecmp(smartlist_get(elts,1), "stderr")) {
3267 if (daemon) {
3268 log_warn(LD_CONFIG, "Can't log to stderr with RunAsDaemon set.");
3269 ok = 0; goto cleanup;
3271 if (!validate_only) {
3272 add_stream_log(levelMin, levelMax, "<stderr>", stderr);
3274 } else if (!strcasecmp(smartlist_get(elts,1), "syslog")) {
3275 #ifdef HAVE_SYSLOG_H
3276 if (!validate_only)
3277 add_syslog_log(levelMin, levelMax);
3278 #else
3279 log_warn(LD_CONFIG, "Syslog is not supported on this system. Sorry.");
3280 #endif
3281 } else {
3282 log_warn(LD_CONFIG, "Unrecognized log type %s",
3283 (const char*)smartlist_get(elts,1));
3284 if (strchr(smartlist_get(elts,1), '/') ||
3285 strchr(smartlist_get(elts,1), '\\')) {
3286 log_warn(LD_CONFIG, "Did you mean to say 'Log %s file %s' ?",
3287 (const char *)smartlist_get(elts,0),
3288 (const char *)smartlist_get(elts,1));
3290 ok = 0; goto cleanup;
3292 cleanup:
3293 SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp));
3294 smartlist_clear(elts);
3296 smartlist_free(elts);
3298 return ok?0:-1;
3301 /** Parse a single RedirectExit line's contents from <b>line</b>. If
3302 * they are valid, and <b>result</b> is not NULL, add an element to
3303 * <b>result</b> and return 0. Else if they are valid, return 0.
3304 * Else set *msg and return -1. */
3305 static int
3306 parse_redirect_line(smartlist_t *result, config_line_t *line, char **msg)
3308 smartlist_t *elements = NULL;
3309 exit_redirect_t *r;
3311 tor_assert(line);
3313 r = tor_malloc_zero(sizeof(exit_redirect_t));
3314 elements = smartlist_create();
3315 smartlist_split_string(elements, line->value, NULL,
3316 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
3317 if (smartlist_len(elements) != 2) {
3318 *msg = tor_strdup("Wrong number of elements in RedirectExit line");
3319 goto err;
3321 if (parse_addr_and_port_range(smartlist_get(elements,0),&r->addr,&r->mask,
3322 &r->port_min,&r->port_max)) {
3323 *msg = tor_strdup("Error parsing source address in RedirectExit line");
3324 goto err;
3326 if (0==strcasecmp(smartlist_get(elements,1), "pass")) {
3327 r->is_redirect = 0;
3328 } else {
3329 if (parse_addr_port(LOG_WARN, smartlist_get(elements,1),NULL,
3330 &r->addr_dest, &r->port_dest)) {
3331 *msg = tor_strdup("Error parsing dest address in RedirectExit line");
3332 goto err;
3334 r->is_redirect = 1;
3337 goto done;
3338 err:
3339 tor_free(r);
3340 done:
3341 SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
3342 smartlist_free(elements);
3343 if (r) {
3344 if (result)
3345 smartlist_add(result, r);
3346 else
3347 tor_free(r);
3348 return 0;
3349 } else {
3350 tor_assert(*msg);
3351 return -1;
3355 /** Read the contents of a DirServer line from <b>line</b>. Return 0
3356 * if the line is well-formed, and -1 if it isn't. If
3357 * <b>validate_only</b> is 0, and the line is well-formed, then add
3358 * the dirserver described in the line as a valid server. */
3359 static int
3360 parse_dir_server_line(const char *line, int validate_only)
3362 smartlist_t *items = NULL;
3363 int r;
3364 char *addrport=NULL, *address=NULL, *nickname=NULL, *fingerprint=NULL;
3365 uint16_t dir_port = 0, or_port = 0;
3366 char digest[DIGEST_LEN];
3367 int is_v1_authority = 0, is_hidserv_authority = 0,
3368 is_not_hidserv_authority = 0, is_v2_authority = 1;
3370 items = smartlist_create();
3371 smartlist_split_string(items, line, NULL,
3372 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
3373 if (smartlist_len(items) < 1) {
3374 log_warn(LD_CONFIG, "No arguments on DirServer line.");
3375 goto err;
3378 if (is_legal_nickname(smartlist_get(items, 0))) {
3379 nickname = smartlist_get(items, 0);
3380 smartlist_del_keeporder(items, 0);
3383 while (smartlist_len(items)) {
3384 char *flag = smartlist_get(items, 0);
3385 if (TOR_ISDIGIT(flag[0]))
3386 break;
3387 if (!strcasecmp(flag, "v1")) {
3388 is_v1_authority = is_hidserv_authority = 1;
3389 } else if (!strcasecmp(flag, "hs")) {
3390 is_hidserv_authority = 1;
3391 } else if (!strcasecmp(flag, "no-hs")) {
3392 is_not_hidserv_authority = 1;
3393 } else if (!strcasecmp(flag, "no-v2")) {
3394 is_v2_authority = 0;
3395 } else if (!strcasecmpstart(flag, "orport=")) {
3396 int ok;
3397 char *portstring = flag + strlen("orport=");
3398 or_port = (uint16_t) tor_parse_long(portstring, 10, 1, 65535, &ok, NULL);
3399 if (!ok)
3400 log_warn(LD_CONFIG, "Invalid orport '%s' on DirServer line.",
3401 portstring);
3402 } else {
3403 log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirServer line",
3404 flag);
3406 tor_free(flag);
3407 smartlist_del_keeporder(items, 0);
3410 if (is_not_hidserv_authority)
3411 is_hidserv_authority = 0;
3413 if (smartlist_len(items) < 2) {
3414 log_warn(LD_CONFIG, "Too few arguments to DirServer line.");
3415 goto err;
3417 addrport = smartlist_get(items, 0);
3418 smartlist_del_keeporder(items, 0);
3419 if (parse_addr_port(LOG_WARN, addrport, &address, NULL, &dir_port)<0) {
3420 log_warn(LD_CONFIG, "Error parsing DirServer address '%s'", addrport);
3421 goto err;
3423 if (!dir_port) {
3424 log_warn(LD_CONFIG, "Missing port in DirServer address '%s'",addrport);
3425 goto err;
3428 fingerprint = smartlist_join_strings(items, "", 0, NULL);
3429 if (strlen(fingerprint) != HEX_DIGEST_LEN) {
3430 log_warn(LD_CONFIG, "Key digest for DirServer is wrong length.");
3431 goto err;
3433 if (base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN)<0) {
3434 log_warn(LD_CONFIG, "Unable to decode DirServer key digest.");
3435 goto err;
3438 if (!validate_only) {
3439 log_debug(LD_DIR, "Trusted dirserver at %s:%d (%s)", address,
3440 (int)dir_port,
3441 (char*)smartlist_get(items,1));
3442 add_trusted_dir_server(nickname, address, dir_port, or_port, digest,
3443 is_v1_authority,
3444 is_v2_authority, is_hidserv_authority);
3448 r = 0;
3449 goto done;
3451 err:
3452 r = -1;
3454 done:
3455 SMARTLIST_FOREACH(items, char*, s, tor_free(s));
3456 smartlist_free(items);
3457 tor_free(addrport);
3458 tor_free(address);
3459 tor_free(nickname);
3460 tor_free(fingerprint);
3461 return r;
3464 /** Adjust the value of options->DataDirectory, or fill it in if it's
3465 * absent. Return 0 on success, -1 on failure. */
3466 static int
3467 normalize_data_directory(or_options_t *options)
3469 #ifdef MS_WINDOWS
3470 char *p;
3471 if (options->DataDirectory)
3472 return 0; /* all set */
3473 p = tor_malloc(MAX_PATH);
3474 strlcpy(p,get_windows_conf_root(),MAX_PATH);
3475 options->DataDirectory = p;
3476 return 0;
3477 #else
3478 const char *d = options->DataDirectory;
3479 if (!d)
3480 d = "~/.tor";
3482 if (strncmp(d,"~/",2) == 0) {
3483 char *fn = expand_filename(d);
3484 if (!fn) {
3485 log_err(LD_CONFIG,"Failed to expand filename \"%s\".", d);
3486 return -1;
3488 if (!options->DataDirectory && !strcmp(fn,"/.tor")) {
3489 /* If our homedir is /, we probably don't want to use it. */
3490 /* Default to LOCALSTATEDIR/tor which is probably closer to what we
3491 * want. */
3492 log_warn(LD_CONFIG,
3493 "Default DataDirectory is \"~/.tor\". This expands to "
3494 "\"%s\", which is probably not what you want. Using \"%s/tor\" "
3495 "instead", fn, LOCALSTATEDIR);
3496 tor_free(fn);
3497 fn = tor_strdup(LOCALSTATEDIR"/tor");
3500 tor_free(options->DataDirectory);
3501 options->DataDirectory = fn;
3503 return 0;
3504 #endif
3507 /** Check and normalize the value of options->DataDirectory; return 0 if it
3508 * sane, -1 otherwise. */
3509 static int
3510 validate_data_directory(or_options_t *options)
3512 if (normalize_data_directory(options) < 0)
3513 return -1;
3514 tor_assert(options->DataDirectory);
3515 if (strlen(options->DataDirectory) > (512-128)) {
3516 log_err(LD_CONFIG, "DataDirectory is too long.");
3517 return -1;
3519 return 0;
3522 /** This string must remain the same forevermore. It is how we
3523 * recognize that the torrc file doesn't need to be backed up. */
3524 #define GENERATED_FILE_PREFIX "# This file was generated by Tor; " \
3525 "if you edit it, comments will not be preserved"
3526 /** This string can change; it tries to give the reader an idea
3527 * that editing this file by hand is not a good plan. */
3528 #define GENERATED_FILE_COMMENT "# The old torrc file was renamed " \
3529 "to torrc.orig.1 or similar, and Tor will ignore it"
3531 /** Save a configuration file for the configuration in <b>options</b>
3532 * into the file <b>fname</b>. If the file already exists, and
3533 * doesn't begin with GENERATED_FILE_PREFIX, rename it. Otherwise
3534 * replace it. Return 0 on success, -1 on failure. */
3535 static int
3536 write_configuration_file(const char *fname, or_options_t *options)
3538 char *old_val=NULL, *new_val=NULL, *new_conf=NULL;
3539 int rename_old = 0, r;
3540 size_t len;
3542 if (fname) {
3543 switch (file_status(fname)) {
3544 case FN_FILE:
3545 old_val = read_file_to_str(fname, 0, NULL);
3546 if (strcmpstart(old_val, GENERATED_FILE_PREFIX)) {
3547 rename_old = 1;
3549 tor_free(old_val);
3550 break;
3551 case FN_NOENT:
3552 break;
3553 case FN_ERROR:
3554 case FN_DIR:
3555 default:
3556 log_warn(LD_CONFIG,
3557 "Config file \"%s\" is not a file? Failing.", fname);
3558 return -1;
3562 if (!(new_conf = options_dump(options, 1))) {
3563 log_warn(LD_BUG, "Couldn't get configuration string");
3564 goto err;
3567 len = strlen(new_conf)+256;
3568 new_val = tor_malloc(len);
3569 tor_snprintf(new_val, len, "%s\n%s\n\n%s",
3570 GENERATED_FILE_PREFIX, GENERATED_FILE_COMMENT, new_conf);
3572 if (rename_old) {
3573 int i = 1;
3574 size_t fn_tmp_len = strlen(fname)+32;
3575 char *fn_tmp;
3576 tor_assert(fn_tmp_len > strlen(fname)); /*check for overflow*/
3577 fn_tmp = tor_malloc(fn_tmp_len);
3578 while (1) {
3579 if (tor_snprintf(fn_tmp, fn_tmp_len, "%s.orig.%d", fname, i)<0) {
3580 log_warn(LD_BUG, "tor_snprintf failed inexplicably");
3581 tor_free(fn_tmp);
3582 goto err;
3584 if (file_status(fn_tmp) == FN_NOENT)
3585 break;
3586 ++i;
3588 log_notice(LD_CONFIG, "Renaming old configuration file to \"%s\"", fn_tmp);
3589 if (rename(fname, fn_tmp) < 0) {
3590 log_warn(LD_FS,
3591 "Couldn't rename configuration file \"%s\" to \"%s\": %s",
3592 fname, fn_tmp, strerror(errno));
3593 tor_free(fn_tmp);
3594 goto err;
3596 tor_free(fn_tmp);
3599 if (write_str_to_file(fname, new_val, 0) < 0)
3600 goto err;
3602 r = 0;
3603 goto done;
3604 err:
3605 r = -1;
3606 done:
3607 tor_free(new_val);
3608 tor_free(new_conf);
3609 return r;
3613 * Save the current configuration file value to disk. Return 0 on
3614 * success, -1 on failure.
3617 options_save_current(void)
3619 if (torrc_fname) {
3620 /* This fails if we can't write to our configuration file.
3622 * If we try falling back to datadirectory or something, we have a better
3623 * chance of saving the configuration, but a better chance of doing
3624 * something the user never expected. Let's just warn instead. */
3625 return write_configuration_file(torrc_fname, get_options());
3627 return write_configuration_file(get_default_conf_file(), get_options());
3630 /** Mapping from a unit name to a multiplier for converting that unit into a
3631 * base unit. */
3632 struct unit_table_t {
3633 const char *unit;
3634 uint64_t multiplier;
3637 static struct unit_table_t memory_units[] = {
3638 { "", 1 },
3639 { "b", 1<< 0 },
3640 { "byte", 1<< 0 },
3641 { "bytes", 1<< 0 },
3642 { "kb", 1<<10 },
3643 { "kilobyte", 1<<10 },
3644 { "kilobytes", 1<<10 },
3645 { "m", 1<<20 },
3646 { "mb", 1<<20 },
3647 { "megabyte", 1<<20 },
3648 { "megabytes", 1<<20 },
3649 { "gb", 1<<30 },
3650 { "gigabyte", 1<<30 },
3651 { "gigabytes", 1<<30 },
3652 { "tb", U64_LITERAL(1)<<40 },
3653 { "terabyte", U64_LITERAL(1)<<40 },
3654 { "terabytes", U64_LITERAL(1)<<40 },
3655 { NULL, 0 },
3658 static struct unit_table_t time_units[] = {
3659 { "", 1 },
3660 { "second", 1 },
3661 { "seconds", 1 },
3662 { "minute", 60 },
3663 { "minutes", 60 },
3664 { "hour", 60*60 },
3665 { "hours", 60*60 },
3666 { "day", 24*60*60 },
3667 { "days", 24*60*60 },
3668 { "week", 7*24*60*60 },
3669 { "weeks", 7*24*60*60 },
3670 { NULL, 0 },
3673 /** Parse a string <b>val</b> containing a number, zero or more
3674 * spaces, and an optional unit string. If the unit appears in the
3675 * table <b>u</b>, then multiply the number by the unit multiplier.
3676 * On success, set *<b>ok</b> to 1 and return this product.
3677 * Otherwise, set *<b>ok</b> to 0.
3679 static uint64_t
3680 config_parse_units(const char *val, struct unit_table_t *u, int *ok)
3682 uint64_t v;
3683 char *cp;
3685 tor_assert(ok);
3687 v = tor_parse_uint64(val, 10, 0, UINT64_MAX, ok, &cp);
3688 if (!*ok)
3689 return 0;
3690 if (!cp) {
3691 *ok = 1;
3692 return v;
3694 while (TOR_ISSPACE(*cp))
3695 ++cp;
3696 for ( ;u->unit;++u) {
3697 if (!strcasecmp(u->unit, cp)) {
3698 v *= u->multiplier;
3699 *ok = 1;
3700 return v;
3703 log_warn(LD_CONFIG, "Unknown unit '%s'.", cp);
3704 *ok = 0;
3705 return 0;
3708 /** Parse a string in the format "number unit", where unit is a unit of
3709 * information (byte, KB, M, etc). On success, set *<b>ok</b> to true
3710 * and return the number of bytes specified. Otherwise, set
3711 * *<b>ok</b> to false and return 0. */
3712 static uint64_t
3713 config_parse_memunit(const char *s, int *ok)
3715 return config_parse_units(s, memory_units, ok);
3718 /** Parse a string in the format "number unit", where unit is a unit of time.
3719 * On success, set *<b>ok</b> to true and return the number of seconds in
3720 * the provided interval. Otherwise, set *<b>ok</b> to 0 and return -1.
3722 static int
3723 config_parse_interval(const char *s, int *ok)
3725 uint64_t r;
3726 r = config_parse_units(s, time_units, ok);
3727 if (!ok)
3728 return -1;
3729 if (r > INT_MAX) {
3730 log_warn(LD_CONFIG, "Interval '%s' is too long", s);
3731 *ok = 0;
3732 return -1;
3734 return (int)r;
3738 * Initialize the libevent library.
3740 static void
3741 init_libevent(void)
3743 configure_libevent_logging();
3744 /* If the kernel complains that some method (say, epoll) doesn't
3745 * exist, we don't care about it, since libevent will cope.
3747 suppress_libevent_log_msg("Function not implemented");
3748 #ifdef __APPLE__
3749 if (decode_libevent_version() < LE_11B) {
3750 setenv("EVENT_NOKQUEUE","1",1);
3751 } else if (!getenv("EVENT_NOKQUEUE")) {
3752 const char *ver = NULL;
3753 #ifdef HAVE_EVENT_GET_VERSION
3754 ver = event_get_version();
3755 #endif
3756 /* If we're 1.1b or later, we'd better have get_version() */
3757 tor_assert(ver);
3758 log(LOG_NOTICE, LD_GENERAL, "Enabling experimental OS X kqueue support "
3759 "with libevent %s. If this turns out to not work, "
3760 "set the environment variable EVENT_NOKQUEUE, and tell the Tor "
3761 "developers.", ver);
3763 #endif
3764 event_init();
3765 suppress_libevent_log_msg(NULL);
3766 #if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
3767 /* Making this a NOTICE for now so we can link bugs to a libevent versions
3768 * or methods better. */
3769 log(LOG_NOTICE, LD_GENERAL,
3770 "Initialized libevent version %s using method %s. Good.",
3771 event_get_version(), event_get_method());
3772 check_libevent_version(event_get_method(), get_options()->ORPort != 0);
3773 #else
3774 log(LOG_NOTICE, LD_GENERAL,
3775 "Initialized old libevent (version 1.0b or earlier).");
3776 log(LOG_WARN, LD_GENERAL,
3777 "You have a *VERY* old version of libevent. It is likely to be buggy; "
3778 "please build Tor with a more recent version.");
3779 #endif
3782 #if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
3783 static const struct {
3784 const char *name; le_version_t version;
3785 } le_version_table[] = {
3786 /* earlier versions don't have get_version. */
3787 { "1.0c", LE_10C },
3788 { "1.0d", LE_10D },
3789 { "1.0e", LE_10E },
3790 { "1.1", LE_11 },
3791 { "1.1a", LE_11A },
3792 { "1.1b", LE_11B },
3793 { "1.2", LE_12 },
3794 { "1.2a", LE_12A },
3795 { NULL, LE_OTHER }
3798 static le_version_t
3799 decode_libevent_version(void)
3801 const char *v = event_get_version();
3802 int i;
3803 for (i=0; le_version_table[i].name; ++i) {
3804 if (!strcmp(le_version_table[i].name, v)) {
3805 return le_version_table[i].version;
3808 return LE_OTHER;
3812 * Compare the given libevent method and version to a list of versions
3813 * which are known not to work. Warn the user as appropriate.
3816 static void
3817 check_libevent_version(const char *m, int server)
3819 int buggy = 0, iffy = 0, slow = 0;
3820 le_version_t version;
3821 const char *v = event_get_version();
3822 const char *badness = NULL;
3824 version = decode_libevent_version();
3826 /* XXX Would it be worthwhile disabling the methods that we know
3827 * are buggy, rather than just warning about them and then proceeding
3828 * to use them? If so, we should probably not wrap this whole thing
3829 * in HAVE_EVENT_GET_VERSION and HAVE_EVENT_GET_METHOD. -RD */
3830 /* XXXX The problem is that it's not trivial to get libevent to change it's
3831 * method once it's initialized, and it's not trivial to tell what method it
3832 * will use without initializing it. I guess we could preemptively disable
3833 * buggy libevent modes based on the version _before_ initializing it,
3834 * though, but then there's no good way (afaict) to warn "I would have used
3835 * kqueue, but instead I'm using select." -NM */
3836 if (!strcmp(m, "kqueue")) {
3837 if (version < LE_11B)
3838 buggy = 1;
3839 } else if (!strcmp(m, "epoll")) {
3840 if (version < LE_11)
3841 iffy = 1;
3842 } else if (!strcmp(m, "poll")) {
3843 if (version < LE_10E)
3844 buggy = 1;
3845 else if (version < LE_11)
3846 slow = 1;
3847 } else if (!strcmp(m, "select")) {
3848 if (version < LE_11)
3849 slow = 1;
3850 } else if (!strcmp(m, "win32")) {
3851 if (version < LE_11B)
3852 buggy = 1;
3855 if (buggy) {
3856 log(LOG_WARN, LD_GENERAL,
3857 "There are known bugs in using %s with libevent %s. "
3858 "Please use the latest version of libevent.", m, v);
3859 badness = "BROKEN";
3860 } else if (iffy) {
3861 log(LOG_WARN, LD_GENERAL,
3862 "There are minor bugs in using %s with libevent %s. "
3863 "You may want to use the latest version of libevent.", m, v);
3864 badness = "BUGGY";
3865 } else if (slow && server) {
3866 log(LOG_WARN, LD_GENERAL,
3867 "libevent %s can be very slow with %s. "
3868 "When running a server, please use the latest version of libevent.",
3869 v,m);
3870 badness = "SLOW";
3872 if (badness) {
3873 control_event_general_status(LOG_WARN,
3874 "BAD_LIBEVENT VERSION=%s METHOD=%s BADNESS=%s RECOVERED=NO",
3875 v, m, badness);
3879 #else
3880 static le_version_t
3881 decode_libevent_version(void)
3883 return LE_OLD;
3885 #endif
3887 /** Return the persistent state struct for this Tor. */
3888 or_state_t *
3889 get_or_state(void)
3891 tor_assert(global_state);
3892 return global_state;
3895 /** Return the filename used to write and read the persistent state. */
3896 static char *
3897 get_or_state_fname(void)
3899 char *fname = NULL;
3900 or_options_t *options = get_options();
3901 size_t len = strlen(options->DataDirectory) + 16;
3902 fname = tor_malloc(len);
3903 tor_snprintf(fname, len, "%s/state", options->DataDirectory);
3904 return fname;
3907 /** Return 0 if every setting in <b>state</b> is reasonable, and a
3908 * permissible transition from <b>old_state</b>. Else warn and return -1.
3909 * Should have no side effects, except for normalizing the contents of
3910 * <b>state</b>.
3912 /* XXX from_setconf is here because of bug 238 */
3913 static int
3914 or_state_validate(or_state_t *old_state, or_state_t *state,
3915 int from_setconf, char **msg)
3917 /* We don't use these; only options do. Still, we need to match that
3918 * signature. */
3919 (void) from_setconf;
3920 (void) old_state;
3921 if (entry_guards_parse_state(state, 0, msg)<0) {
3922 return -1;
3924 if (state->TorVersion) {
3925 tor_version_t v;
3926 if (tor_version_parse(state->TorVersion, &v)) {
3927 log_warn(LD_GENERAL, "Can't parse Tor version '%s' from your state "
3928 "file. Proceeding anyway.", state->TorVersion);
3929 } else { /* take action based on v */
3930 if (tor_version_as_new_as(state->TorVersion, "0.1.1.10-alpha") &&
3931 !tor_version_as_new_as(state->TorVersion, "0.1.1.16-rc-cvs")) {
3932 log_notice(LD_CONFIG, "Detected state file from buggy version '%s'. "
3933 "Enabling workaround to choose working entry guards.",
3934 state->TorVersion);
3935 config_free_lines(state->EntryGuards);
3936 state->EntryGuards = NULL;
3940 return 0;
3943 /** Replace the current persistent state with <b>new_state</b> */
3944 static void
3945 or_state_set(or_state_t *new_state)
3947 char *err = NULL;
3948 tor_assert(new_state);
3949 if (global_state)
3950 config_free(&state_format, global_state);
3951 global_state = new_state;
3952 if (entry_guards_parse_state(global_state, 1, &err)<0) {
3953 log_warn(LD_GENERAL,"%s",err);
3954 tor_free(err);
3956 if (rep_hist_load_state(global_state, &err)<0) {
3957 log_warn(LD_GENERAL,"Unparseable bandwidth history state: %s",err);
3958 tor_free(err);
3962 /** Reload the persistent state from disk, generating a new state as needed.
3963 * Return 0 on success, less than 0 on failure.
3966 or_state_load(void)
3968 or_state_t *new_state = NULL;
3969 char *contents = NULL, *fname;
3970 char *errmsg = NULL;
3971 int r = -1, badstate = 0;
3973 fname = get_or_state_fname();
3974 switch (file_status(fname)) {
3975 case FN_FILE:
3976 if (!(contents = read_file_to_str(fname, 0, NULL))) {
3977 log_warn(LD_FS, "Unable to read state file \"%s\"", fname);
3978 goto done;
3980 break;
3981 case FN_NOENT:
3982 break;
3983 case FN_ERROR:
3984 case FN_DIR:
3985 default:
3986 log_warn(LD_GENERAL,"State file \"%s\" is not a file? Failing.", fname);
3987 goto done;
3989 new_state = tor_malloc_zero(sizeof(or_state_t));
3990 new_state->_magic = OR_STATE_MAGIC;
3991 config_init(&state_format, new_state);
3992 if (contents) {
3993 config_line_t *lines=NULL;
3994 int assign_retval;
3995 if (config_get_lines(contents, &lines)<0)
3996 goto done;
3997 assign_retval = config_assign(&state_format, new_state,
3998 lines, 0, 0, &errmsg);
3999 config_free_lines(lines);
4000 if (assign_retval<0)
4001 badstate = 1;
4002 if (errmsg) {
4003 log_warn(LD_GENERAL, "%s", errmsg);
4004 tor_free(errmsg);
4008 if (!badstate && or_state_validate(NULL, new_state, 1, &errmsg) < 0)
4009 badstate = 1;
4011 if (errmsg) {
4012 log_warn(LD_GENERAL, "%s", errmsg);
4013 tor_free(errmsg);
4016 if (badstate && !contents) {
4017 log_warn(LD_BUG, "Uh oh. We couldn't even validate our own default state."
4018 " This is a bug in Tor.");
4019 goto done;
4020 } else if (badstate && contents) {
4021 int i;
4022 file_status_t status;
4023 size_t len = strlen(fname)+16;
4024 char *fname2 = tor_malloc(len);
4025 for (i = 0; i < 100; ++i) {
4026 tor_snprintf(fname2, len, "%s.%d", fname, i);
4027 status = file_status(fname2);
4028 if (status == FN_NOENT)
4029 break;
4031 if (i == 100) {
4032 log_warn(LD_BUG, "Unable to parse state in \"%s\"; too many saved bad "
4033 "state files to move aside. Discarding the old state file.",
4034 fname);
4035 unlink(fname);
4036 } else {
4037 log_warn(LD_BUG, "Unable to parse state in \"%s\". Moving it aside "
4038 "to \"%s\". This could be a bug in Tor; please tell "
4039 "the developers.", fname, fname2);
4040 rename(fname, fname2);
4042 tor_free(fname2);
4043 tor_free(contents);
4044 config_free(&state_format, new_state);
4046 new_state = tor_malloc_zero(sizeof(or_state_t));
4047 new_state->_magic = OR_STATE_MAGIC;
4048 config_init(&state_format, new_state);
4049 } else if (contents) {
4050 log_info(LD_GENERAL, "Loaded state from \"%s\"", fname);
4051 } else {
4052 log_info(LD_GENERAL, "Initialized state");
4054 or_state_set(new_state);
4055 new_state = NULL;
4056 if (!contents) {
4057 global_state->next_write = 0;
4058 or_state_save(time(NULL));
4060 r = 0;
4062 done:
4063 tor_free(fname);
4064 tor_free(contents);
4065 if (new_state)
4066 config_free(&state_format, new_state);
4068 return r;
4071 /** Write the persistent state to disk. Return 0 for success, <0 on failure. */
4073 or_state_save(time_t now)
4075 char *state, *contents;
4076 char tbuf[ISO_TIME_LEN+1];
4077 size_t len;
4078 char *fname;
4080 tor_assert(global_state);
4082 if (global_state->next_write > now)
4083 return 0;
4085 /* Call everything else that might dirty the state even more, in order
4086 * to avoid redundant writes. */
4087 entry_guards_update_state(global_state);
4088 rep_hist_update_state(global_state);
4089 if (accounting_is_enabled(get_options()))
4090 accounting_run_housekeeping(now);
4092 global_state->LastWritten = time(NULL);
4093 tor_free(global_state->TorVersion);
4094 global_state->TorVersion = tor_strdup("Tor " VERSION);
4095 state = config_dump(&state_format, global_state, 1, 0);
4096 len = strlen(state)+256;
4097 contents = tor_malloc(len);
4098 format_local_iso_time(tbuf, time(NULL));
4099 tor_snprintf(contents, len,
4100 "# Tor state file last generated on %s local time\n"
4101 "# Other times below are in GMT\n"
4102 "# You *do not* need to edit this file.\n\n%s",
4103 tbuf, state);
4104 tor_free(state);
4105 fname = get_or_state_fname();
4106 if (write_str_to_file(fname, contents, 0)<0) {
4107 log_warn(LD_FS, "Unable to write state to file \"%s\"", fname);
4108 tor_free(fname);
4109 tor_free(contents);
4110 return -1;
4112 log_info(LD_GENERAL, "Saved state to \"%s\"", fname);
4113 tor_free(fname);
4114 tor_free(contents);
4116 global_state->next_write = TIME_MAX;
4117 return 0;
4120 /** Helper to implement GETINFO functions about configuration variables (not
4121 * their values). Given a "config/names" question, set *<b>answer</b> to a
4122 * new string describing the supported configuration variables and their
4123 * types. */
4125 getinfo_helper_config(control_connection_t *conn,
4126 const char *question, char **answer)
4128 (void) conn;
4129 if (!strcmp(question, "config/names")) {
4130 smartlist_t *sl = smartlist_create();
4131 int i;
4132 for (i = 0; _option_vars[i].name; ++i) {
4133 config_var_t *var = &_option_vars[i];
4134 const char *type, *desc;
4135 char *line;
4136 size_t len;
4137 desc = config_find_description(&options_format, var->name);
4138 switch (var->type) {
4139 case CONFIG_TYPE_STRING: type = "String"; break;
4140 case CONFIG_TYPE_UINT: type = "Integer"; break;
4141 case CONFIG_TYPE_INTERVAL: type = "TimeInterval"; break;
4142 case CONFIG_TYPE_MEMUNIT: type = "DataSize"; break;
4143 case CONFIG_TYPE_DOUBLE: type = "Float"; break;
4144 case CONFIG_TYPE_BOOL: type = "Boolean"; break;
4145 case CONFIG_TYPE_ISOTIME: type = "Time"; break;
4146 case CONFIG_TYPE_CSV: type = "CommaList"; break;
4147 case CONFIG_TYPE_LINELIST: type = "LineList"; break;
4148 case CONFIG_TYPE_LINELIST_S: type = "Dependant"; break;
4149 case CONFIG_TYPE_LINELIST_V: type = "Virtual"; break;
4150 default:
4151 case CONFIG_TYPE_OBSOLETE:
4152 type = NULL; break;
4154 if (!type)
4155 continue;
4156 len = strlen(var->name)+strlen(type)+16;
4157 if (desc)
4158 len += strlen(desc);
4159 line = tor_malloc(len);
4160 if (desc)
4161 tor_snprintf(line, len, "%s %s %s\n",var->name,type,desc);
4162 else
4163 tor_snprintf(line, len, "%s %s\n",var->name,type);
4164 smartlist_add(sl, line);
4166 *answer = smartlist_join_strings(sl, "", 0, NULL);
4167 SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
4168 smartlist_free(sl);
4170 return 0;
4173 #include "../common/ht.h"
4174 #include "../common/test.h"
4176 extern const char aes_c_id[];
4177 extern const char compat_c_id[];
4178 extern const char container_c_id[];
4179 extern const char crypto_c_id[];
4180 extern const char log_c_id[];
4181 extern const char torgzip_c_id[];
4182 extern const char tortls_c_id[];
4183 extern const char util_c_id[];
4185 extern const char buffers_c_id[];
4186 extern const char circuitbuild_c_id[];
4187 extern const char circuitlist_c_id[];
4188 extern const char circuituse_c_id[];
4189 extern const char command_c_id[];
4190 // extern const char config_c_id[];
4191 extern const char connection_c_id[];
4192 extern const char connection_edge_c_id[];
4193 extern const char connection_or_c_id[];
4194 extern const char control_c_id[];
4195 extern const char cpuworker_c_id[];
4196 extern const char directory_c_id[];
4197 extern const char dirserv_c_id[];
4198 extern const char dns_c_id[];
4199 extern const char hibernate_c_id[];
4200 extern const char main_c_id[];
4201 extern const char onion_c_id[];
4202 extern const char policies_c_id[];
4203 extern const char relay_c_id[];
4204 extern const char rendclient_c_id[];
4205 extern const char rendcommon_c_id[];
4206 extern const char rendmid_c_id[];
4207 extern const char rendservice_c_id[];
4208 extern const char rephist_c_id[];
4209 extern const char router_c_id[];
4210 extern const char routerlist_c_id[];
4211 extern const char routerparse_c_id[];
4213 /** Dump the version of every file to the log. */
4214 static void
4215 print_svn_version(void)
4217 puts(AES_H_ID);
4218 puts(COMPAT_H_ID);
4219 puts(CONTAINER_H_ID);
4220 puts(CRYPTO_H_ID);
4221 puts(HT_H_ID);
4222 puts(TEST_H_ID);
4223 puts(LOG_H_ID);
4224 puts(TORGZIP_H_ID);
4225 puts(TORINT_H_ID);
4226 puts(TORTLS_H_ID);
4227 puts(UTIL_H_ID);
4228 puts(aes_c_id);
4229 puts(compat_c_id);
4230 puts(container_c_id);
4231 puts(crypto_c_id);
4232 puts(log_c_id);
4233 puts(torgzip_c_id);
4234 puts(tortls_c_id);
4235 puts(util_c_id);
4237 puts(OR_H_ID);
4238 puts(buffers_c_id);
4239 puts(circuitbuild_c_id);
4240 puts(circuitlist_c_id);
4241 puts(circuituse_c_id);
4242 puts(command_c_id);
4243 puts(config_c_id);
4244 puts(connection_c_id);
4245 puts(connection_edge_c_id);
4246 puts(connection_or_c_id);
4247 puts(control_c_id);
4248 puts(cpuworker_c_id);
4249 puts(directory_c_id);
4250 puts(dirserv_c_id);
4251 puts(dns_c_id);
4252 puts(hibernate_c_id);
4253 puts(main_c_id);
4254 puts(onion_c_id);
4255 puts(policies_c_id);
4256 puts(relay_c_id);
4257 puts(rendclient_c_id);
4258 puts(rendcommon_c_id);
4259 puts(rendmid_c_id);
4260 puts(rendservice_c_id);
4261 puts(rephist_c_id);
4262 puts(router_c_id);
4263 puts(routerlist_c_id);
4264 puts(routerparse_c_id);