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 */
6 const char config_c_id
[] = \
11 * \brief Code to parse and interpret configuration files.
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. */
40 /** An abbreviation for a configuration option allowed on the command line. */
41 typedef struct config_abbrev_t
{
42 const char *abbreviated
;
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
[] = {
58 PLURAL(LongLivedPort
),
59 PLURAL(HiddenServiceNode
),
60 PLURAL(HiddenServiceExcludeNode
),
63 PLURAL(RendExcludeNode
),
64 PLURAL(StrictEntryNode
),
65 PLURAL(StrictExitNode
),
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},
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 },
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
101 off_t var_offset
; /**< Offset of the corresponding member of or_options_t. */
102 const char *initvalue
; /**< String (or null) describing initial value. */
105 /** An entry for config_vars: "The option <b>name</b> has type
106 * CONFIG_TYPE_<b>conftype</b>, and corresponds to
107 * or_options_t.<b>member</b>"
109 #define VAR(name,conftype,member,initvalue) \
110 { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_options_t, member), \
112 /** An entry for config_vars: "The option <b>name</b> is obsolete." */
113 #define OBSOLETE(name) { name, CONFIG_TYPE_OBSOLETE, 0, NULL }
115 /** Array of configuration options. Until we disallow nonstandard
116 * abbreviations, order is significant, since the first matching option will
119 static config_var_t _option_vars
[] = {
120 OBSOLETE("AccountingMaxKB"),
121 VAR("AccountingMax", MEMUNIT
, AccountingMax
, "0 bytes"),
122 VAR("AccountingStart", STRING
, AccountingStart
, NULL
),
123 VAR("Address", STRING
, Address
, NULL
),
124 VAR("__AllDirActionsPrivate",BOOL
, AllDirActionsPrivate
, "0"),
125 VAR("AllowInvalidNodes", CSV
, AllowInvalidNodes
,
126 "middle,rendezvous"),
127 VAR("AllowNonRFC953Hostnames", BOOL
, AllowNonRFC953Hostnames
, "0"),
128 VAR("AssumeReachable", BOOL
, AssumeReachable
, "0"),
129 VAR("AuthDirBadExit", LINELIST
, AuthDirBadExit
, NULL
),
130 VAR("AuthDirInvalid", LINELIST
, AuthDirInvalid
, NULL
),
131 VAR("AuthDirReject", LINELIST
, AuthDirReject
, NULL
),
132 VAR("AuthDirRejectUnlisted",BOOL
, AuthDirRejectUnlisted
,"0"),
133 VAR("AuthDirListBadExits", BOOL
, AuthDirListBadExits
, "0"),
134 VAR("AuthoritativeDirectory",BOOL
, AuthoritativeDir
, "0"),
135 VAR("AvoidDiskWrites", BOOL
, AvoidDiskWrites
, "0"),
136 VAR("BandwidthBurst", MEMUNIT
, BandwidthBurst
, "6 MB"),
137 VAR("BandwidthRate", MEMUNIT
, BandwidthRate
, "3 MB"),
138 VAR("CircuitBuildTimeout", INTERVAL
, CircuitBuildTimeout
, "1 minute"),
139 VAR("CircuitIdleTimeout", INTERVAL
, CircuitIdleTimeout
, "1 hour"),
140 VAR("ClientOnly", BOOL
, ClientOnly
, "0"),
141 VAR("ConnLimit", UINT
, ConnLimit
, "1000"),
142 VAR("ContactInfo", STRING
, ContactInfo
, NULL
),
143 VAR("ControlListenAddress",LINELIST
, ControlListenAddress
, NULL
),
144 VAR("ControlPort", UINT
, ControlPort
, "0"),
145 VAR("CookieAuthentication",BOOL
, CookieAuthentication
, "0"),
146 VAR("DataDirectory", STRING
, DataDirectory
, NULL
),
147 OBSOLETE("DebugLogFile"),
148 VAR("DirAllowPrivateAddresses",BOOL
, DirAllowPrivateAddresses
, NULL
),
149 VAR("DirListenAddress", LINELIST
, DirListenAddress
, NULL
),
150 OBSOLETE("DirFetchPeriod"),
151 VAR("DirPolicy", LINELIST
, DirPolicy
, NULL
),
152 VAR("DirPort", UINT
, DirPort
, "0"),
153 OBSOLETE("DirPostPeriod"),
154 VAR("DirServer", LINELIST
, DirServers
, NULL
),
155 VAR("EnforceDistinctSubnets", BOOL
, EnforceDistinctSubnets
,"1"),
156 VAR("EntryNodes", STRING
, EntryNodes
, NULL
),
157 VAR("ExcludeNodes", STRING
, ExcludeNodes
, NULL
),
158 VAR("ExitNodes", STRING
, ExitNodes
, NULL
),
159 VAR("ExitPolicy", LINELIST
, ExitPolicy
, NULL
),
160 VAR("ExitPolicyRejectPrivate", BOOL
, ExitPolicyRejectPrivate
, "1"),
161 VAR("FascistFirewall", BOOL
, FascistFirewall
, "0"),
162 VAR("FirewallPorts", CSV
, FirewallPorts
, ""),
163 VAR("FastFirstHopPK", BOOL
, FastFirstHopPK
, "1"),
164 VAR("FetchServerDescriptors",BOOL
, FetchServerDescriptors
,"1"),
165 VAR("FetchHidServDescriptors",BOOL
, FetchHidServDescriptors
, "1"),
166 VAR("FetchUselessDescriptors",BOOL
, FetchUselessDescriptors
, "0"),
167 VAR("Group", STRING
, Group
, NULL
),
168 VAR("HardwareAccel", BOOL
, HardwareAccel
, "0"),
169 VAR("HashedControlPassword",STRING
, HashedControlPassword
, NULL
),
170 VAR("HiddenServiceDir", LINELIST_S
, RendConfigLines
, NULL
),
171 VAR("HiddenServiceExcludeNodes", LINELIST_S
, RendConfigLines
, NULL
),
172 VAR("HiddenServiceNodes", LINELIST_S
, RendConfigLines
, NULL
),
173 VAR("HiddenServiceOptions",LINELIST_V
, RendConfigLines
, NULL
),
174 VAR("HiddenServicePort", LINELIST_S
, RendConfigLines
, NULL
),
175 VAR("HSAuthoritativeDir", BOOL
, HSAuthoritativeDir
, "0"),
176 VAR("HttpProxy", STRING
, HttpProxy
, NULL
),
177 VAR("HttpProxyAuthenticator",STRING
, HttpProxyAuthenticator
,NULL
),
178 VAR("HttpsProxy", STRING
, HttpsProxy
, NULL
),
179 VAR("HttpsProxyAuthenticator",STRING
,HttpsProxyAuthenticator
,NULL
),
180 OBSOLETE("IgnoreVersion"),
181 VAR("KeepalivePeriod", INTERVAL
, KeepalivePeriod
, "5 minutes"),
182 VAR("Log", LINELIST
, Logs
, NULL
),
183 OBSOLETE("LinkPadding"),
184 OBSOLETE("LogLevel"),
186 VAR("LongLivedPorts", CSV
, LongLivedPorts
,
187 "21,22,706,1863,5050,5190,5222,5223,6667,6697,8300"),
188 VAR("MapAddress", LINELIST
, AddressMap
, NULL
),
189 VAR("MaxAdvertisedBandwidth",MEMUNIT
,MaxAdvertisedBandwidth
,"128 TB"),
190 VAR("MaxCircuitDirtiness", INTERVAL
, MaxCircuitDirtiness
, "10 minutes"),
191 VAR("MaxOnionsPending", UINT
, MaxOnionsPending
, "100"),
192 OBSOLETE("MonthlyAccountingStart"),
193 VAR("MyFamily", STRING
, MyFamily
, NULL
),
194 VAR("NewCircuitPeriod", INTERVAL
, NewCircuitPeriod
, "30 seconds"),
195 VAR("NamingAuthoritativeDirectory",BOOL
, NamingAuthoritativeDir
, "0"),
196 VAR("NatdListenAddress", LINELIST
, NatdListenAddress
, NULL
),
197 VAR("NatdPort", UINT
, NatdPort
, "0"),
198 VAR("Nickname", STRING
, Nickname
, NULL
),
199 VAR("NoPublish", BOOL
, NoPublish
, "0"),
200 VAR("NodeFamily", LINELIST
, NodeFamilies
, NULL
),
201 VAR("NumCpus", UINT
, NumCpus
, "1"),
202 VAR("NumEntryGuards", UINT
, NumEntryGuards
, "3"),
203 VAR("ORListenAddress", LINELIST
, ORListenAddress
, NULL
),
204 VAR("ORPort", UINT
, ORPort
, "0"),
205 VAR("OutboundBindAddress", STRING
, OutboundBindAddress
, NULL
),
206 OBSOLETE("PathlenCoinWeight"),
207 VAR("PidFile", STRING
, PidFile
, NULL
),
208 VAR("PreferTunneledDirConns", BOOL
, PreferTunneledDirConns
, "0"),
209 VAR("ProtocolWarnings", BOOL
, ProtocolWarnings
, "0"),
210 VAR("PublishServerDescriptor",BOOL
, PublishServerDescriptor
,"1"),
211 VAR("PublishHidServDescriptors",BOOL
,PublishHidServDescriptors
, "1"),
212 VAR("ReachableAddresses", LINELIST
, ReachableAddresses
, NULL
),
213 VAR("ReachableDirAddresses",LINELIST
,ReachableDirAddresses
,NULL
),
214 VAR("ReachableORAddresses",LINELIST
, ReachableORAddresses
, NULL
),
215 VAR("RecommendedVersions", LINELIST
, RecommendedVersions
, NULL
),
216 VAR("RecommendedClientVersions", LINELIST
, RecommendedClientVersions
, NULL
),
217 VAR("RecommendedServerVersions", LINELIST
, RecommendedServerVersions
, NULL
),
218 VAR("RedirectExit", LINELIST
, RedirectExit
, NULL
),
219 VAR("RendExcludeNodes", STRING
, RendExcludeNodes
, NULL
),
220 VAR("RendNodes", STRING
, RendNodes
, NULL
),
221 VAR("RendPostPeriod", INTERVAL
, RendPostPeriod
, "1 hour"),
222 VAR("RephistTrackTime", INTERVAL
, RephistTrackTime
, "24 hours"),
223 OBSOLETE("RouterFile"),
224 VAR("RunAsDaemon", BOOL
, RunAsDaemon
, "0"),
225 VAR("RunTesting", BOOL
, RunTesting
, "0"),
226 VAR("SafeLogging", BOOL
, SafeLogging
, "1"),
227 VAR("SafeSocks", BOOL
, SafeSocks
, "0"),
228 VAR("ServerDNSAllowNonRFC953Hostnames",
229 BOOL
, ServerDNSAllowNonRFC953Hostnames
, "0"),
230 VAR("ServerDNSDetectHijacking",BOOL
, ServerDNSDetectHijacking
,"1"),
231 VAR("ServerDNSResolvConfFile", STRING
, ServerDNSResolvConfFile
, NULL
),
232 VAR("ServerDNSSearchDomains", BOOL
, ServerDNSSearchDomains
, "0"),
233 VAR("ServerDNSTestAddresses", CSV
, ServerDNSTestAddresses
,
234 "www.google.com,www.mit.edu,www.yahoo.com,www.slashdot.org"),
235 VAR("ShutdownWaitLength", INTERVAL
, ShutdownWaitLength
, "30 seconds"),
236 VAR("SocksListenAddress", LINELIST
, SocksListenAddress
, NULL
),
237 VAR("SocksPolicy", LINELIST
, SocksPolicy
, NULL
),
238 VAR("SocksPort", UINT
, SocksPort
, "9050"),
239 VAR("SocksTimeout", INTERVAL
, SocksTimeout
, "2 minutes"),
240 OBSOLETE("StatusFetchPeriod"),
241 VAR("StrictEntryNodes", BOOL
, StrictEntryNodes
, "0"),
242 VAR("StrictExitNodes", BOOL
, StrictExitNodes
, "0"),
244 VAR("TestSocks", BOOL
, TestSocks
, "0"),
245 VAR("TestVia", STRING
, TestVia
, NULL
),
246 VAR("TrackHostExits", CSV
, TrackHostExits
, NULL
),
247 VAR("TrackHostExitsExpire",INTERVAL
, TrackHostExitsExpire
, "30 minutes"),
248 OBSOLETE("TrafficShaping"),
249 VAR("TransListenAddress", LINELIST
, TransListenAddress
, NULL
),
250 VAR("TransPort", UINT
, TransPort
, "0"),
251 VAR("TunnelDirConns", BOOL
, TunnelDirConns
, "0"),
252 VAR("UseEntryGuards", BOOL
, UseEntryGuards
, "1"),
253 VAR("User", STRING
, User
, NULL
),
254 VAR("V1AuthoritativeDirectory",BOOL
, V1AuthoritativeDir
, "0"),
255 VAR("VersioningAuthoritativeDirectory",BOOL
,VersioningAuthoritativeDir
, "0"),
256 VAR("VirtualAddrNetwork", STRING
, VirtualAddrNetwork
, "127.192.0.0/10"),
257 VAR("__LeaveStreamsUnattached", BOOL
,LeaveStreamsUnattached
, "0"),
258 { NULL
, CONFIG_TYPE_OBSOLETE
, 0, NULL
}
262 #define VAR(name,conftype,member,initvalue) \
263 { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_state_t, member), \
265 static config_var_t _state_vars
[] = {
266 VAR("AccountingBytesReadInInterval", MEMUNIT
,
267 AccountingBytesReadInInterval
, NULL
),
268 VAR("AccountingBytesWrittenInInterval", MEMUNIT
,
269 AccountingBytesWrittenInInterval
, NULL
),
270 VAR("AccountingExpectedUsage", MEMUNIT
, AccountingExpectedUsage
, NULL
),
271 VAR("AccountingIntervalStart", ISOTIME
, AccountingIntervalStart
, NULL
),
272 VAR("AccountingSecondsActive", INTERVAL
, AccountingSecondsActive
, NULL
),
273 VAR("EntryGuard", LINELIST_S
, EntryGuards
, NULL
),
274 VAR("EntryGuardDownSince", LINELIST_S
, EntryGuards
, NULL
),
275 VAR("EntryGuardUnlistedSince", LINELIST_S
, EntryGuards
, NULL
),
276 VAR("EntryGuards", LINELIST_V
, EntryGuards
, NULL
),
278 VAR("BWHistoryReadEnds", ISOTIME
, BWHistoryReadEnds
, NULL
),
279 VAR("BWHistoryReadInterval", UINT
, BWHistoryReadInterval
, "900"),
280 VAR("BWHistoryReadValues", CSV
, BWHistoryReadValues
, ""),
281 VAR("BWHistoryWriteEnds", ISOTIME
, BWHistoryWriteEnds
, NULL
),
282 VAR("BWHistoryWriteInterval", UINT
, BWHistoryWriteInterval
, "900"),
283 VAR("BWHistoryWriteValues", CSV
, BWHistoryWriteValues
, ""),
285 VAR("TorVersion", STRING
, TorVersion
, NULL
),
287 VAR("LastRotatedOnionKey", ISOTIME
, LastRotatedOnionKey
, NULL
),
288 VAR("LastWritten", ISOTIME
, LastWritten
, NULL
),
290 { NULL
, CONFIG_TYPE_OBSOLETE
, 0, NULL
}
296 /** Represents an English description of a configuration variable; used when
297 * generating configuration file comments. */
298 typedef struct config_var_description_t
{
300 const char *description
;
301 } config_var_description_t
;
303 static config_var_description_t options_description
[] = {
304 /* ==== general options */
305 { "AvoidDiskWrites", "If non-zero, try to write to disk less frequently than"
306 " we would otherwise." },
307 { "BandwidthRate", "A token bucket limits the average incoming bandwidth on "
308 "this node to the specified number of bytes per second." },
309 { "BandwidthBurst", "Limit the maximum token buffer size (also known as "
310 "burst) to the given number of bytes." },
311 { "ConnLimit", "Maximum number of simultaneous sockets allowed." },
312 /* ControlListenAddress */
313 { "ControlPort", "If set, Tor will accept connections from the same machine "
314 "(localhost only) on this port, and allow those connections to control "
315 "the Tor process using the Tor Control Protocol (described in"
316 "control-spec.txt).", },
317 { "CookieAuthentication", "If this option is set to 1, don't allow any "
318 "connections to the control port except when the connecting process "
319 "can read a file that Tor creates in its data directory." },
320 { "DataDirectory", "Store working data, state, keys, and caches here." },
321 { "DirServer", "Tor only trusts directories signed with one of these "
322 "servers' keys. Used to override the standard list of directory "
324 /* { "FastFirstHopPK", "" }, */
325 /* FetchServerDescriptors, FetchHidServDescriptors,
326 * FetchUselessDescriptors */
327 { "Group", "On startup, setgid to this group." },
328 { "HardwareAccel", "If set, Tor tries to use hardware crypto accelerators "
330 /* HashedControlPassword */
331 { "HTTPProxy", "Force Tor to make all HTTP directory requests through this "
332 "host:port (or host:80 if port is not set)." },
333 { "HTTPProxyAuthenticator", "A username:password pair to be used with "
335 { "HTTPSProxy", "Force Tor to make all TLS (SSL) connectinos through this "
336 "host:port (or host:80 if port is not set)." },
337 { "HTTPSProxyAuthenticator", "A username:password pair to be used with "
339 { "KeepalivePeriod", "Send a padding cell every N seconds to keep firewalls "
340 "from closing our connections while Tor is not in use." },
341 { "Log", "Where to send logging messages. Format is "
342 "minSeverity[-maxSeverity] (stderr|stdout|syslog|file FILENAME)." },
343 { "OutboundBindAddress", "Make all outbound connections originate from the "
344 "provided IP address (only useful for multiple network interfaces)." },
345 { "PIDFile", "On startup, write our PID to this file. On clean shutdown, "
346 "remove the file." },
347 { "PreferTunneledDirConns", "If non-zero, avoid directory servers that "
348 "don't support tunneled conncetions." },
349 /* PreferTunneledDirConns */
350 /* ProtocolWarnings */
351 /* RephistTrackTime */
352 { "RunAsDaemon", "If set, Tor forks and daemonizes to the background when "
353 "started. Unix only." },
354 { "SafeLogging", "If set to 0, Tor logs potentially sensitive strings "
355 "rather than replacing them with the string [scrubbed]." },
356 { "TunnelDirConns", "If non-zero, when a directory server we contact "
357 "supports it, we will build a one-hop circuit and make an encrypted "
358 "connection via its ORPort." },
359 { "User", "On startup, setuid to this user" },
361 /* ==== client options */
362 { "AllowInvalidNodes", "Where on our circuits should Tor allow servers "
363 "that the directory authorities haven't called \"valid\"?" },
364 { "AllowNonRFC953Hostnames", "If set to 1, we don't automatically reject "
365 "hostnames for having invalid characters." },
366 /* CircuitBuildTimeout, CircuitIdleTimeout */
367 { "ClientOnly", "If set to 1, Tor will under no circumstances run as a "
368 "server, even if ORPort is enabled." },
369 { "EntryNodes", "A list of preferred entry nodes to use for the first hop "
370 "in circuits, when possible." },
371 /* { "EnforceDistinctSubnets" , "" }, */
372 { "ExitNodes", "A list of preferred nodes to use for the last hop in "
373 "circuits, when possible." },
374 { "ExcludeNodes", "A list of nodes never to use when building a circuit." },
375 { "FascistFirewall", "If set, Tor will only create outgoing connections to "
376 "servers running on the ports listed in FirewallPorts." },
377 { "FirewallPorts", "A list of ports that we can connect to. Only used "
378 "when FascistFirewall is set." },
379 { "LongLivedPorts", "A list of ports for services that tend to require "
380 "high-uptime connections." },
381 { "MapAddress", "Force Tor to treat all requests for one address as if "
382 "they were for another." },
383 { "NewCircuitPeriod", "Force Tor to consider whether to build a new circuit "
384 "every NUM seconds." },
385 { "MaxCircuitDirtiness", "Do not attach new streams to a circuit that has "
386 "been used more than this many seconds ago." },
387 /* NatdPort, NatdListenAddress */
388 { "NodeFamily", "A list of servers that constitute a 'family' and should "
389 "never be used in the same circuit." },
390 { "NumEntryGuards", "How many entry guards should we keep at a time?" },
391 /* PathlenCoinWeight */
392 { "ReachableAddresses", "Addresses we can connect to, as IP/bits:port-port. "
393 "By default, we assume all addresses are reachable." },
394 /* reachablediraddresses, reachableoraddresses. */
395 { "RendNodes", "A list of preferred nodes to use for a rendezvous point, "
397 { "RendExcludenodes", "A list of nodes never to use as rendezvous points." },
399 { "SOCKSPort", "The port where we listen for SOCKS connections from "
401 { "SOCKSListenAddress", "Bind to this address to listen to connections from "
402 "SOCKS-speaking applications." },
403 { "SOCKSPolicy", "Set an entry policy to limit which addresses can connect "
404 "to the SOCKSPort." },
406 { "StrictExitNodes", "If set, Tor will fail to operate when none of the "
407 "configured ExitNodes can be used." },
408 { "StrictEntryNodes", "If set, Tor will fail to operate when none of the "
409 "configured EntryNodes can be used." },
411 { "TrackHostsExit", "Hosts and domains which should, if possible, be "
412 "accessed from the same exit node each time we connect to them." },
413 { "TrackHostsExitExpire", "Time after which we forget which exit we were "
414 "using to connect to hosts in TrackHostsExit." },
415 /* "TransPort", "TransListenAddress */
416 { "UseEntryGuards", "Set to 0 if we want to pick from the whole set of "
417 "servers for the first position in each circuit, rather than picking a "
418 "set of 'Guards' to prevent profiling attacks." },
420 /* === server options */
421 { "Address", "The advertised (external) address we should use." },
422 /* Accounting* options. */
423 /* AssumeReachable */
424 { "ContactInfo", "Administrative contact information to advertise for this "
426 { "ExitPolicy", "Address/port ranges for which to accept or reject outgoing "
427 "connections on behalf of Tor users." },
428 /* { "ExitPolicyRejectPrivate, "" }, */
429 { "MaxAdvertisedBandwidth", "If set, we will not advertise more than this "
430 "amount of bandwidth for our bandwidth rate, regardless of how much "
431 "bandwidth we actually detect." },
432 { "MaxOnionsPending", "Reject new attempts to extend circuits when we "
433 "already have this many pending." },
434 { "MyFamily", "Declare a list of other servers as belonging to the same "
435 "family as this one, so that clients will not use two from the same "
436 "family in the same circuit." },
437 { "Nickname", "Set the server nickname." },
438 { "NoPublish", "{DEPRECATED}" },
439 { "NumCPUs", "How many processes to use at once for public-key crypto." },
440 { "ORPort", "Advertise this port to listen for connections from Tor clients "
442 { "ORListenAddress", "Bind to this address to listen for connections from "
443 "clients and servers, instead of the default 0.0.0.0:ORPort." },
444 { "PublishServerDescriptors", "Set to 0 in order to keep the server from "
445 "uploading info to the directory authorities." },
446 /*{ "RedirectExit", "When an outgoing connection tries to connect to a "
447 *"given address, redirect it to another address instead." },
449 /* ServerDNS: DetectHijacking, ResolvConfFile, SearchDomains */
450 { "ShutdownWaitLength", "Wait this long for clients to finish when "
451 "shutting down because of a SIGINT." },
454 /* === directory cache options */
455 { "DirPort", "Serve directory information from this port, and act as a "
456 "directory cache." },
457 { "DirListenAddress", "Bind to this address to listen for connections from "
458 "clients and servers, instead of the default 0.0.0.0:DirPort." },
459 { "DirPolicy", "Set a policy to limit who can connect to the directory "
462 /* Authority options: AuthDirBadExit, AuthDirInvalid, AuthDirReject,
463 * AuthDirRejectUnlisted, AuthDirListBadExits, AuthoritativeDirectory,
464 * DirAllowPrivateAddresses, HSAuthoritativeDir,
465 * NamingAuthoritativeDirectory, RecommendedVersions,
466 * RecommendedClientVersions, RecommendedServerVersions, RendPostPeriod,
467 * RunTesting, V1AuthoritativeDirectory, VersioningAuthoritativeDirectory, */
469 /* Hidden service options: HiddenService: dir,excludenodes, nodes,
470 * options, port. PublishHidServDescriptor */
472 /* Nonpersistent options: __LeaveStreamsUnattached, __AllDirActionsPrivate */
476 static config_var_description_t state_description
[] = {
477 { "AccountingBytesReadInInterval",
478 "How many bytes have we read in this accounting period?" },
479 { "AccountingBytesWrittenInInterval",
480 "How many bytes have we written in this accounting period?" },
481 { "AccountingExpectedUsage",
482 "How many bytes did we expect to use per minute? (0 for no estimate.)" },
483 { "AccountingIntervalStart", "When did this accounting period begin?" },
484 { "AccountingSecondsActive", "How long have we been awake in this period?" },
486 { "BWHistoryReadEnds", "When does the last-recorded read-interval end?" },
487 { "BWHistoryReadInterval", "How long is each read-interval (in seconds)?" },
488 { "BWHistoryReadValues", "Number of bytes read in each interval." },
489 { "BWHistoryWriteEnds", "When does the last-recorded write-interval end?" },
490 { "BWHistoryWriteInterval", "How long is each write-interval (in seconds)?"},
491 { "BWHistoryWriteValues", "Number of bytes written in each interval." },
493 { "EntryGuard", "One of the nodes we have chosen as a fixed entry" },
494 { "EntryGuardDownSince",
495 "The last entry guard has been unreachable since this time." },
496 { "EntryGuardUnlistedSince",
497 "The last entry guard has been unusable since this time." },
498 { "LastRotatedOnionKey",
499 "The last time at which we changed the medium-term private key used for "
500 "building circuits." },
501 { "LastWritten", "When was this state file last regenerated?" },
503 { "TorVersion", "Which version of Tor generated this state file?" },
507 /** Type of a callback to validate whether a given configuration is
508 * well-formed and consistent. See options_trial_assign() for documentation
510 typedef int (*validate_fn_t
)(void*,void*,int,char**);
512 /** Information on the keys, value types, key-to-struct-member mappings,
513 * variable descriptions, validation functions, and abbreviations for a
514 * configuration or storage format. */
516 size_t size
; /**< Size of the struct that everything gets parsed into. */
517 uint32_t magic
; /**< Required 'magic value' to make sure we have a struct
518 * of the right type. */
519 off_t magic_offset
; /**< Offset of the magic value within the struct. */
520 config_abbrev_t
*abbrevs
; /**< List of abbreviations that we expand when
521 * parsing this format. */
522 config_var_t
*vars
; /**< List of variables we recognize, their default
523 * values, and where we stick them in the structure. */
524 validate_fn_t validate_fn
; /**< Function to validate config. */
525 /** Documentation for configuration variables. */
526 config_var_description_t
*descriptions
;
527 /** If present, extra is a LINELIST variable for unrecognized
528 * lines. Otherwise, unrecognized lines are an error. */
532 /** Macro: assert that <b>cfg</b> has the right magic field for format
534 #define CHECK(fmt, cfg) do { \
535 tor_assert(fmt && cfg); \
536 tor_assert((fmt)->magic == \
537 *(uint32_t*)STRUCT_VAR_P(cfg,fmt->magic_offset)); \
540 static void config_line_append(config_line_t
**lst
,
541 const char *key
, const char *val
);
542 static void option_clear(config_format_t
*fmt
, or_options_t
*options
,
544 static void option_reset(config_format_t
*fmt
, or_options_t
*options
,
545 config_var_t
*var
, int use_defaults
);
546 static void config_free(config_format_t
*fmt
, void *options
);
547 static int option_is_same(config_format_t
*fmt
,
548 or_options_t
*o1
, or_options_t
*o2
,
550 static or_options_t
*options_dup(config_format_t
*fmt
, or_options_t
*old
);
551 static int options_validate(or_options_t
*old_options
, or_options_t
*options
,
552 int from_setconf
, char **msg
);
553 static int options_act_reversible(or_options_t
*old_options
, char **msg
);
554 static int options_act(or_options_t
*old_options
);
555 static int options_transition_allowed(or_options_t
*old
, or_options_t
*new,
557 static int options_transition_affects_workers(or_options_t
*old_options
,
558 or_options_t
*new_options
);
559 static int options_transition_affects_descriptor(or_options_t
*old_options
,
560 or_options_t
*new_options
);
561 static int check_nickname_list(const char *lst
, const char *name
, char **msg
);
562 static void config_register_addressmaps(or_options_t
*options
);
564 static int parse_dir_server_line(const char *line
, int validate_only
);
565 static int parse_redirect_line(smartlist_t
*result
,
566 config_line_t
*line
, char **msg
);
567 static int parse_log_severity_range(const char *range
, int *min_out
,
569 static int validate_data_directory(or_options_t
*options
);
570 static int write_configuration_file(const char *fname
, or_options_t
*options
);
571 static config_line_t
*get_assigned_option(config_format_t
*fmt
,
572 or_options_t
*options
, const char *key
);
573 static void config_init(config_format_t
*fmt
, void *options
);
574 static int or_state_validate(or_state_t
*old_options
, or_state_t
*options
,
575 int from_setconf
, char **msg
);
577 static uint64_t config_parse_memunit(const char *s
, int *ok
);
578 static int config_parse_interval(const char *s
, int *ok
);
579 static void print_svn_version(void);
580 static void init_libevent(void);
581 static int opt_streq(const char *s1
, const char *s2
);
582 /** Versions of libevent. */
584 /* Note: we compare these, so it's important that "old" precede everything,
585 * and that "other" come last. */
586 LE_OLD
=0, LE_10C
, LE_10D
, LE_10E
, LE_11
, LE_11A
, LE_11B
, LE_12
, LE_12A
,
590 static le_version_t
decode_libevent_version(void);
591 #if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
592 static void check_libevent_version(const char *m
, int server
);
595 /*static*/ or_options_t
*options_new(void);
597 /** Magic value for or_options_t. */
598 #define OR_OPTIONS_MAGIC 9090909
600 /** Configuration format for or_options_t. */
601 static config_format_t options_format
= {
602 sizeof(or_options_t
),
604 STRUCT_OFFSET(or_options_t
, _magic
),
607 (validate_fn_t
)options_validate
,
612 /** Magic value for or_state_t. */
613 #define OR_STATE_MAGIC 0x57A73f57
615 /** "Extra" variable in the state that receives lines we can't parse. This
616 * lets us preserve options from versions of Tor newer than us. */
617 static config_var_t state_extra_var
= {
618 "__extra", CONFIG_TYPE_LINELIST
, STRUCT_OFFSET(or_state_t
, ExtraLines
), NULL
621 /** Configuration format for or_state_t. */
622 static config_format_t state_format
= {
625 STRUCT_OFFSET(or_state_t
, _magic
),
628 (validate_fn_t
)or_state_validate
,
634 * Functions to read and write the global options pointer.
637 /** Command-line and config-file options. */
638 static or_options_t
*global_options
= NULL
;
639 /** Name of most recently read torrc file. */
640 static char *torrc_fname
= NULL
;
641 /** Persistent serialized state. */
642 static or_state_t
*global_state
= NULL
;
644 /** Allocate an empty configuration object of a given format type. */
646 config_alloc(config_format_t
*fmt
)
648 void *opts
= tor_malloc_zero(fmt
->size
);
649 *(uint32_t*)STRUCT_VAR_P(opts
, fmt
->magic_offset
) = fmt
->magic
;
654 /** Return the currently configured options. */
658 tor_assert(global_options
);
659 return global_options
;
662 /** Change the current global options to contain <b>new_val</b> instead of
663 * their current value; take action based on the new value; free the old value
667 set_options(or_options_t
*new_val
, char **msg
)
669 or_options_t
*old_options
= global_options
;
670 global_options
= new_val
;
671 /* Note that we pass the *old* options below, for comparison. It
672 * pulls the new options directly out of global_options. */
673 if (options_act_reversible(old_options
, msg
)<0) {
675 global_options
= old_options
;
678 if (options_act(old_options
) < 0) { /* acting on the options failed. die. */
680 "Acting on config options left us in a broken state. Dying.");
684 config_free(&options_format
, old_options
);
689 /** Release all memory and resources held by global configuration structures.
692 config_free_all(void)
694 if (global_options
) {
695 config_free(&options_format
, global_options
);
696 global_options
= NULL
;
699 config_free(&state_format
, global_state
);
702 tor_free(torrc_fname
);
705 /** If options->SafeLogging is on, return a not very useful string,
706 * else return address.
709 safe_str(const char *address
)
711 if (get_options()->SafeLogging
)
717 /** Equivalent to escaped(safe_str(address)). See reentrancy note on
718 * escaped(): don't use this outside the main thread, or twice in the same
721 escaped_safe_str(const char *address
)
723 if (get_options()->SafeLogging
)
726 return escaped(address
);
729 /** Add the default directory servers directly into the trusted dir list. */
731 add_default_trusted_dirservers(void)
734 const char *dirservers
[] = {
735 /* eventually we should mark moria1 as "v1only" */
736 "moria1 v1 orport=9001 18.244.0.188:9031 "
737 "FFCB 46DB 1339 DA84 674C 70D7 CB58 6434 C437 0441",
738 "moria2 v1 orport=443 18.244.0.114:80 "
739 "719B E45D E224 B607 C537 07D0 E214 3E2D 423E 74CF",
740 "tor26 v1 orport=443 86.59.21.38:80 "
741 "847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D",
742 "lefkada orport=443 140.247.60.64:80 "
743 "38D4 F5FC F7B1 0232 28B8 95EA 56ED E7D5 CCDC AF32",
744 "dizum 194.109.206.212:80 "
745 "7EA6 EAD6 FD83 083C 538F 4403 8BBF A077 587D D755",
748 for (i
=0; dirservers
[i
]; i
++)
749 parse_dir_server_line(dirservers
[i
], 0);
752 /** Fetch the active option list, and take actions based on it. All of the
753 * things we do should survive being done repeatedly. If present,
754 * <b>old_options</b> contains the previous value of the options.
756 * Return 0 if all goes well, return -1 if things went badly.
759 options_act_reversible(or_options_t
*old_options
, char **msg
)
761 smartlist_t
*new_listeners
= smartlist_create();
762 smartlist_t
*replaced_listeners
= smartlist_create();
763 static int libevent_initialized
= 0;
764 or_options_t
*options
= get_options();
765 int running_tor
= options
->command
== CMD_RUN_TOR
;
766 int set_conn_limit
= 0;
770 if (running_tor
&& options
->RunAsDaemon
) {
771 /* No need to roll back, since you can't change the value. */
775 /* Setuid/setgid as appropriate */
776 if (options
->User
|| options
->Group
) {
777 if (switch_id(options
->User
, options
->Group
) != 0) {
778 /* No need to roll back, since you can't change the value. */
779 *msg
= tor_strdup("Problem with User or Group value. "
780 "See logs for details.");
785 /* Set up libevent. */
786 if (running_tor
&& !libevent_initialized
) {
788 libevent_initialized
= 1;
791 /* Ensure data directory is private; create if possible. */
792 if (check_private_dir(options
->DataDirectory
, CPD_CREATE
)<0) {
794 int tmp
= tor_snprintf(buf
, sizeof(buf
),
795 "Couldn't access/create private data directory \"%s\"",
796 options
->DataDirectory
);
797 *msg
= tor_strdup(tmp
>= 0 ? buf
: "internal error");
799 /* No need to roll back, since you can't change the value. */
802 /* Bail out at this point if we're not going to be a client or server:
803 * we don't run Tor itself. */
804 if (options
->command
!= CMD_RUN_TOR
)
807 options
->_ConnLimit
=
808 set_max_file_descriptors((unsigned)options
->ConnLimit
, MAXCONNECTIONS
);
809 if (options
->_ConnLimit
< 0) {
810 *msg
= tor_strdup("Problem with ConnLimit value. See logs for details.");
815 if (retry_all_listeners(0, replaced_listeners
, new_listeners
) < 0) {
816 *msg
= tor_strdup("Failed to bind one of the listener ports.");
820 mark_logs_temp(); /* Close current logs once new logs are open. */
822 if (options_init_logs(options
, 0)<0) { /* Configure the log(s) */
823 *msg
= tor_strdup("Failed to init Log options. See logs for details.");
831 add_callback_log(LOG_ERR
, LOG_ERR
, control_event_logmsg
);
832 control_adjust_event_log_severity();
834 SMARTLIST_FOREACH(replaced_listeners
, connection_t
*, conn
,
836 log_notice(LD_NET
, "Closing old %s on %s:%d",
837 conn_type_to_string(conn
->type
), conn
->address
, conn
->port
);
838 connection_close_immediate(conn
);
839 connection_mark_for_close(conn
);
848 rollback_log_changes();
849 control_adjust_event_log_severity();
852 if (set_conn_limit
&& old_options
)
853 set_max_file_descriptors((unsigned)old_options
->ConnLimit
,MAXCONNECTIONS
);
855 SMARTLIST_FOREACH(new_listeners
, connection_t
*, conn
,
857 log_notice(LD_NET
, "Closing partially-constructed listener %s on %s:%d",
858 conn_type_to_string(conn
->type
), conn
->address
, conn
->port
);
859 connection_close_immediate(conn
);
860 connection_mark_for_close(conn
);
864 smartlist_free(new_listeners
);
865 smartlist_free(replaced_listeners
);
869 /** Fetch the active option list, and take actions based on it. All of the
870 * things we do should survive being done repeatedly. If present,
871 * <b>old_options</b> contains the previous value of the options.
873 * Return 0 if all goes well, return -1 if it's time to die.
875 * Note: We haven't moved all the "act on new configuration" logic
876 * here yet. Some is still in do_hup() and other places.
879 options_act(or_options_t
*old_options
)
884 or_options_t
*options
= get_options();
885 int running_tor
= options
->command
== CMD_RUN_TOR
;
888 clear_trusted_dir_servers();
889 if (options
->DirServers
) {
890 for (cl
= options
->DirServers
; cl
; cl
= cl
->next
) {
891 if (parse_dir_server_line(cl
->value
, 0)<0) {
893 "Bug: Previously validated DirServer line could not be added!");
898 add_default_trusted_dirservers();
901 if (running_tor
&& rend_config_services(options
, 0)<0) {
903 "Bug: Previously validated hidden services line could not be added!");
908 len
= strlen(options
->DataDirectory
)+32;
909 fn
= tor_malloc(len
);
910 tor_snprintf(fn
, len
, "%s/cached-status", options
->DataDirectory
);
911 if (check_private_dir(fn
, CPD_CREATE
) != 0) {
913 "Couldn't access/create private data directory \"%s\"", fn
);
925 /* Bail out at this point if we're not going to be a client or server:
926 * we want to not fork, and to log stuff to stderr. */
927 if (options
->command
!= CMD_RUN_TOR
)
931 smartlist_t
*sl
= smartlist_create();
933 for (cl
= options
->RedirectExit
; cl
; cl
= cl
->next
) {
934 if (parse_redirect_line(sl
, cl
, &errmsg
)<0) {
935 log_warn(LD_CONFIG
, "%s", errmsg
);
940 set_exit_redirects(sl
);
943 /* Finish backgrounding the process */
944 if (running_tor
&& options
->RunAsDaemon
) {
945 /* We may be calling this for the n'th time (on SIGHUP), but it's safe. */
946 finish_daemon(options
->DataDirectory
);
949 /* Write our pid to the pid file. If we do not have write permissions we
950 * will log a warning */
951 if (running_tor
&& options
->PidFile
)
952 write_pidfile(options
->PidFile
);
954 /* Register addressmap directives */
955 config_register_addressmaps(options
);
956 parse_virtual_addr_network(options
->VirtualAddrNetwork
, 0, &msg
);
958 /* Update address policies. */
959 policies_parse_from_options(options
);
961 init_cookie_authentication(options
->CookieAuthentication
);
963 /* reload keys as needed for rendezvous services. */
964 if (rend_service_load_keys()<0) {
965 log_err(LD_GENERAL
,"Error loading rendezvous service keys");
969 /* Set up accounting */
970 if (accounting_parse_options(options
, 0)<0) {
971 log_err(LD_CONFIG
,"Error in accounting options");
974 if (accounting_is_enabled(options
))
975 configure_accounting(time(NULL
));
980 /* Check for transitions that need action. */
982 if (options
->UseEntryGuards
&& !old_options
->UseEntryGuards
) {
984 "Switching to entry guards; abandoning previous circuits");
985 circuit_mark_all_unused_circs();
986 circuit_expire_all_dirty_circs();
989 if (options_transition_affects_workers(old_options
, options
)) {
991 "Worker-related options changed. Rotating workers.");
992 if (server_mode(options
) && !server_mode(old_options
)) {
993 if (init_keys() < 0) {
994 log_err(LD_BUG
,"Error initializing keys; exiting");
997 ip_address_changed(0);
998 if (has_completed_circuit
|| !any_predicted_circuits(time(NULL
)))
999 inform_testing_reachability();
1001 cpuworkers_rotate();
1013 /* Check if we need to parse and add the EntryNodes config option. */
1014 if (options
->EntryNodes
&&
1016 !opt_streq(old_options
->EntryNodes
, options
->EntryNodes
)))
1017 entry_nodes_should_be_added();
1019 /* Since our options changed, we might need to regenerate and upload our
1020 * server descriptor.
1023 options_transition_affects_descriptor(old_options
, options
))
1024 mark_my_descriptor_dirty();
1030 * Functions to parse config options
1033 /** If <b>option</b> is an official abbreviation for a longer option,
1034 * return the longer option. Otherwise return <b>option</b>.
1035 * If <b>command_line</b> is set, apply all abbreviations. Otherwise, only
1036 * apply abbreviations that work for the config file and the command line.
1037 * If <b>warn_obsolete</b> is set, warn about deprecated names. */
1039 expand_abbrev(config_format_t
*fmt
, const char *option
, int command_line
,
1045 for (i
=0; fmt
->abbrevs
[i
].abbreviated
; ++i
) {
1046 /* Abbreviations are casei. */
1047 if (!strcasecmp(option
,fmt
->abbrevs
[i
].abbreviated
) &&
1048 (command_line
|| !fmt
->abbrevs
[i
].commandline_only
)) {
1049 if (warn_obsolete
&& fmt
->abbrevs
[i
].warn
) {
1051 "The configuration option '%s' is deprecated; "
1052 "use '%s' instead.",
1053 fmt
->abbrevs
[i
].abbreviated
,
1054 fmt
->abbrevs
[i
].full
);
1056 return fmt
->abbrevs
[i
].full
;
1062 /** Helper: Read a list of configuration options from the command line.
1063 * If successful, put them in *<b>result</b> and return 0, and return
1064 * -1 and leave *<b>result</b> alone. */
1066 config_get_commandlines(int argc
, char **argv
, config_line_t
**result
)
1068 config_line_t
*front
= NULL
;
1069 config_line_t
**new = &front
;
1074 if (!strcmp(argv
[i
],"-f") ||
1075 !strcmp(argv
[i
],"--hash-password")) {
1076 i
+= 2; /* command-line option with argument. ignore them. */
1078 } else if (!strcmp(argv
[i
],"--list-fingerprint") ||
1079 !strcmp(argv
[i
],"--verify-config") ||
1080 !strcmp(argv
[i
],"--ignore-missing-torrc")) {
1081 i
+= 1; /* command-line option. ignore it. */
1083 } else if (!strcmp(argv
[i
],"--nt-service") ||
1084 !strcmp(argv
[i
],"-nt-service")) {
1089 log_warn(LD_CONFIG
,"Command-line option '%s' with no value. Failing.",
1091 config_free_lines(front
);
1095 *new = tor_malloc_zero(sizeof(config_line_t
));
1101 (*new)->key
= tor_strdup(expand_abbrev(&options_format
, s
, 1, 1));
1102 (*new)->value
= tor_strdup(argv
[i
+1]);
1103 (*new)->next
= NULL
;
1104 log(LOG_DEBUG
, LD_CONFIG
, "Commandline: parsed keyword '%s', value '%s'",
1105 (*new)->key
, (*new)->value
);
1107 new = &((*new)->next
);
1114 /** Helper: allocate a new configuration option mapping 'key' to 'val',
1115 * append it to *<b>lst</b>. */
1117 config_line_append(config_line_t
**lst
,
1121 config_line_t
*newline
;
1123 newline
= tor_malloc(sizeof(config_line_t
));
1124 newline
->key
= tor_strdup(key
);
1125 newline
->value
= tor_strdup(val
);
1126 newline
->next
= NULL
;
1128 lst
= &((*lst
)->next
);
1133 /** Helper: parse the config string and strdup into key/value
1134 * strings. Set *result to the list, or NULL if parsing the string
1135 * failed. Return 0 on success, -1 on failure. Warn and ignore any
1136 * misformatted lines. Modifies the contents of <b>string</b>. */
1138 config_get_lines(char *string
, config_line_t
**result
)
1140 config_line_t
*list
= NULL
, **next
;
1145 string
= parse_line_from_str(string
, &k
, &v
);
1147 config_free_lines(list
);
1151 /* This list can get long, so we keep a pointer to the end of it
1152 * rather than using config_line_append over and over and getting n^2
1153 * performance. This is the only really long list. */
1154 *next
= tor_malloc(sizeof(config_line_t
));
1155 (*next
)->key
= tor_strdup(k
);
1156 (*next
)->value
= tor_strdup(v
);
1157 (*next
)->next
= NULL
;
1158 next
= &((*next
)->next
);
1167 * Free all the configuration lines on the linked list <b>front</b>.
1170 config_free_lines(config_line_t
*front
)
1179 tor_free(tmp
->value
);
1184 /** Return the description for a given configuration variable, or NULL if no
1185 * description exists. */
1187 config_find_description(config_format_t
*fmt
, const char *name
)
1190 for (i
=0; fmt
->descriptions
[i
].name
; ++i
) {
1191 if (!strcasecmp(name
, fmt
->descriptions
[i
].name
))
1192 return fmt
->descriptions
[i
].description
;
1197 /** If <b>key</b> is a configuration option, return the corresponding
1198 * config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation,
1199 * warn, and return the corresponding config_var_t. Otherwise return NULL.
1201 static config_var_t
*
1202 config_find_option(config_format_t
*fmt
, const char *key
)
1205 size_t keylen
= strlen(key
);
1207 return NULL
; /* if they say "--" on the commandline, it's not an option */
1208 /* First, check for an exact (case-insensitive) match */
1209 for (i
=0; fmt
->vars
[i
].name
; ++i
) {
1210 if (!strcasecmp(key
, fmt
->vars
[i
].name
)) {
1211 return &fmt
->vars
[i
];
1214 /* If none, check for an abbreviated match */
1215 for (i
=0; fmt
->vars
[i
].name
; ++i
) {
1216 if (!strncasecmp(key
, fmt
->vars
[i
].name
, keylen
)) {
1217 log_warn(LD_CONFIG
, "The abbreviation '%s' is deprecated. "
1218 "Please use '%s' instead",
1219 key
, fmt
->vars
[i
].name
);
1220 return &fmt
->vars
[i
];
1223 /* Okay, unrecognized option */
1228 * Functions to assign config options.
1231 /** <b>c</b>-\>key is known to be a real key. Update <b>options</b>
1232 * with <b>c</b>-\>value and return 0, or return -1 if bad value.
1234 * Called from config_assign_line() and option_reset().
1237 config_assign_value(config_format_t
*fmt
, or_options_t
*options
,
1238 config_line_t
*c
, char **msg
)
1245 CHECK(fmt
, options
);
1247 var
= config_find_option(fmt
, c
->key
);
1250 lvalue
= STRUCT_VAR_P(options
, var
->var_offset
);
1252 switch (var
->type
) {
1254 case CONFIG_TYPE_UINT
:
1255 i
= tor_parse_long(c
->value
, 10, 0, INT_MAX
, &ok
, NULL
);
1257 r
= tor_snprintf(buf
, sizeof(buf
),
1258 "Int keyword '%s %s' is malformed or out of bounds.",
1260 *msg
= tor_strdup(r
>= 0 ? buf
: "internal error");
1266 case CONFIG_TYPE_INTERVAL
: {
1267 i
= config_parse_interval(c
->value
, &ok
);
1269 r
= tor_snprintf(buf
, sizeof(buf
),
1270 "Interval '%s %s' is malformed or out of bounds.",
1272 *msg
= tor_strdup(r
>= 0 ? buf
: "internal error");
1279 case CONFIG_TYPE_MEMUNIT
: {
1280 uint64_t u64
= config_parse_memunit(c
->value
, &ok
);
1282 r
= tor_snprintf(buf
, sizeof(buf
),
1283 "Value '%s %s' is malformed or out of bounds.",
1285 *msg
= tor_strdup(r
>= 0 ? buf
: "internal error");
1288 *(uint64_t *)lvalue
= u64
;
1292 case CONFIG_TYPE_BOOL
:
1293 i
= tor_parse_long(c
->value
, 10, 0, 1, &ok
, NULL
);
1295 r
= tor_snprintf(buf
, sizeof(buf
),
1296 "Boolean '%s %s' expects 0 or 1.",
1298 *msg
= tor_strdup(r
>= 0 ? buf
: "internal error");
1304 case CONFIG_TYPE_STRING
:
1305 tor_free(*(char **)lvalue
);
1306 *(char **)lvalue
= tor_strdup(c
->value
);
1309 case CONFIG_TYPE_DOUBLE
:
1310 *(double *)lvalue
= atof(c
->value
);
1313 case CONFIG_TYPE_ISOTIME
:
1314 if (parse_iso_time(c
->value
, (time_t *)lvalue
)) {
1315 r
= tor_snprintf(buf
, sizeof(buf
),
1316 "Invalid time '%s' for keyword '%s'", c
->value
, c
->key
);
1317 *msg
= tor_strdup(r
>= 0 ? buf
: "internal error");
1322 case CONFIG_TYPE_CSV
:
1323 if (*(smartlist_t
**)lvalue
) {
1324 SMARTLIST_FOREACH(*(smartlist_t
**)lvalue
, char *, cp
, tor_free(cp
));
1325 smartlist_clear(*(smartlist_t
**)lvalue
);
1327 *(smartlist_t
**)lvalue
= smartlist_create();
1330 smartlist_split_string(*(smartlist_t
**)lvalue
, c
->value
, ",",
1331 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, 0);
1334 case CONFIG_TYPE_LINELIST
:
1335 case CONFIG_TYPE_LINELIST_S
:
1336 config_line_append((config_line_t
**)lvalue
, c
->key
, c
->value
);
1339 case CONFIG_TYPE_OBSOLETE
:
1340 log_warn(LD_CONFIG
, "Skipping obsolete configuration option '%s'", c
->key
);
1342 case CONFIG_TYPE_LINELIST_V
:
1343 r
= tor_snprintf(buf
, sizeof(buf
),
1344 "You may not provide a value for virtual option '%s'", c
->key
);
1345 *msg
= tor_strdup(r
>= 0 ? buf
: "internal error");
1354 /** If <b>c</b> is a syntactically valid configuration line, update
1355 * <b>options</b> with its value and return 0. Otherwise return -1 for bad
1356 * key, -2 for bad value.
1358 * If <b>clear_first</b> is set, clear the value first. Then if
1359 * <b>use_defaults</b> is set, set the value to the default.
1361 * Called from config_assign().
1364 config_assign_line(config_format_t
*fmt
, or_options_t
*options
,
1365 config_line_t
*c
, int use_defaults
,
1366 int clear_first
, char **msg
)
1370 CHECK(fmt
, options
);
1372 var
= config_find_option(fmt
, c
->key
);
1375 void *lvalue
= STRUCT_VAR_P(options
, fmt
->extra
->var_offset
);
1377 "Found unrecognized option '%s'; saving it.", c
->key
);
1378 config_line_append((config_line_t
**)lvalue
, c
->key
, c
->value
);
1382 int tmp
= tor_snprintf(buf
, sizeof(buf
),
1383 "Unknown option '%s'. Failing.", c
->key
);
1384 *msg
= tor_strdup(tmp
>= 0 ? buf
: "internal error");
1388 /* Put keyword into canonical case. */
1389 if (strcmp(var
->name
, c
->key
)) {
1391 c
->key
= tor_strdup(var
->name
);
1394 if (!strlen(c
->value
)) {
1395 /* reset or clear it, then return */
1397 if (var
->type
== CONFIG_TYPE_LINELIST
||
1398 var
->type
== CONFIG_TYPE_LINELIST_S
) {
1399 /* We got an empty linelist from the torrc or commandline.
1400 As a special case, call this an error. Warn and ignore. */
1402 "Linelist option '%s' has no value. Skipping.", c
->key
);
1403 } else { /* not already cleared */
1404 option_reset(fmt
, options
, var
, use_defaults
);
1410 if (config_assign_value(fmt
, options
, c
, msg
) < 0)
1415 /** Restore the option named <b>key</b> in options to its default value.
1416 * Called from config_assign(). */
1418 config_reset_line(config_format_t
*fmt
, or_options_t
*options
,
1419 const char *key
, int use_defaults
)
1423 CHECK(fmt
, options
);
1425 var
= config_find_option(fmt
, key
);
1427 return; /* give error on next pass. */
1429 option_reset(fmt
, options
, var
, use_defaults
);
1432 /** Return true iff key is a valid configuration option. */
1434 option_is_recognized(const char *key
)
1436 config_var_t
*var
= config_find_option(&options_format
, key
);
1437 return (var
!= NULL
);
1440 /** Return the canonical name of a configuration option. */
1442 option_get_canonical_name(const char *key
)
1444 config_var_t
*var
= config_find_option(&options_format
, key
);
1448 /** Return a canonicalized list of the options assigned for key.
1451 option_get_assignment(or_options_t
*options
, const char *key
)
1453 return get_assigned_option(&options_format
, options
, key
);
1456 /** Return a newly allocated deep copy of the lines in <b>inp</b>. */
1457 static config_line_t
*
1458 config_lines_dup(const config_line_t
*inp
)
1460 config_line_t
*result
= NULL
;
1461 config_line_t
**next_out
= &result
;
1463 *next_out
= tor_malloc(sizeof(config_line_t
));
1464 (*next_out
)->key
= tor_strdup(inp
->key
);
1465 (*next_out
)->value
= tor_strdup(inp
->value
);
1467 next_out
= &((*next_out
)->next
);
1473 /** Return newly allocated line or lines corresponding to <b>key</b> in the
1474 * configuration <b>options</b>. Return NULL if no such key exists. */
1475 static config_line_t
*
1476 get_assigned_option(config_format_t
*fmt
, or_options_t
*options
,
1478 /* XXXX argument is options, but fmt is provided. Inconsistent. */
1483 config_line_t
*result
;
1484 tor_assert(options
&& key
);
1486 CHECK(fmt
, options
);
1488 var
= config_find_option(fmt
, key
);
1490 log_warn(LD_CONFIG
, "Unknown option '%s'. Failing.", key
);
1493 value
= STRUCT_VAR_P(options
, var
->var_offset
);
1495 result
= tor_malloc_zero(sizeof(config_line_t
));
1496 result
->key
= tor_strdup(var
->name
);
1499 case CONFIG_TYPE_STRING
:
1500 if (*(char**)value
) {
1501 result
->value
= tor_strdup(*(char**)value
);
1503 tor_free(result
->key
);
1508 case CONFIG_TYPE_ISOTIME
:
1509 if (*(time_t*)value
) {
1510 result
->value
= tor_malloc(ISO_TIME_LEN
+1);
1511 format_iso_time(result
->value
, *(time_t*)value
);
1513 tor_free(result
->key
);
1517 case CONFIG_TYPE_INTERVAL
:
1518 case CONFIG_TYPE_UINT
:
1519 /* This means every or_options_t uint or bool element
1520 * needs to be an int. Not, say, a uint16_t or char. */
1521 tor_snprintf(buf
, sizeof(buf
), "%d", *(int*)value
);
1522 result
->value
= tor_strdup(buf
);
1524 case CONFIG_TYPE_MEMUNIT
:
1525 tor_snprintf(buf
, sizeof(buf
), U64_FORMAT
,
1526 U64_PRINTF_ARG(*(uint64_t*)value
));
1527 result
->value
= tor_strdup(buf
);
1529 case CONFIG_TYPE_DOUBLE
:
1530 tor_snprintf(buf
, sizeof(buf
), "%f", *(double*)value
);
1531 result
->value
= tor_strdup(buf
);
1533 case CONFIG_TYPE_BOOL
:
1534 result
->value
= tor_strdup(*(int*)value
? "1" : "0");
1536 case CONFIG_TYPE_CSV
:
1537 if (*(smartlist_t
**)value
)
1539 smartlist_join_strings(*(smartlist_t
**)value
, ",", 0, NULL
);
1541 result
->value
= tor_strdup("");
1543 case CONFIG_TYPE_OBSOLETE
:
1545 "You asked me for the value of an obsolete config option '%s'.",
1547 tor_free(result
->key
);
1550 case CONFIG_TYPE_LINELIST_S
:
1552 "Can't return context-sensitive '%s' on its own", key
);
1553 tor_free(result
->key
);
1556 case CONFIG_TYPE_LINELIST
:
1557 case CONFIG_TYPE_LINELIST_V
:
1558 tor_free(result
->key
);
1560 return config_lines_dup(*(const config_line_t
**)value
);
1562 tor_free(result
->key
);
1564 log_warn(LD_BUG
,"Bug: unknown type %d for known key '%s'",
1572 /** Iterate through the linked list of requested options <b>list</b>.
1573 * For each item, convert as appropriate and assign to <b>options</b>.
1574 * If an item is unrecognized, set *msg and return -1 immediately,
1575 * else return 0 for success.
1577 * If <b>clear_first</b>, interpret config options as replacing (not
1578 * extending) their previous values. If <b>clear_first</b> is set,
1579 * then <b>use_defaults</b> to decide if you set to defaults after
1580 * clearing, or make the value 0 or NULL.
1582 * Here are the use cases:
1583 * 1. A non-empty AllowInvalid line in your torrc. Appends to current
1584 * if linelist, replaces current if csv.
1585 * 2. An empty AllowInvalid line in your torrc. Should clear it.
1586 * 3. "RESETCONF AllowInvalid" sets it to default.
1587 * 4. "SETCONF AllowInvalid" makes it NULL.
1588 * 5. "SETCONF AllowInvalid=foo" clears it and sets it to "foo".
1590 * Use_defaults Clear_first
1592 * 1 0 undefined, don't use
1593 * 0 1 "set to null first"
1594 * 1 1 "set to defaults first"
1595 * Return 0 on success, -1 on bad key, -2 on bad value.
1597 * As an additional special case, if a LINELIST config option has
1598 * no value and clear_first is 0, then warn and ignore it.
1602 There are three call cases for config_assign() currently.
1604 Case one: Torrc entry
1605 options_init_from_torrc() calls config_assign(0, 0)
1606 calls config_assign_line(0, 0).
1607 if value is empty, calls option_reset(0) and returns.
1608 calls config_assign_value(), appends.
1611 options_trial_assign() calls config_assign(0, 1)
1612 calls config_reset_line(0)
1613 calls option_reset(0)
1614 calls option_clear().
1615 calls config_assign_line(0, 1).
1616 if value is empty, returns.
1617 calls config_assign_value(), appends.
1619 Case three: resetconf
1620 options_trial_assign() calls config_assign(1, 1)
1621 calls config_reset_line(1)
1622 calls option_reset(1)
1623 calls option_clear().
1624 calls config_assign_value(default)
1625 calls config_assign_line(1, 1).
1629 config_assign(config_format_t
*fmt
, void *options
, config_line_t
*list
,
1630 int use_defaults
, int clear_first
, char **msg
)
1634 CHECK(fmt
, options
);
1636 /* pass 1: normalize keys */
1637 for (p
= list
; p
; p
= p
->next
) {
1638 const char *full
= expand_abbrev(fmt
, p
->key
, 0, 1);
1639 if (strcmp(full
,p
->key
)) {
1641 p
->key
= tor_strdup(full
);
1645 /* pass 2: if we're reading from a resetting source, clear all
1646 * mentioned config options, and maybe set to their defaults. */
1648 for (p
= list
; p
; p
= p
->next
)
1649 config_reset_line(fmt
, options
, p
->key
, use_defaults
);
1652 /* pass 3: assign. */
1655 if ((r
=config_assign_line(fmt
, options
, list
, use_defaults
,
1663 /** Try assigning <b>list</b> to the global options. You do this by duping
1664 * options, assigning list to the new one, then validating it. If it's
1665 * ok, then throw out the old one and stick with the new one. Else,
1666 * revert to old and return failure. Return 0 on success, -1 on bad
1667 * keys, -2 on bad values, -3 on bad transition, and -4 on failed-to-set.
1669 * If not success, point *<b>msg</b> to a newly allocated string describing
1673 options_trial_assign(config_line_t
*list
, int use_defaults
,
1674 int clear_first
, char **msg
)
1677 or_options_t
*trial_options
= options_dup(&options_format
, get_options());
1679 if ((r
=config_assign(&options_format
, trial_options
,
1680 list
, use_defaults
, clear_first
, msg
)) < 0) {
1681 config_free(&options_format
, trial_options
);
1685 if (options_validate(get_options(), trial_options
, 1, msg
) < 0) {
1686 config_free(&options_format
, trial_options
);
1690 if (options_transition_allowed(get_options(), trial_options
, msg
) < 0) {
1691 config_free(&options_format
, trial_options
);
1695 if (set_options(trial_options
, msg
)<0) {
1696 config_free(&options_format
, trial_options
);
1700 /* we liked it. put it in place. */
1704 /** Reset config option <b>var</b> to 0, 0.0, NULL, or the equivalent.
1705 * Called from option_reset() and config_free(). */
1707 option_clear(config_format_t
*fmt
, or_options_t
*options
, config_var_t
*var
)
1709 void *lvalue
= STRUCT_VAR_P(options
, var
->var_offset
);
1710 (void)fmt
; /* unused */
1711 switch (var
->type
) {
1712 case CONFIG_TYPE_STRING
:
1713 tor_free(*(char**)lvalue
);
1715 case CONFIG_TYPE_DOUBLE
:
1716 *(double*)lvalue
= 0.0;
1718 case CONFIG_TYPE_ISOTIME
:
1719 *(time_t*)lvalue
= 0;
1720 case CONFIG_TYPE_INTERVAL
:
1721 case CONFIG_TYPE_UINT
:
1722 case CONFIG_TYPE_BOOL
:
1725 case CONFIG_TYPE_MEMUNIT
:
1726 *(uint64_t*)lvalue
= 0;
1728 case CONFIG_TYPE_CSV
:
1729 if (*(smartlist_t
**)lvalue
) {
1730 SMARTLIST_FOREACH(*(smartlist_t
**)lvalue
, char *, cp
, tor_free(cp
));
1731 smartlist_free(*(smartlist_t
**)lvalue
);
1732 *(smartlist_t
**)lvalue
= NULL
;
1735 case CONFIG_TYPE_LINELIST
:
1736 case CONFIG_TYPE_LINELIST_S
:
1737 config_free_lines(*(config_line_t
**)lvalue
);
1738 *(config_line_t
**)lvalue
= NULL
;
1740 case CONFIG_TYPE_LINELIST_V
:
1741 /* handled by linelist_s. */
1743 case CONFIG_TYPE_OBSOLETE
:
1748 /** Clear the option indexed by <b>var</b> in <b>options</b>. Then if
1749 * <b>use_defaults</b>, set it to its default value.
1750 * Called by config_init() and option_reset_line() and option_assign_line(). */
1752 option_reset(config_format_t
*fmt
, or_options_t
*options
,
1753 config_var_t
*var
, int use_defaults
)
1757 CHECK(fmt
, options
);
1758 option_clear(fmt
, options
, var
); /* clear it first */
1760 return; /* all done */
1761 if (var
->initvalue
) {
1762 c
= tor_malloc_zero(sizeof(config_line_t
));
1763 c
->key
= tor_strdup(var
->name
);
1764 c
->value
= tor_strdup(var
->initvalue
);
1765 if (config_assign_value(fmt
, options
, c
, &msg
) < 0) {
1766 log_warn(LD_BUG
, "Failed to assign default: %s", msg
);
1767 tor_free(msg
); /* if this happens it's a bug */
1769 config_free_lines(c
);
1773 /** Print a usage message for tor. */
1778 "Copyright 2001-2007 Roger Dingledine, Nick Mathewson.\n\n"
1779 "tor -f <torrc> [args]\n"
1780 "See man page for options, or http://tor.eff.org/ for documentation.\n");
1783 /** Print all non-obsolete torrc options. */
1785 list_torrc_options(void)
1788 smartlist_t
*lines
= smartlist_create();
1789 for (i
= 0; _option_vars
[i
].name
; ++i
) {
1790 config_var_t
*var
= &_option_vars
[i
];
1792 if (var
->type
== CONFIG_TYPE_OBSOLETE
||
1793 var
->type
== CONFIG_TYPE_LINELIST_V
)
1795 desc
= config_find_description(&options_format
, var
->name
);
1796 printf("%s\n", var
->name
);
1798 wrap_string(lines
, desc
, 76, " ", " ");
1799 SMARTLIST_FOREACH(lines
, char *, cp
, {
1803 smartlist_clear(lines
);
1808 /** Last value actually set by resolve_my_address. */
1809 static uint32_t last_resolved_addr
= 0;
1811 * Based on <b>options-\>Address</b>, guess our public IP address and put it
1812 * (in host order) into *<b>addr_out</b>. If <b>hostname_out</b> is provided,
1813 * set *<b>hostname_out</b> to a new string holding the hostname we used to
1814 * get the address. Return 0 if all is well, or -1 if we can't find a suitable
1815 * public IP address.
1818 resolve_my_address(int warn_severity
, or_options_t
*options
,
1819 uint32_t *addr_out
, char **hostname_out
)
1822 struct hostent
*rent
;
1825 int explicit_hostname
=1;
1826 int from_interface
=0;
1827 char tmpbuf
[INET_NTOA_BUF_LEN
];
1828 const char *address
= options
->Address
;
1829 int notice_severity
= warn_severity
<= LOG_NOTICE
?
1830 LOG_NOTICE
: warn_severity
;
1832 tor_assert(addr_out
);
1834 if (address
&& *address
) {
1835 strlcpy(hostname
, address
, sizeof(hostname
));
1836 } else { /* then we need to guess our address */
1837 explicit_ip
= 0; /* it's implicit */
1838 explicit_hostname
= 0; /* it's implicit */
1840 if (gethostname(hostname
, sizeof(hostname
)) < 0) {
1841 log_fn(warn_severity
, LD_NET
,"Error obtaining local hostname");
1844 log_debug(LD_CONFIG
,"Guessed local host name as '%s'",hostname
);
1847 /* now we know hostname. resolve it and keep only the IP address */
1849 if (tor_inet_aton(hostname
, &in
) == 0) {
1850 /* then we have to resolve it */
1852 rent
= (struct hostent
*)gethostbyname(hostname
);
1854 uint32_t interface_ip
;
1856 if (explicit_hostname
) {
1857 log_fn(warn_severity
, LD_CONFIG
,
1858 "Could not resolve local Address '%s'. Failing.", hostname
);
1861 log_fn(notice_severity
, LD_CONFIG
,
1862 "Could not resolve guessed local hostname '%s'. "
1863 "Trying something else.", hostname
);
1864 if (get_interface_address(warn_severity
, &interface_ip
)) {
1865 log_fn(warn_severity
, LD_CONFIG
,
1866 "Could not get local interface IP address. Failing.");
1870 in
.s_addr
= htonl(interface_ip
);
1871 tor_inet_ntoa(&in
,tmpbuf
,sizeof(tmpbuf
));
1872 log_fn(notice_severity
, LD_CONFIG
, "Learned IP address '%s' for "
1873 "local interface. Using that.", tmpbuf
);
1874 strlcpy(hostname
, "<guessed from interfaces>", sizeof(hostname
));
1876 tor_assert(rent
->h_length
== 4);
1877 memcpy(&in
.s_addr
, rent
->h_addr
, rent
->h_length
);
1879 if (!explicit_hostname
&&
1880 is_internal_IP(ntohl(in
.s_addr
), 0)) {
1881 uint32_t interface_ip
;
1883 tor_inet_ntoa(&in
,tmpbuf
,sizeof(tmpbuf
));
1884 log_fn(notice_severity
, LD_CONFIG
, "Guessed local hostname '%s' "
1885 "resolves to a private IP address (%s). Trying something "
1886 "else.", hostname
, tmpbuf
);
1888 if (get_interface_address(warn_severity
, &interface_ip
)) {
1889 log_fn(warn_severity
, LD_CONFIG
,
1890 "Could not get local interface IP address. Too bad.");
1891 } else if (is_internal_IP(interface_ip
, 0)) {
1893 in2
.s_addr
= htonl(interface_ip
);
1894 tor_inet_ntoa(&in2
,tmpbuf
,sizeof(tmpbuf
));
1895 log_fn(notice_severity
, LD_CONFIG
,
1896 "Interface IP address '%s' is a private address too. "
1897 "Ignoring.", tmpbuf
);
1900 in
.s_addr
= htonl(interface_ip
);
1901 tor_inet_ntoa(&in
,tmpbuf
,sizeof(tmpbuf
));
1902 log_fn(notice_severity
, LD_CONFIG
,
1903 "Learned IP address '%s' for local interface."
1904 " Using that.", tmpbuf
);
1905 strlcpy(hostname
, "<guessed from interfaces>", sizeof(hostname
));
1911 tor_inet_ntoa(&in
,tmpbuf
,sizeof(tmpbuf
));
1912 if (is_internal_IP(ntohl(in
.s_addr
), 0) &&
1913 options
->PublishServerDescriptor
) {
1914 /* make sure we're ok with publishing an internal IP */
1915 if (!options
->DirServers
) {
1916 /* if they are using the default dirservers, disallow internal IPs
1918 log_fn(warn_severity
, LD_CONFIG
,
1919 "Address '%s' resolves to private IP address '%s'. "
1920 "Tor servers that use the default DirServers must have public "
1921 "IP addresses.", hostname
, tmpbuf
);
1925 /* even if they've set their own dirservers, require an explicit IP if
1926 * they're using an internal address. */
1927 log_fn(warn_severity
, LD_CONFIG
, "Address '%s' resolves to private "
1928 "IP address '%s'. Please set the Address config option to be "
1929 "the IP address you want to use.", hostname
, tmpbuf
);
1934 log_debug(LD_CONFIG
, "Resolved Address to '%s'.", tmpbuf
);
1935 *addr_out
= ntohl(in
.s_addr
);
1936 if (last_resolved_addr
&& last_resolved_addr
!= *addr_out
) {
1937 /* Leave this as a notice, regardless of the requested severity,
1938 * at least until dynamic IP address support becomes bulletproof. */
1939 log_notice(LD_NET
, "Your IP address seems to have changed. Updating.");
1940 ip_address_changed(0);
1942 if (last_resolved_addr
!= *addr_out
) {
1944 const char *h
= hostname
;
1946 method
= "CONFIGURED";
1948 } else if (explicit_hostname
) {
1949 method
= "RESOLVED";
1950 } else if (from_interface
) {
1951 method
= "INTERFACE";
1954 method
= "GETHOSTNAME";
1956 control_event_server_status(LOG_NOTICE
,
1957 "EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s %s%s",
1958 tmpbuf
, method
, h
?"HOSTNAME=":"", h
);
1960 last_resolved_addr
= *addr_out
;
1962 *hostname_out
= tor_strdup(hostname
);
1966 /** Return true iff <b>ip</b> (in host order) is judged to be on the
1967 * same network as us, or on a private network.
1970 is_local_IP(uint32_t ip
)
1972 if (is_internal_IP(ip
, 0))
1974 /* Check whether ip is on the same /24 as we are. */
1975 if (get_options()->EnforceDistinctSubnets
== 0)
1977 /* It's possible that this next check will hit before the first time
1978 * resolve_my_address actually succeeds. (For clients, it is likely that
1979 * resolve_my_address will never be called at all). In those cases,
1980 * last_resolved_addr will be 0, and so checking to see whether ip is on the
1981 * same /24 as last_resolved_addr will be the same as checking whether it
1982 * was on net 0, which is already done by is_internal_IP.
1984 if ((last_resolved_addr
& 0xffffff00ul
) == (ip
& 0xffffff00ul
))
1989 /** Called when we don't have a nickname set. Try to guess a good nickname
1990 * based on the hostname, and return it in a newly allocated string. If we
1991 * can't, return NULL and let the caller warn if it wants to. */
1993 get_default_nickname(void)
1995 static const char * const bad_default_nicknames
[] = {
1999 char localhostname
[256];
2000 char *cp
, *out
, *outp
;
2003 if (gethostname(localhostname
, sizeof(localhostname
)) < 0)
2006 /* Put it in lowercase; stop at the first dot. */
2007 if ((cp
= strchr(localhostname
, '.')))
2009 tor_strlower(localhostname
);
2011 /* Strip invalid characters. */
2013 out
= outp
= tor_malloc(strlen(localhostname
) + 1);
2015 if (strchr(LEGAL_NICKNAME_CHARACTERS
, *cp
))
2022 /* Enforce length. */
2023 if (strlen(out
) > MAX_NICKNAME_LEN
)
2024 out
[MAX_NICKNAME_LEN
]='\0';
2026 /* Check for dumb names. */
2027 for (i
= 0; bad_default_nicknames
[i
]; ++i
) {
2028 if (!strcmp(out
, bad_default_nicknames
[i
])) {
2037 /** Release storage held by <b>options</b> */
2039 config_free(config_format_t
*fmt
, void *options
)
2043 tor_assert(options
);
2045 for (i
=0; fmt
->vars
[i
].name
; ++i
)
2046 option_clear(fmt
, options
, &(fmt
->vars
[i
]));
2048 config_line_t
**linep
= STRUCT_VAR_P(options
, fmt
->extra
->var_offset
);
2049 config_free_lines(*linep
);
2055 /** Return true iff a and b contain identical keys and values in identical
2058 config_lines_eq(config_line_t
*a
, config_line_t
*b
)
2061 if (strcasecmp(a
->key
, b
->key
) || strcmp(a
->value
, b
->value
))
2071 /** Return true iff the option <b>var</b> has the same value in <b>o1</b>
2072 * and <b>o2</b>. Must not be called for LINELIST_S or OBSOLETE options.
2075 option_is_same(config_format_t
*fmt
,
2076 or_options_t
*o1
, or_options_t
*o2
, const char *name
)
2078 config_line_t
*c1
, *c2
;
2083 c1
= get_assigned_option(fmt
, o1
, name
);
2084 c2
= get_assigned_option(fmt
, o2
, name
);
2085 r
= config_lines_eq(c1
, c2
);
2086 config_free_lines(c1
);
2087 config_free_lines(c2
);
2091 /** Copy storage held by <b>old</b> into a new or_options_t and return it. */
2092 static or_options_t
*
2093 options_dup(config_format_t
*fmt
, or_options_t
*old
)
2095 or_options_t
*newopts
;
2097 config_line_t
*line
;
2099 newopts
= config_alloc(fmt
);
2100 for (i
=0; fmt
->vars
[i
].name
; ++i
) {
2101 if (fmt
->vars
[i
].type
== CONFIG_TYPE_LINELIST_S
)
2103 if (fmt
->vars
[i
].type
== CONFIG_TYPE_OBSOLETE
)
2105 line
= get_assigned_option(fmt
, old
, fmt
->vars
[i
].name
);
2108 if (config_assign(fmt
, newopts
, line
, 0, 0, &msg
) < 0) {
2109 log_err(LD_BUG
, "Bug: config_get_assigned_option() generated "
2110 "something we couldn't config_assign(): %s", msg
);
2115 config_free_lines(line
);
2120 /** Return a new empty or_options_t. Used for testing. */
2124 return config_alloc(&options_format
);
2127 /** Set <b>options</b> to hold reasonable defaults for most options.
2128 * Each option defaults to zero. */
2130 options_init(or_options_t
*options
)
2132 config_init(&options_format
, options
);
2135 /* Set all vars in the configuration object 'options' to their default
2138 config_init(config_format_t
*fmt
, void *options
)
2142 CHECK(fmt
, options
);
2144 for (i
=0; fmt
->vars
[i
].name
; ++i
) {
2145 var
= &fmt
->vars
[i
];
2146 if (!var
->initvalue
)
2147 continue; /* defaults to NULL or 0 */
2148 option_reset(fmt
, options
, var
, 1);
2152 /** Allocate and return a new string holding the written-out values of the vars
2153 * in 'options'. If 'minimal', do not write out any default-valued vars.
2154 * Else, if comment_defaults, write default values as comments.
2157 config_dump(config_format_t
*fmt
, void *options
, int minimal
,
2158 int comment_defaults
)
2160 smartlist_t
*elements
;
2161 or_options_t
*defaults
;
2162 config_line_t
*line
, *assigned
;
2168 defaults
= config_alloc(fmt
);
2169 config_init(fmt
, defaults
);
2171 /* XXX use a 1 here so we don't add a new log line while dumping */
2172 if (fmt
->validate_fn(NULL
,defaults
, 1, &msg
) < 0) {
2173 log_err(LD_BUG
, "Failed to validate default config.");
2178 elements
= smartlist_create();
2179 for (i
=0; fmt
->vars
[i
].name
; ++i
) {
2180 int comment_option
= 0;
2181 if (fmt
->vars
[i
].type
== CONFIG_TYPE_OBSOLETE
||
2182 fmt
->vars
[i
].type
== CONFIG_TYPE_LINELIST_S
)
2184 /* Don't save 'hidden' control variables. */
2185 if (!strcmpstart(fmt
->vars
[i
].name
, "__"))
2187 if (minimal
&& option_is_same(fmt
, options
, defaults
, fmt
->vars
[i
].name
))
2189 else if (comment_defaults
&&
2190 option_is_same(fmt
, options
, defaults
, fmt
->vars
[i
].name
))
2193 desc
= config_find_description(fmt
, fmt
->vars
[i
].name
);
2194 line
= assigned
= get_assigned_option(fmt
, options
, fmt
->vars
[i
].name
);
2197 /* Only dump the description if there's something to describe. */
2198 wrap_string(elements
, desc
, 78, "# ", "# ");
2201 for (; line
; line
= line
->next
) {
2202 size_t len
= strlen(line
->key
) + strlen(line
->value
) + 5;
2204 tmp
= tor_malloc(len
);
2205 if (tor_snprintf(tmp
, len
, "%s%s %s\n",
2206 comment_option
? "# " : "",
2207 line
->key
, line
->value
)<0) {
2208 log_err(LD_BUG
,"Internal error writing option value");
2211 smartlist_add(elements
, tmp
);
2213 config_free_lines(assigned
);
2217 line
= *(config_line_t
**)STRUCT_VAR_P(options
, fmt
->extra
->var_offset
);
2218 for (; line
; line
= line
->next
) {
2219 size_t len
= strlen(line
->key
) + strlen(line
->value
) + 3;
2221 tmp
= tor_malloc(len
);
2222 if (tor_snprintf(tmp
, len
, "%s %s\n", line
->key
, line
->value
)<0) {
2223 log_err(LD_BUG
,"Internal error writing option value");
2226 smartlist_add(elements
, tmp
);
2230 result
= smartlist_join_strings(elements
, "", 0, NULL
);
2231 SMARTLIST_FOREACH(elements
, char *, cp
, tor_free(cp
));
2232 smartlist_free(elements
);
2233 config_free(fmt
, defaults
);
2237 /** Return a string containing a possible configuration file that would give
2238 * the configuration in <b>options</b>. If <b>minimal</b> is true, do not
2239 * include options that are the same as Tor's defaults.
2242 options_dump(or_options_t
*options
, int minimal
)
2244 return config_dump(&options_format
, options
, minimal
, 0);
2247 /** Return 0 if every element of sl is a string holding a decimal
2248 * representation of a port number, or if sl is NULL.
2249 * Otherwise set *msg and return -1. */
2251 validate_ports_csv(smartlist_t
*sl
, const char *name
, char **msg
)
2260 SMARTLIST_FOREACH(sl
, const char *, cp
,
2263 if (i
< 1 || i
> 65535) {
2264 int r
= tor_snprintf(buf
, sizeof(buf
),
2265 "Port '%s' out of range in %s", cp
, name
);
2266 *msg
= tor_strdup(r
>= 0 ? buf
: "internal error");
2273 /** Lowest allowable value for RendPostPeriod; if this is too low, hidden
2274 * services can overload the directory system. */
2275 #define MIN_REND_POST_PERIOD (5*60)
2277 /** Highest allowable value for RendPostPeriod. */
2278 #define MAX_DIR_PERIOD (MIN_ONION_KEY_LIFETIME/2)
2280 /** Return 0 if every setting in <b>options</b> is reasonable, and a
2281 * permissible transition from <b>old_options</b>. Else return -1.
2282 * Should have no side effects, except for normalizing the contents of
2285 * On error, tor_strdup an error explanation into *<b>msg</b>.
2288 * If <b>from_setconf</b>, we were called by the controller, and our
2289 * Log line should stay empty. If it's 0, then give us a default log
2290 * if there are no logs defined.
2293 options_validate(or_options_t
*old_options
, or_options_t
*options
,
2294 int from_setconf
, char **msg
)
2298 const char *uname
= get_uname();
2300 #define REJECT(arg) \
2301 do { *msg = tor_strdup(arg); return -1; } while (0)
2302 #define COMPLAIN(arg) do { log(LOG_WARN, LD_CONFIG, arg); } while (0)
2307 if (options
->ORPort
< 0 || options
->ORPort
> 65535)
2308 REJECT("ORPort option out of bounds.");
2310 if (server_mode(options
) &&
2311 (!strcmpstart(uname
, "Windows 95") ||
2312 !strcmpstart(uname
, "Windows 98") ||
2313 !strcmpstart(uname
, "Windows Me"))) {
2314 log(LOG_WARN
, LD_CONFIG
, "Tor is running as a server, but you are "
2315 "running %s; this probably won't work. See "
2316 "http://wiki.noreply.org/noreply/TheOnionRouter/TorFAQ#ServerOS "
2317 "for details.", uname
);
2320 if (options
->ORPort
== 0 && options
->ORListenAddress
!= NULL
)
2321 REJECT("ORPort must be defined if ORListenAddress is defined.");
2323 if (options
->DirPort
== 0 && options
->DirListenAddress
!= NULL
)
2324 REJECT("DirPort must be defined if DirListenAddress is defined.");
2326 if (options
->ControlPort
== 0 && options
->ControlListenAddress
!= NULL
)
2327 REJECT("ControlPort must be defined if ControlListenAddress is defined.");
2329 if (options
->TransPort
== 0 && options
->TransListenAddress
!= NULL
)
2330 REJECT("TransPort must be defined if TransListenAddress is defined.");
2332 if (options
->NatdPort
== 0 && options
->NatdListenAddress
!= NULL
)
2333 REJECT("NatdPort must be defined if NatdListenAddress is defined.");
2335 /* Don't gripe about SocksPort 0 with SocksListenAddress set; a standard
2336 * configuration does this. */
2338 for (i
= 0; i
< 3; ++i
) {
2339 int is_socks
= i
==0;
2340 int is_trans
= i
==1;
2341 config_line_t
*line
, *opt
, *old
;
2344 opt
= options
->SocksListenAddress
;
2345 old
= old_options
? old_options
->SocksListenAddress
: NULL
;
2347 } else if (is_trans
) {
2348 opt
= options
->TransListenAddress
;
2349 old
= old_options
? old_options
->TransListenAddress
: NULL
;
2350 tp
= "transparent proxy";
2352 opt
= options
->NatdListenAddress
;
2353 old
= old_options
? old_options
->NatdListenAddress
: NULL
;
2357 for (line
= opt
; line
; line
= line
->next
) {
2358 char *address
= NULL
;
2361 if (parse_addr_port(LOG_WARN
, line
->value
, &address
, &addr
, &port
)<0)
2362 continue; /* We'll warn about this later. */
2363 if (!is_internal_IP(addr
, 1) &&
2364 (!old_options
|| !config_lines_eq(old
, opt
))) {
2366 "You specified a public address '%s' for a %s. Other "
2367 "people on the Internet might find your computer and use it as "
2368 "an open %s. Please don't allow this unless you have "
2369 "a good reason.", address
, tp
, tp
);
2375 if (validate_data_directory(options
)<0)
2376 REJECT("Invalid DataDirectory");
2378 if (options
->Nickname
== NULL
) {
2379 if (server_mode(options
)) {
2380 if (!(options
->Nickname
= get_default_nickname())) {
2381 log_notice(LD_CONFIG
, "Couldn't pick a nickname based on "
2382 "our hostname; using %s instead.", UNNAMED_ROUTER_NICKNAME
);
2383 options
->Nickname
= tor_strdup(UNNAMED_ROUTER_NICKNAME
);
2385 log_notice(LD_CONFIG
, "Choosing default nickname '%s'",
2390 if (!is_legal_nickname(options
->Nickname
)) {
2391 r
= tor_snprintf(buf
, sizeof(buf
),
2392 "Nickname '%s' is wrong length or contains illegal characters.",
2394 *msg
= tor_strdup(r
>= 0 ? buf
: "internal error");
2399 if (server_mode(options
) && !options
->ContactInfo
)
2400 log(LOG_NOTICE
, LD_CONFIG
, "Your ContactInfo config option is not set. "
2401 "Please consider setting it, so we can contact you if your server is "
2402 "misconfigured or something else goes wrong.");
2404 /* Special case on first boot if no Log options are given. */
2405 if (!options
->Logs
&& !options
->RunAsDaemon
&& !from_setconf
)
2406 config_line_append(&options
->Logs
, "Log", "notice stdout");
2408 if (options_init_logs(options
, 1)<0) /* Validate the log(s) */
2409 REJECT("Failed to validate Log options. See logs for details.");
2411 if (options
->NoPublish
) {
2412 log(LOG_WARN
, LD_CONFIG
,
2413 "NoPublish is obsolete. Use PublishServerDescriptor instead.");
2414 options
->PublishServerDescriptor
= 0;
2417 if (authdir_mode(options
)) {
2418 /* confirm that our address isn't broken, so we can complain now */
2420 if (resolve_my_address(LOG_WARN
, options
, &tmp
, NULL
) < 0)
2421 REJECT("Failed to resolve/guess local address. See logs for details.");
2425 if (options
->RunAsDaemon
&& torrc_fname
&& path_is_relative(torrc_fname
))
2426 REJECT("Can't use a relative path to torrc when RunAsDaemon is set.");
2429 if (options
->SocksPort
< 0 || options
->SocksPort
> 65535)
2430 REJECT("SocksPort option out of bounds.");
2432 if (options
->TransPort
< 0 || options
->TransPort
> 65535)
2433 REJECT("TransPort option out of bounds.");
2435 if (options
->NatdPort
< 0 || options
->NatdPort
> 65535)
2436 REJECT("NatdPort option out of bounds.");
2438 if (options
->SocksPort
== 0 && options
->TransPort
== 0 &&
2439 options
->NatdPort
== 0 && options
->ORPort
== 0)
2440 REJECT("SocksPort, TransPort, NatdPort, and ORPort are all undefined? "
2443 if (options
->ControlPort
< 0 || options
->ControlPort
> 65535)
2444 REJECT("ControlPort option out of bounds.");
2446 if (options
->DirPort
< 0 || options
->DirPort
> 65535)
2447 REJECT("DirPort option out of bounds.");
2449 #ifndef USE_TRANSPARENT
2450 if (options
->TransPort
|| options
->TransListenAddress
)
2451 REJECT("TransPort and TransListenAddress are disabled in this build.");
2454 if (options
->StrictExitNodes
&&
2455 (!options
->ExitNodes
|| !strlen(options
->ExitNodes
)) &&
2457 (old_options
->StrictExitNodes
!= options
->StrictExitNodes
) ||
2458 (!opt_streq(old_options
->ExitNodes
, options
->ExitNodes
))))
2459 COMPLAIN("StrictExitNodes set, but no ExitNodes listed.");
2461 if (options
->StrictEntryNodes
&&
2462 (!options
->EntryNodes
|| !strlen(options
->EntryNodes
)) &&
2464 (old_options
->StrictEntryNodes
!= options
->StrictEntryNodes
) ||
2465 (!opt_streq(old_options
->EntryNodes
, options
->EntryNodes
))))
2466 COMPLAIN("StrictEntryNodes set, but no EntryNodes listed.");
2468 if (options
->AuthoritativeDir
) {
2469 if (!options
->ContactInfo
)
2470 REJECT("Authoritative directory servers must set ContactInfo");
2471 if (options
->V1AuthoritativeDir
&& !options
->RecommendedVersions
)
2472 REJECT("V1 auth dir servers must set RecommendedVersions.");
2473 if (!options
->RecommendedClientVersions
)
2474 options
->RecommendedClientVersions
=
2475 config_lines_dup(options
->RecommendedVersions
);
2476 if (!options
->RecommendedServerVersions
)
2477 options
->RecommendedServerVersions
=
2478 config_lines_dup(options
->RecommendedVersions
);
2479 if (options
->VersioningAuthoritativeDir
&&
2480 (!options
->RecommendedClientVersions
||
2481 !options
->RecommendedServerVersions
))
2482 REJECT("Versioning auth dir servers must set Recommended*Versions.");
2483 if (options
->UseEntryGuards
) {
2484 log_info(LD_CONFIG
, "Authoritative directory servers can't set "
2485 "UseEntryGuards. Disabling.");
2486 options
->UseEntryGuards
= 0;
2490 if (options
->AuthoritativeDir
&& !options
->DirPort
)
2491 REJECT("Running as authoritative directory, but no DirPort set.");
2493 if (options
->AuthoritativeDir
&& !options
->ORPort
)
2494 REJECT("Running as authoritative directory, but no ORPort set.");
2496 if (options
->AuthoritativeDir
&& options
->ClientOnly
)
2497 REJECT("Running as authoritative directory, but ClientOnly also set.");
2499 if (options
->ConnLimit
<= 0) {
2500 r
= tor_snprintf(buf
, sizeof(buf
),
2501 "ConnLimit must be greater than 0, but was set to %d",
2502 options
->ConnLimit
);
2503 *msg
= tor_strdup(r
>= 0 ? buf
: "internal error");
2507 if (validate_ports_csv(options
->FirewallPorts
, "FirewallPorts", msg
) < 0)
2510 if (validate_ports_csv(options
->LongLivedPorts
, "LongLivedPorts", msg
) < 0)
2513 if (options
->FascistFirewall
&& !options
->ReachableAddresses
) {
2514 if (options
->FirewallPorts
&& smartlist_len(options
->FirewallPorts
)) {
2515 /* We already have firewall ports set, so migrate them to
2516 * ReachableAddresses, which will set ReachableORAddresses and
2517 * ReachableDirAddresses if they aren't set explicitly. */
2518 smartlist_t
*instead
= smartlist_create();
2519 config_line_t
*new_line
= tor_malloc_zero(sizeof(config_line_t
));
2520 new_line
->key
= tor_strdup("ReachableAddresses");
2521 /* If we're configured with the old format, we need to prepend some
2523 SMARTLIST_FOREACH(options
->FirewallPorts
, const char *, portno
,
2525 int p
= atoi(portno
);
2529 tor_snprintf(s
, 16, "*:%d", p
);
2530 smartlist_add(instead
, s
);
2532 new_line
->value
= smartlist_join_strings(instead
,",",0,NULL
);
2533 /* These have been deprecated since 0.1.1.5-alpha-cvs */
2534 log(LOG_NOTICE
, LD_CONFIG
,
2535 "Converting FascistFirewall and FirewallPorts "
2536 "config options to new format: \"ReachableAddresses %s\"",
2538 options
->ReachableAddresses
= new_line
;
2539 SMARTLIST_FOREACH(instead
, char *, cp
, tor_free(cp
));
2540 smartlist_free(instead
);
2542 /* We do not have FirewallPorts set, so add 80 to
2543 * ReachableDirAddresses, and 443 to ReachableORAddresses. */
2544 if (!options
->ReachableDirAddresses
) {
2545 config_line_t
*new_line
= tor_malloc_zero(sizeof(config_line_t
));
2546 new_line
->key
= tor_strdup("ReachableDirAddresses");
2547 new_line
->value
= tor_strdup("*:80");
2548 options
->ReachableDirAddresses
= new_line
;
2549 log(LOG_NOTICE
, LD_CONFIG
, "Converting FascistFirewall config option "
2550 "to new format: \"ReachableDirAddresses *:80\"");
2552 if (!options
->ReachableORAddresses
) {
2553 config_line_t
*new_line
= tor_malloc_zero(sizeof(config_line_t
));
2554 new_line
->key
= tor_strdup("ReachableORAddresses");
2555 new_line
->value
= tor_strdup("*:443");
2556 options
->ReachableORAddresses
= new_line
;
2557 log(LOG_NOTICE
, LD_CONFIG
, "Converting FascistFirewall config option "
2558 "to new format: \"ReachableORAddresses *:443\"");
2563 for (i
=0; i
<3; i
++) {
2564 config_line_t
**linep
=
2565 (i
==0) ? &options
->ReachableAddresses
:
2566 (i
==1) ? &options
->ReachableORAddresses
:
2567 &options
->ReachableDirAddresses
;
2570 /* We need to end with a reject *:*, not an implicit accept *:* */
2572 if (!strcmp((*linep
)->value
, "reject *:*")) /* already there */
2574 linep
= &((*linep
)->next
);
2576 *linep
= tor_malloc_zero(sizeof(config_line_t
));
2577 (*linep
)->key
= tor_strdup(
2578 (i
==0) ? "ReachableAddresses" :
2579 (i
==1) ? "ReachableORAddresses" :
2580 "ReachableDirAddresses");
2581 (*linep
)->value
= tor_strdup("reject *:*");
2587 if ((options
->ReachableAddresses
||
2588 options
->ReachableORAddresses
||
2589 options
->ReachableDirAddresses
) &&
2590 server_mode(options
))
2591 REJECT("Servers must be able to freely connect to the rest "
2592 "of the Internet, so they must not set Reachable*Addresses "
2593 "or FascistFirewall.");
2595 options
->_AllowInvalid
= 0;
2596 if (options
->AllowInvalidNodes
) {
2597 SMARTLIST_FOREACH(options
->AllowInvalidNodes
, const char *, cp
, {
2598 if (!strcasecmp(cp
, "entry"))
2599 options
->_AllowInvalid
|= ALLOW_INVALID_ENTRY
;
2600 else if (!strcasecmp(cp
, "exit"))
2601 options
->_AllowInvalid
|= ALLOW_INVALID_EXIT
;
2602 else if (!strcasecmp(cp
, "middle"))
2603 options
->_AllowInvalid
|= ALLOW_INVALID_MIDDLE
;
2604 else if (!strcasecmp(cp
, "introduction"))
2605 options
->_AllowInvalid
|= ALLOW_INVALID_INTRODUCTION
;
2606 else if (!strcasecmp(cp
, "rendezvous"))
2607 options
->_AllowInvalid
|= ALLOW_INVALID_RENDEZVOUS
;
2609 r
= tor_snprintf(buf
, sizeof(buf
),
2610 "Unrecognized value '%s' in AllowInvalidNodes", cp
);
2611 *msg
= tor_strdup(r
>= 0 ? buf
: "internal error");
2618 if (options
->SocksPort
>= 1 &&
2619 (options
->PathlenCoinWeight
< 0.0 || options
->PathlenCoinWeight
>= 1.0))
2620 REJECT("PathlenCoinWeight option must be >=0.0 and <1.0.");
2623 if (options
->RendPostPeriod
< MIN_REND_POST_PERIOD
) {
2624 log(LOG_WARN
,LD_CONFIG
,"RendPostPeriod option must be at least %d seconds."
2625 " Clipping.", MIN_REND_POST_PERIOD
);
2626 options
->RendPostPeriod
= MIN_REND_POST_PERIOD
;
2629 if (options
->RendPostPeriod
> MAX_DIR_PERIOD
) {
2630 log(LOG_WARN
, LD_CONFIG
, "RendPostPeriod is too large; clipping to %ds.",
2632 options
->RendPostPeriod
= MAX_DIR_PERIOD
;
2635 if (options
->KeepalivePeriod
< 1)
2636 REJECT("KeepalivePeriod option must be positive.");
2638 if (options
->BandwidthRate
> INT_MAX
) {
2639 r
= tor_snprintf(buf
, sizeof(buf
),
2640 "BandwidthRate must be less than %d",INT_MAX
);
2641 *msg
= tor_strdup(r
>= 0 ? buf
: "internal error");
2644 if (options
->BandwidthBurst
> INT_MAX
) {
2645 r
= tor_snprintf(buf
, sizeof(buf
),
2646 "BandwidthBurst must be less than %d",INT_MAX
);
2647 *msg
= tor_strdup(r
>= 0 ? buf
: "internal error");
2650 if (server_mode(options
)) {
2651 if (options
->BandwidthRate
< ROUTER_REQUIRED_MIN_BANDWIDTH
*2) {
2652 r
= tor_snprintf(buf
, sizeof(buf
),
2653 "BandwidthRate is set to %d bytes/second. "
2654 "For servers, it must be at least %d.",
2655 (int)options
->BandwidthRate
,
2656 ROUTER_REQUIRED_MIN_BANDWIDTH
*2);
2657 *msg
= tor_strdup(r
>= 0 ? buf
: "internal error");
2659 } else if (options
->MaxAdvertisedBandwidth
<
2660 ROUTER_REQUIRED_MIN_BANDWIDTH
) {
2661 r
= tor_snprintf(buf
, sizeof(buf
),
2662 "MaxAdvertisedBandwidth is set to %d bytes/second. "
2663 "For servers, it must be at least %d.",
2664 (int)options
->MaxAdvertisedBandwidth
,
2665 ROUTER_REQUIRED_MIN_BANDWIDTH
);
2666 *msg
= tor_strdup(r
>= 0 ? buf
: "internal error");
2671 if (options
->BandwidthRate
> options
->BandwidthBurst
)
2672 REJECT("BandwidthBurst must be at least equal to BandwidthRate.");
2674 if (accounting_parse_options(options
, 1)<0)
2675 REJECT("Failed to parse accounting options. See logs for details.");
2677 if (options
->HttpProxy
) { /* parse it now */
2678 if (parse_addr_port(LOG_WARN
, options
->HttpProxy
, NULL
,
2679 &options
->HttpProxyAddr
, &options
->HttpProxyPort
) < 0)
2680 REJECT("HttpProxy failed to parse or resolve. Please fix.");
2681 if (options
->HttpProxyPort
== 0) { /* give it a default */
2682 options
->HttpProxyPort
= 80;
2686 if (options
->HttpProxyAuthenticator
) {
2687 if (strlen(options
->HttpProxyAuthenticator
) >= 48)
2688 REJECT("HttpProxyAuthenticator is too long (>= 48 chars).");
2691 if (options
->HttpsProxy
) { /* parse it now */
2692 if (parse_addr_port(LOG_WARN
, options
->HttpsProxy
, NULL
,
2693 &options
->HttpsProxyAddr
, &options
->HttpsProxyPort
) <0)
2694 REJECT("HttpsProxy failed to parse or resolve. Please fix.");
2695 if (options
->HttpsProxyPort
== 0) { /* give it a default */
2696 options
->HttpsProxyPort
= 443;
2700 if (options
->HttpsProxyAuthenticator
) {
2701 if (strlen(options
->HttpsProxyAuthenticator
) >= 48)
2702 REJECT("HttpsProxyAuthenticator is too long (>= 48 chars).");
2705 if (options
->HashedControlPassword
) {
2706 if (decode_hashed_password(NULL
, options
->HashedControlPassword
)<0)
2707 REJECT("Bad HashedControlPassword: wrong length or bad encoding");
2709 if (options
->HashedControlPassword
&& options
->CookieAuthentication
)
2710 REJECT("Cannot set both HashedControlPassword and CookieAuthentication");
2712 if (options
->UseEntryGuards
&& ! options
->NumEntryGuards
)
2713 REJECT("Cannot enable UseEntryGuards with NumEntryGuards set to 0");
2715 #ifndef USE_EVENTDNS
2716 if (options
->ServerDNSResolvConfFile
)
2717 log(LOG_WARN
, LD_CONFIG
,
2718 "ServerDNSResolvConfFile only works when eventdns support is enabled.");
2721 if (check_nickname_list(options
->ExitNodes
, "ExitNodes", msg
))
2723 if (check_nickname_list(options
->EntryNodes
, "EntryNodes", msg
))
2725 if (check_nickname_list(options
->ExcludeNodes
, "ExcludeNodes", msg
))
2727 if (check_nickname_list(options
->RendNodes
, "RendNodes", msg
))
2729 if (check_nickname_list(options
->RendNodes
, "RendExcludeNodes", msg
))
2731 if (check_nickname_list(options
->TestVia
, "TestVia", msg
))
2733 if (check_nickname_list(options
->MyFamily
, "MyFamily", msg
))
2735 for (cl
= options
->NodeFamilies
; cl
; cl
= cl
->next
) {
2736 if (check_nickname_list(cl
->value
, "NodeFamily", msg
))
2740 if (validate_addr_policies(options
, msg
) < 0)
2743 for (cl
= options
->RedirectExit
; cl
; cl
= cl
->next
) {
2744 if (parse_redirect_line(NULL
, cl
, msg
)<0)
2748 if (options
->DirServers
) {
2750 !config_lines_eq(options
->DirServers
, old_options
->DirServers
))
2751 COMPLAIN("You have used DirServer to specify directory authorities in "
2752 "your configuration. This is potentially dangerous: it can "
2753 "make you look different from all other Tor users, and hurt "
2754 "your anonymity. Even if you've specified the same "
2755 "authorities as Tor uses by default, the defaults could "
2756 "change in the future. Be sure you know what you're doing.");
2757 for (cl
= options
->DirServers
; cl
; cl
= cl
->next
) {
2758 if (parse_dir_server_line(cl
->value
, 1)<0)
2759 REJECT("DirServer line did not parse. See logs for details.");
2763 if (rend_config_services(options
, 1) < 0)
2764 REJECT("Failed to configure rendezvous options. See logs for details.");
2766 if (parse_virtual_addr_network(options
->VirtualAddrNetwork
, 1, NULL
)<0)
2769 if (options
->PreferTunneledDirConns
&& !options
->TunnelDirConns
)
2770 REJECT("Must set TunnelDirConns if PreferTunneledDirConns is set.");
2777 /** Helper: return true iff s1 and s2 are both NULL, or both non-NULL
2780 opt_streq(const char *s1
, const char *s2
)
2784 else if (s1
&& s2
&& !strcmp(s1
,s2
))
2790 /** Check if any of the previous options have changed but aren't allowed to. */
2792 options_transition_allowed(or_options_t
*old
, or_options_t
*new_val
,
2798 if (!opt_streq(old
->PidFile
, new_val
->PidFile
)) {
2799 *msg
= tor_strdup("PidFile is not allowed to change.");
2803 if (old
->RunAsDaemon
!= new_val
->RunAsDaemon
) {
2804 *msg
= tor_strdup("While Tor is running, changing RunAsDaemon "
2809 if (strcmp(old
->DataDirectory
,new_val
->DataDirectory
)!=0) {
2811 int r
= tor_snprintf(buf
, sizeof(buf
),
2812 "While Tor is running, changing DataDirectory "
2813 "(\"%s\"->\"%s\") is not allowed.",
2814 old
->DataDirectory
, new_val
->DataDirectory
);
2815 *msg
= tor_strdup(r
>= 0 ? buf
: "internal error");
2819 if (!opt_streq(old
->User
, new_val
->User
)) {
2820 *msg
= tor_strdup("While Tor is running, changing User is not allowed.");
2824 if (!opt_streq(old
->Group
, new_val
->Group
)) {
2825 *msg
= tor_strdup("While Tor is running, changing Group is not allowed.");
2829 if (old
->HardwareAccel
!= new_val
->HardwareAccel
) {
2830 *msg
= tor_strdup("While Tor is running, changing HardwareAccel is "
2838 /** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
2839 * will require us to rotate the cpu and dns workers; else return 0. */
2841 options_transition_affects_workers(or_options_t
*old_options
,
2842 or_options_t
*new_options
)
2844 if (!opt_streq(old_options
->DataDirectory
, new_options
->DataDirectory
) ||
2845 old_options
->NumCpus
!= new_options
->NumCpus
||
2846 old_options
->ORPort
!= new_options
->ORPort
||
2847 old_options
->ServerDNSSearchDomains
!=
2848 new_options
->ServerDNSSearchDomains
||
2849 old_options
->SafeLogging
!= new_options
->SafeLogging
||
2850 old_options
->ClientOnly
!= new_options
->ClientOnly
||
2851 !config_lines_eq(old_options
->Logs
, new_options
->Logs
))
2854 /* Check whether log options match. */
2856 /* Nothing that changed matters. */
2860 /** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
2861 * will require us to generate a new descriptor; else return 0. */
2863 options_transition_affects_descriptor(or_options_t
*old_options
,
2864 or_options_t
*new_options
)
2866 if (!opt_streq(old_options
->DataDirectory
, new_options
->DataDirectory
) ||
2867 !opt_streq(old_options
->Nickname
,new_options
->Nickname
) ||
2868 !opt_streq(old_options
->Address
,new_options
->Address
) ||
2869 !config_lines_eq(old_options
->ExitPolicy
,new_options
->ExitPolicy
) ||
2870 old_options
->ORPort
!= new_options
->ORPort
||
2871 old_options
->DirPort
!= new_options
->DirPort
||
2872 old_options
->ClientOnly
!= new_options
->ClientOnly
||
2873 old_options
->NoPublish
!= new_options
->NoPublish
||
2874 old_options
->PublishServerDescriptor
!=
2875 new_options
->PublishServerDescriptor
||
2876 old_options
->BandwidthRate
!= new_options
->BandwidthRate
||
2877 old_options
->BandwidthBurst
!= new_options
->BandwidthBurst
||
2878 !opt_streq(old_options
->ContactInfo
, new_options
->ContactInfo
) ||
2879 !opt_streq(old_options
->MyFamily
, new_options
->MyFamily
) ||
2880 !opt_streq(old_options
->AccountingStart
, new_options
->AccountingStart
) ||
2881 old_options
->AccountingMax
!= new_options
->AccountingMax
)
2888 /** Return the directory on windows where we expect to find our application
2891 get_windows_conf_root(void)
2893 static int is_set
= 0;
2894 static char path
[MAX_PATH
+1];
2903 /* Find X:\documents and settings\username\application data\ .
2904 * We would use SHGetSpecialFolder path, but that wasn't added until IE4.
2906 if (!SUCCEEDED(SHGetSpecialFolderLocation(NULL
, CSIDL_APPDATA
,
2908 GetCurrentDirectory(MAX_PATH
, path
);
2911 "I couldn't find your application data folder: are you "
2912 "running an ancient version of Windows 95? Defaulting to \"%s\"",
2916 /* Convert the path from an "ID List" (whatever that is!) to a path. */
2917 result
= SHGetPathFromIDList(idl
, path
);
2918 /* Now we need to free the */
2921 m
->lpVtbl
->Free(m
, idl
);
2922 m
->lpVtbl
->Release(m
);
2924 if (!SUCCEEDED(result
)) {
2927 strlcat(path
,"\\tor",MAX_PATH
);
2933 /** Return the default location for our torrc file. */
2935 get_default_conf_file(void)
2938 static char path
[MAX_PATH
+1];
2939 strlcpy(path
, get_windows_conf_root(), MAX_PATH
);
2940 strlcat(path
,"\\torrc",MAX_PATH
);
2943 return (CONFDIR
"/torrc");
2947 /** Verify whether lst is a string containing valid-looking space-separated
2948 * nicknames, or NULL. Return 0 on success. Warn and return -1 on failure.
2951 check_nickname_list(const char *lst
, const char *name
, char **msg
)
2958 sl
= smartlist_create();
2959 smartlist_split_string(sl
, lst
, ",", SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, 0);
2960 SMARTLIST_FOREACH(sl
, const char *, s
,
2962 if (!is_legal_nickname_or_hexdigest(s
)) {
2964 int tmp
= tor_snprintf(buf
, sizeof(buf
),
2965 "Invalid nickname '%s' in %s line", s
, name
);
2966 *msg
= tor_strdup(tmp
>= 0 ? buf
: "internal error");
2971 SMARTLIST_FOREACH(sl
, char *, s
, tor_free(s
));
2976 /** Read a configuration file into <b>options</b>, finding the configuration
2977 * file location based on the command line. After loading the options,
2978 * validate them for consistency, then take actions based on them.
2979 * Return 0 if success, -1 if failure. */
2981 options_init_from_torrc(int argc
, char **argv
)
2983 or_options_t
*oldoptions
, *newoptions
;
2985 char *cf
=NULL
, *fname
=NULL
, *errmsg
=NULL
;
2987 int using_default_torrc
;
2988 int ignore_missing_torrc
;
2989 static char **backup_argv
;
2990 static int backup_argc
;
2992 if (argv
) { /* first time we're called. save commandline args */
2996 } else { /* we're reloading. need to clean up old options first. */
2999 oldoptions
= get_options();
3001 if (argc
> 1 && (!strcmp(argv
[1], "-h") || !strcmp(argv
[1],"--help"))) {
3005 if (argc
> 1 && !strcmp(argv
[1], "--list-torrc-options")) {
3006 /* For documenting validating whether we've documented everything. */
3007 list_torrc_options();
3011 if (argc
> 1 && (!strcmp(argv
[1],"--version"))) {
3012 printf("Tor version %s.\n",VERSION
);
3013 if (argc
> 2 && (!strcmp(argv
[2],"--version"))) {
3014 print_svn_version();
3019 newoptions
= tor_malloc_zero(sizeof(or_options_t
));
3020 newoptions
->_magic
= OR_OPTIONS_MAGIC
;
3021 options_init(newoptions
);
3023 /* learn config file name */
3025 using_default_torrc
= 1;
3026 ignore_missing_torrc
= 0;
3027 newoptions
->command
= CMD_RUN_TOR
;
3028 for (i
= 1; i
< argc
; ++i
) {
3029 if (i
< argc
-1 && !strcmp(argv
[i
],"-f")) {
3031 log(LOG_WARN
, LD_CONFIG
, "Duplicate -f options on command line.");
3034 fname
= tor_strdup(argv
[i
+1]);
3035 using_default_torrc
= 0;
3037 } else if (!strcmp(argv
[i
],"--ignore-missing-torrc")) {
3038 ignore_missing_torrc
= 1;
3039 } else if (!strcmp(argv
[i
],"--list-fingerprint")) {
3040 newoptions
->command
= CMD_LIST_FINGERPRINT
;
3041 } else if (!strcmp(argv
[i
],"--hash-password")) {
3042 newoptions
->command
= CMD_HASH_PASSWORD
;
3043 newoptions
->command_arg
= tor_strdup( (i
< argc
-1) ? argv
[i
+1] : "");
3045 } else if (!strcmp(argv
[i
],"--verify-config")) {
3046 newoptions
->command
= CMD_VERIFY_CONFIG
;
3049 if (using_default_torrc
) {
3050 /* didn't find one, try CONFDIR */
3051 const char *dflt
= get_default_conf_file();
3052 if (dflt
&& file_status(dflt
) == FN_FILE
) {
3053 fname
= tor_strdup(dflt
);
3057 fn
= expand_filename("~/.torrc");
3058 if (fn
&& file_status(fn
) == FN_FILE
) {
3062 fname
= tor_strdup(dflt
);
3065 fname
= tor_strdup(dflt
);
3070 log(LOG_DEBUG
, LD_CONFIG
, "Opening config file \"%s\"", fname
);
3072 tor_free(torrc_fname
);
3073 torrc_fname
= fname
;
3075 /* get config lines, assign them */
3076 if (file_status(fname
) != FN_FILE
||
3077 !(cf
= read_file_to_str(fname
,0,NULL
))) {
3078 if (using_default_torrc
== 1 || ignore_missing_torrc
) {
3079 log(LOG_NOTICE
, LD_CONFIG
, "Configuration file \"%s\" not present, "
3080 "using reasonable defaults.", fname
);
3081 tor_free(fname
); /* sets fname to NULL */
3084 log(LOG_WARN
, LD_CONFIG
,
3085 "Unable to open configuration file \"%s\".", fname
);
3088 } else { /* it opened successfully. use it. */
3089 retval
= config_get_lines(cf
, &cl
);
3093 retval
= config_assign(&options_format
, newoptions
, cl
, 0, 0, &errmsg
);
3094 config_free_lines(cl
);
3099 /* Go through command-line variables too */
3100 if (config_get_commandlines(argc
, argv
, &cl
) < 0)
3102 retval
= config_assign(&options_format
, newoptions
, cl
, 0, 0, &errmsg
);
3103 config_free_lines(cl
);
3107 /* Validate newoptions */
3108 if (options_validate(oldoptions
, newoptions
, 0, &errmsg
) < 0)
3111 if (options_transition_allowed(oldoptions
, newoptions
, &errmsg
) < 0)
3114 if (set_options(newoptions
, &errmsg
))
3115 goto err
; /* frees and replaces old options */
3121 config_free(&options_format
, newoptions
);
3123 log(LOG_WARN
,LD_CONFIG
,"Failed to parse/validate config: %s", errmsg
);
3129 /** Return the location for our configuration file.
3132 get_torrc_fname(void)
3137 return get_default_conf_file();
3140 /** Adjust the address map mased on the MapAddress elements in the
3141 * configuration <b>options</b>
3144 config_register_addressmaps(or_options_t
*options
)
3150 addressmap_clear_configured();
3151 elts
= smartlist_create();
3152 for (opt
= options
->AddressMap
; opt
; opt
= opt
->next
) {
3153 smartlist_split_string(elts
, opt
->value
, NULL
,
3154 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, 2);
3155 if (smartlist_len(elts
) >= 2) {
3156 from
= smartlist_get(elts
,0);
3157 to
= smartlist_get(elts
,1);
3158 if (address_is_invalid_destination(to
, 1)) {
3160 "Skipping invalid argument '%s' to MapAddress", to
);
3162 addressmap_register(from
, tor_strdup(to
), 0);
3163 if (smartlist_len(elts
)>2) {
3164 log_warn(LD_CONFIG
,"Ignoring extra arguments to MapAddress.");
3168 log_warn(LD_CONFIG
,"MapAddress '%s' has too few arguments. Ignoring.",
3171 SMARTLIST_FOREACH(elts
, char*, cp
, tor_free(cp
));
3172 smartlist_clear(elts
);
3174 smartlist_free(elts
);
3177 /** If <b>range</b> is of the form MIN-MAX, for MIN and MAX both
3178 * recognized log severity levels, set *<b>min_out</b> to MIN and
3179 * *<b>max_out</b> to MAX and return 0. Else, if <b>range</b> is of
3180 * the form MIN, act as if MIN-err had been specified. Else, warn and
3184 parse_log_severity_range(const char *range
, int *min_out
, int *max_out
)
3186 int levelMin
, levelMax
;
3188 cp
= strchr(range
, '-');
3191 levelMin
= LOG_DEBUG
;
3193 char *tmp_sev
= tor_strndup(range
, cp
- range
);
3194 levelMin
= parse_log_level(tmp_sev
);
3196 log_warn(LD_CONFIG
, "Unrecognized minimum log severity '%s': must be "
3197 "one of err|warn|notice|info|debug", tmp_sev
);
3206 levelMax
= parse_log_level(cp
+1);
3208 log_warn(LD_CONFIG
, "Unrecognized maximum log severity '%s': must be "
3209 "one of err|warn|notice|info|debug", cp
+1);
3214 levelMin
= parse_log_level(range
);
3216 log_warn(LD_CONFIG
, "Unrecognized log severity '%s': must be one of "
3217 "err|warn|notice|info|debug", range
);
3223 *min_out
= levelMin
;
3224 *max_out
= levelMax
;
3230 * Initialize the logs based on the configuration file.
3233 options_init_logs(or_options_t
*options
, int validate_only
)
3242 options
->RunAsDaemon
;
3246 elts
= smartlist_create();
3248 for (opt
= options
->Logs
; opt
; opt
= opt
->next
) {
3249 int levelMin
=LOG_DEBUG
, levelMax
=LOG_ERR
;
3250 smartlist_split_string(elts
, opt
->value
, NULL
,
3251 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, 3);
3252 if (smartlist_len(elts
) == 0) {
3253 log_warn(LD_CONFIG
, "No arguments to Log option 'Log %s'", opt
->value
);
3254 ok
= 0; goto cleanup
;
3256 if (parse_log_severity_range(smartlist_get(elts
,0), &levelMin
,
3258 ok
= 0; goto cleanup
;
3260 if (smartlist_len(elts
) < 2) { /* only loglevels were provided */
3261 if (!validate_only
) {
3264 "Can't log to stdout with RunAsDaemon set; skipping stdout");
3266 add_stream_log(levelMin
, levelMax
, "<stdout>", stdout
);
3271 if (!strcasecmp(smartlist_get(elts
,1), "file")) {
3272 if (smartlist_len(elts
) != 3) {
3273 log_warn(LD_CONFIG
, "Bad syntax on file Log option 'Log %s'",
3275 ok
= 0; goto cleanup
;
3277 if (!validate_only
) {
3278 if (add_file_log(levelMin
, levelMax
, smartlist_get(elts
, 2)) < 0) {
3279 log_warn(LD_CONFIG
, "Couldn't open file for 'Log %s'", opt
->value
);
3285 if (smartlist_len(elts
) != 2) {
3286 log_warn(LD_CONFIG
, "Wrong number of arguments on Log option 'Log %s'",
3288 ok
= 0; goto cleanup
;
3290 if (!strcasecmp(smartlist_get(elts
,1), "stdout")) {
3292 log_warn(LD_CONFIG
, "Can't log to stdout with RunAsDaemon set.");
3293 ok
= 0; goto cleanup
;
3295 if (!validate_only
) {
3296 add_stream_log(levelMin
, levelMax
, "<stdout>", stdout
);
3298 } else if (!strcasecmp(smartlist_get(elts
,1), "stderr")) {
3300 log_warn(LD_CONFIG
, "Can't log to stderr with RunAsDaemon set.");
3301 ok
= 0; goto cleanup
;
3303 if (!validate_only
) {
3304 add_stream_log(levelMin
, levelMax
, "<stderr>", stderr
);
3306 } else if (!strcasecmp(smartlist_get(elts
,1), "syslog")) {
3307 #ifdef HAVE_SYSLOG_H
3309 add_syslog_log(levelMin
, levelMax
);
3311 log_warn(LD_CONFIG
, "Syslog is not supported on this system. Sorry.");
3314 log_warn(LD_CONFIG
, "Unrecognized log type %s",
3315 (const char*)smartlist_get(elts
,1));
3316 if (strchr(smartlist_get(elts
,1), '/') ||
3317 strchr(smartlist_get(elts
,1), '\\')) {
3318 log_warn(LD_CONFIG
, "Did you mean to say 'Log %s file %s' ?",
3319 (const char *)smartlist_get(elts
,0),
3320 (const char *)smartlist_get(elts
,1));
3322 ok
= 0; goto cleanup
;
3325 SMARTLIST_FOREACH(elts
, char*, cp
, tor_free(cp
));
3326 smartlist_clear(elts
);
3328 smartlist_free(elts
);
3333 /** Parse a single RedirectExit line's contents from <b>line</b>. If
3334 * they are valid, and <b>result</b> is not NULL, add an element to
3335 * <b>result</b> and return 0. Else if they are valid, return 0.
3336 * Else set *msg and return -1. */
3338 parse_redirect_line(smartlist_t
*result
, config_line_t
*line
, char **msg
)
3340 smartlist_t
*elements
= NULL
;
3345 r
= tor_malloc_zero(sizeof(exit_redirect_t
));
3346 elements
= smartlist_create();
3347 smartlist_split_string(elements
, line
->value
, NULL
,
3348 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, 0);
3349 if (smartlist_len(elements
) != 2) {
3350 *msg
= tor_strdup("Wrong number of elements in RedirectExit line");
3353 if (parse_addr_and_port_range(smartlist_get(elements
,0),&r
->addr
,&r
->mask
,
3354 &r
->port_min
,&r
->port_max
)) {
3355 *msg
= tor_strdup("Error parsing source address in RedirectExit line");
3358 if (0==strcasecmp(smartlist_get(elements
,1), "pass")) {
3361 if (parse_addr_port(LOG_WARN
, smartlist_get(elements
,1),NULL
,
3362 &r
->addr_dest
, &r
->port_dest
)) {
3363 *msg
= tor_strdup("Error parsing dest address in RedirectExit line");
3373 SMARTLIST_FOREACH(elements
, char *, cp
, tor_free(cp
));
3374 smartlist_free(elements
);
3377 smartlist_add(result
, r
);
3387 /** Read the contents of a DirServer line from <b>line</b>. Return 0
3388 * if the line is well-formed, and -1 if it isn't. If
3389 * <b>validate_only</b> is 0, and the line is well-formed, then add
3390 * the dirserver described in the line as a valid server. */
3392 parse_dir_server_line(const char *line
, int validate_only
)
3394 smartlist_t
*items
= NULL
;
3396 char *addrport
=NULL
, *address
=NULL
, *nickname
=NULL
, *fingerprint
=NULL
;
3397 uint16_t dir_port
= 0, or_port
= 0;
3398 char digest
[DIGEST_LEN
];
3399 int is_v1_authority
= 0, is_hidserv_authority
= 0,
3400 is_not_hidserv_authority
= 0, is_v2_authority
= 1;
3402 items
= smartlist_create();
3403 smartlist_split_string(items
, line
, NULL
,
3404 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, -1);
3405 if (smartlist_len(items
) < 1) {
3406 log_warn(LD_CONFIG
, "No arguments on DirServer line.");
3410 if (is_legal_nickname(smartlist_get(items
, 0))) {
3411 nickname
= smartlist_get(items
, 0);
3412 smartlist_del_keeporder(items
, 0);
3415 while (smartlist_len(items
)) {
3416 char *flag
= smartlist_get(items
, 0);
3417 if (TOR_ISDIGIT(flag
[0]))
3419 if (!strcasecmp(flag
, "v1")) {
3420 is_v1_authority
= is_hidserv_authority
= 1;
3421 } else if (!strcasecmp(flag
, "hs")) {
3422 is_hidserv_authority
= 1;
3423 } else if (!strcasecmp(flag
, "no-hs")) {
3424 is_not_hidserv_authority
= 1;
3425 } else if (!strcasecmp(flag
, "no-v2")) {
3426 is_v2_authority
= 0;
3427 } else if (!strcasecmpstart(flag
, "orport=")) {
3429 char *portstring
= flag
+ strlen("orport=");
3430 or_port
= (uint16_t) tor_parse_long(portstring
, 10, 1, 65535, &ok
, NULL
);
3432 log_warn(LD_CONFIG
, "Invalid orport '%s' on DirServer line.",
3435 log_warn(LD_CONFIG
, "Unrecognized flag '%s' on DirServer line",
3439 smartlist_del_keeporder(items
, 0);
3442 if (is_not_hidserv_authority
)
3443 is_hidserv_authority
= 0;
3445 if (smartlist_len(items
) < 2) {
3446 log_warn(LD_CONFIG
, "Too few arguments to DirServer line.");
3449 addrport
= smartlist_get(items
, 0);
3450 smartlist_del_keeporder(items
, 0);
3451 if (parse_addr_port(LOG_WARN
, addrport
, &address
, NULL
, &dir_port
)<0) {
3452 log_warn(LD_CONFIG
, "Error parsing DirServer address '%s'", addrport
);
3456 log_warn(LD_CONFIG
, "Missing port in DirServer address '%s'",addrport
);
3460 fingerprint
= smartlist_join_strings(items
, "", 0, NULL
);
3461 if (strlen(fingerprint
) != HEX_DIGEST_LEN
) {
3462 log_warn(LD_CONFIG
, "Key digest for DirServer is wrong length.");
3465 if (base16_decode(digest
, DIGEST_LEN
, fingerprint
, HEX_DIGEST_LEN
)<0) {
3466 log_warn(LD_CONFIG
, "Unable to decode DirServer key digest.");
3470 if (!validate_only
) {
3471 log_debug(LD_DIR
, "Trusted dirserver at %s:%d (%s)", address
,
3473 (char*)smartlist_get(items
,1));
3474 add_trusted_dir_server(nickname
, address
, dir_port
, or_port
, digest
,
3476 is_v2_authority
, is_hidserv_authority
);
3487 SMARTLIST_FOREACH(items
, char*, s
, tor_free(s
));
3488 smartlist_free(items
);
3492 tor_free(fingerprint
);
3496 /** Adjust the value of options->DataDirectory, or fill it in if it's
3497 * absent. Return 0 on success, -1 on failure. */
3499 normalize_data_directory(or_options_t
*options
)
3503 if (options
->DataDirectory
)
3504 return 0; /* all set */
3505 p
= tor_malloc(MAX_PATH
);
3506 strlcpy(p
,get_windows_conf_root(),MAX_PATH
);
3507 options
->DataDirectory
= p
;
3510 const char *d
= options
->DataDirectory
;
3514 if (strncmp(d
,"~/",2) == 0) {
3515 char *fn
= expand_filename(d
);
3517 log_err(LD_CONFIG
,"Failed to expand filename \"%s\".", d
);
3520 if (!options
->DataDirectory
&& !strcmp(fn
,"/.tor")) {
3521 /* If our homedir is /, we probably don't want to use it. */
3522 /* Default to LOCALSTATEDIR/tor which is probably closer to what we
3525 "Default DataDirectory is \"~/.tor\". This expands to "
3526 "\"%s\", which is probably not what you want. Using \"%s/tor\" "
3527 "instead", fn
, LOCALSTATEDIR
);
3529 fn
= tor_strdup(LOCALSTATEDIR
"/tor");
3532 tor_free(options
->DataDirectory
);
3533 options
->DataDirectory
= fn
;
3539 /** Check and normalize the value of options->DataDirectory; return 0 if it
3540 * sane, -1 otherwise. */
3542 validate_data_directory(or_options_t
*options
)
3544 if (normalize_data_directory(options
) < 0)
3546 tor_assert(options
->DataDirectory
);
3547 if (strlen(options
->DataDirectory
) > (512-128)) {
3548 log_err(LD_CONFIG
, "DataDirectory is too long.");
3554 /** This string must remain the same forevermore. It is how we
3555 * recognize that the torrc file doesn't need to be backed up. */
3556 #define GENERATED_FILE_PREFIX "# This file was generated by Tor; " \
3557 "if you edit it, comments will not be preserved"
3558 /** This string can change; it tries to give the reader an idea
3559 * that editing this file by hand is not a good plan. */
3560 #define GENERATED_FILE_COMMENT "# The old torrc file was renamed " \
3561 "to torrc.orig.1 or similar, and Tor will ignore it"
3563 /** Save a configuration file for the configuration in <b>options</b>
3564 * into the file <b>fname</b>. If the file already exists, and
3565 * doesn't begin with GENERATED_FILE_PREFIX, rename it. Otherwise
3566 * replace it. Return 0 on success, -1 on failure. */
3568 write_configuration_file(const char *fname
, or_options_t
*options
)
3570 char *old_val
=NULL
, *new_val
=NULL
, *new_conf
=NULL
;
3571 int rename_old
= 0, r
;
3575 switch (file_status(fname
)) {
3577 old_val
= read_file_to_str(fname
, 0, NULL
);
3578 if (strcmpstart(old_val
, GENERATED_FILE_PREFIX
)) {
3589 "Config file \"%s\" is not a file? Failing.", fname
);
3594 if (!(new_conf
= options_dump(options
, 1))) {
3595 log_warn(LD_BUG
, "Couldn't get configuration string");
3599 len
= strlen(new_conf
)+256;
3600 new_val
= tor_malloc(len
);
3601 tor_snprintf(new_val
, len
, "%s\n%s\n\n%s",
3602 GENERATED_FILE_PREFIX
, GENERATED_FILE_COMMENT
, new_conf
);
3606 size_t fn_tmp_len
= strlen(fname
)+32;
3608 tor_assert(fn_tmp_len
> strlen(fname
)); /*check for overflow*/
3609 fn_tmp
= tor_malloc(fn_tmp_len
);
3611 if (tor_snprintf(fn_tmp
, fn_tmp_len
, "%s.orig.%d", fname
, i
)<0) {
3612 log_warn(LD_BUG
, "tor_snprintf failed inexplicably");
3616 if (file_status(fn_tmp
) == FN_NOENT
)
3620 log_notice(LD_CONFIG
, "Renaming old configuration file to \"%s\"", fn_tmp
);
3621 if (rename(fname
, fn_tmp
) < 0) {
3623 "Couldn't rename configuration file \"%s\" to \"%s\": %s",
3624 fname
, fn_tmp
, strerror(errno
));
3631 if (write_str_to_file(fname
, new_val
, 0) < 0)
3645 * Save the current configuration file value to disk. Return 0 on
3646 * success, -1 on failure.
3649 options_save_current(void)
3652 /* This fails if we can't write to our configuration file.
3654 * If we try falling back to datadirectory or something, we have a better
3655 * chance of saving the configuration, but a better chance of doing
3656 * something the user never expected. Let's just warn instead. */
3657 return write_configuration_file(torrc_fname
, get_options());
3659 return write_configuration_file(get_default_conf_file(), get_options());
3662 /** Mapping from a unit name to a multiplier for converting that unit into a
3664 struct unit_table_t
{
3666 uint64_t multiplier
;
3669 static struct unit_table_t memory_units
[] = {
3675 { "kilobyte", 1<<10 },
3676 { "kilobytes", 1<<10 },
3679 { "megabyte", 1<<20 },
3680 { "megabytes", 1<<20 },
3682 { "gigabyte", 1<<30 },
3683 { "gigabytes", 1<<30 },
3684 { "tb", U64_LITERAL(1)<<40 },
3685 { "terabyte", U64_LITERAL(1)<<40 },
3686 { "terabytes", U64_LITERAL(1)<<40 },
3690 static struct unit_table_t time_units
[] = {
3698 { "day", 24*60*60 },
3699 { "days", 24*60*60 },
3700 { "week", 7*24*60*60 },
3701 { "weeks", 7*24*60*60 },
3705 /** Parse a string <b>val</b> containing a number, zero or more
3706 * spaces, and an optional unit string. If the unit appears in the
3707 * table <b>u</b>, then multiply the number by the unit multiplier.
3708 * On success, set *<b>ok</b> to 1 and return this product.
3709 * Otherwise, set *<b>ok</b> to 0.
3712 config_parse_units(const char *val
, struct unit_table_t
*u
, int *ok
)
3719 v
= tor_parse_uint64(val
, 10, 0, UINT64_MAX
, ok
, &cp
);
3726 while (TOR_ISSPACE(*cp
))
3728 for ( ;u
->unit
;++u
) {
3729 if (!strcasecmp(u
->unit
, cp
)) {
3735 log_warn(LD_CONFIG
, "Unknown unit '%s'.", cp
);
3740 /** Parse a string in the format "number unit", where unit is a unit of
3741 * information (byte, KB, M, etc). On success, set *<b>ok</b> to true
3742 * and return the number of bytes specified. Otherwise, set
3743 * *<b>ok</b> to false and return 0. */
3745 config_parse_memunit(const char *s
, int *ok
)
3747 return config_parse_units(s
, memory_units
, ok
);
3750 /** Parse a string in the format "number unit", where unit is a unit of time.
3751 * On success, set *<b>ok</b> to true and return the number of seconds in
3752 * the provided interval. Otherwise, set *<b>ok</b> to 0 and return -1.
3755 config_parse_interval(const char *s
, int *ok
)
3758 r
= config_parse_units(s
, time_units
, ok
);
3762 log_warn(LD_CONFIG
, "Interval '%s' is too long", s
);
3770 * Initialize the libevent library.
3775 configure_libevent_logging();
3776 /* If the kernel complains that some method (say, epoll) doesn't
3777 * exist, we don't care about it, since libevent will cope.
3779 suppress_libevent_log_msg("Function not implemented");
3781 if (decode_libevent_version() < LE_11B
) {
3782 setenv("EVENT_NOKQUEUE","1",1);
3783 } else if (!getenv("EVENT_NOKQUEUE")) {
3784 const char *ver
= NULL
;
3785 #ifdef HAVE_EVENT_GET_VERSION
3786 ver
= event_get_version();
3788 /* If we're 1.1b or later, we'd better have get_version() */
3790 log(LOG_NOTICE
, LD_GENERAL
, "Enabling experimental OS X kqueue support "
3791 "with libevent %s. If this turns out to not work, "
3792 "set the environment variable EVENT_NOKQUEUE, and tell the Tor "
3793 "developers.", ver
);
3797 suppress_libevent_log_msg(NULL
);
3798 #if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
3799 /* Making this a NOTICE for now so we can link bugs to a libevent versions
3800 * or methods better. */
3801 log(LOG_NOTICE
, LD_GENERAL
,
3802 "Initialized libevent version %s using method %s. Good.",
3803 event_get_version(), event_get_method());
3804 check_libevent_version(event_get_method(), get_options()->ORPort
!= 0);
3806 log(LOG_NOTICE
, LD_GENERAL
,
3807 "Initialized old libevent (version 1.0b or earlier).");
3808 log(LOG_WARN
, LD_GENERAL
,
3809 "You have a *VERY* old version of libevent. It is likely to be buggy; "
3810 "please build Tor with a more recent version.");
3814 #if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
3815 /** Table mapping return value of event_get_version() to le_version_t. */
3816 static const struct {
3817 const char *name
; le_version_t version
;
3818 } le_version_table
[] = {
3819 /* earlier versions don't have get_version. */
3832 /** Return the le_version_t for the current version of libevent. If the
3833 * version is very new, return LE_OTHER. If the version is so old that it
3834 * doesn't support event_get_version(), return LE_OLD. */
3836 decode_libevent_version(void)
3838 const char *v
= event_get_version();
3840 for (i
=0; le_version_table
[i
].name
; ++i
) {
3841 if (!strcmp(le_version_table
[i
].name
, v
)) {
3842 return le_version_table
[i
].version
;
3849 * Compare the given libevent method and version to a list of versions
3850 * which are known not to work. Warn the user as appropriate.
3853 check_libevent_version(const char *m
, int server
)
3855 int buggy
= 0, iffy
= 0, slow
= 0;
3856 le_version_t version
;
3857 const char *v
= event_get_version();
3858 const char *badness
= NULL
;
3860 version
= decode_libevent_version();
3862 /* XXX Would it be worthwhile disabling the methods that we know
3863 * are buggy, rather than just warning about them and then proceeding
3864 * to use them? If so, we should probably not wrap this whole thing
3865 * in HAVE_EVENT_GET_VERSION and HAVE_EVENT_GET_METHOD. -RD */
3866 /* XXXX The problem is that it's not trivial to get libevent to change it's
3867 * method once it's initialized, and it's not trivial to tell what method it
3868 * will use without initializing it. I guess we could preemptively disable
3869 * buggy libevent modes based on the version _before_ initializing it,
3870 * though, but then there's no good way (afaict) to warn "I would have used
3871 * kqueue, but instead I'm using select." -NM */
3872 if (!strcmp(m
, "kqueue")) {
3873 if (version
< LE_11B
)
3875 } else if (!strcmp(m
, "epoll")) {
3876 if (version
< LE_11
)
3878 } else if (!strcmp(m
, "poll")) {
3879 if (version
< LE_10E
)
3881 else if (version
< LE_11
)
3883 } else if (!strcmp(m
, "select")) {
3884 if (version
< LE_11
)
3886 } else if (!strcmp(m
, "win32")) {
3887 if (version
< LE_11B
)
3892 log(LOG_WARN
, LD_GENERAL
,
3893 "There are known bugs in using %s with libevent %s. "
3894 "Please use the latest version of libevent.", m
, v
);
3897 log(LOG_WARN
, LD_GENERAL
,
3898 "There are minor bugs in using %s with libevent %s. "
3899 "You may want to use the latest version of libevent.", m
, v
);
3901 } else if (slow
&& server
) {
3902 log(LOG_WARN
, LD_GENERAL
,
3903 "libevent %s can be very slow with %s. "
3904 "When running a server, please use the latest version of libevent.",
3909 control_event_general_status(LOG_WARN
,
3910 "BAD_LIBEVENT VERSION=%s METHOD=%s BADNESS=%s RECOVERED=NO",
3917 decode_libevent_version(void)
3923 /** Return the persistent state struct for this Tor. */
3927 tor_assert(global_state
);
3928 return global_state
;
3931 /** Return the filename used to write and read the persistent state. */
3933 get_or_state_fname(void)
3936 or_options_t
*options
= get_options();
3937 size_t len
= strlen(options
->DataDirectory
) + 16;
3938 fname
= tor_malloc(len
);
3939 tor_snprintf(fname
, len
, "%s/state", options
->DataDirectory
);
3943 /** Return 0 if every setting in <b>state</b> is reasonable, and a
3944 * permissible transition from <b>old_state</b>. Else warn and return -1.
3945 * Should have no side effects, except for normalizing the contents of
3948 /* XXX from_setconf is here because of bug 238 */
3950 or_state_validate(or_state_t
*old_state
, or_state_t
*state
,
3951 int from_setconf
, char **msg
)
3953 /* We don't use these; only options do. Still, we need to match that
3955 (void) from_setconf
;
3957 if (entry_guards_parse_state(state
, 0, msg
)<0) {
3960 if (state
->TorVersion
) {
3962 if (tor_version_parse(state
->TorVersion
, &v
)) {
3963 log_warn(LD_GENERAL
, "Can't parse Tor version '%s' from your state "
3964 "file. Proceeding anyway.", state
->TorVersion
);
3965 } else { /* take action based on v */
3966 if (tor_version_as_new_as(state
->TorVersion
, "0.1.1.10-alpha") &&
3967 !tor_version_as_new_as(state
->TorVersion
, "0.1.1.16-rc-cvs")) {
3968 log_notice(LD_CONFIG
, "Detected state file from buggy version '%s'. "
3969 "Enabling workaround to choose working entry guards.",
3971 config_free_lines(state
->EntryGuards
);
3972 state
->EntryGuards
= NULL
;
3979 /** Replace the current persistent state with <b>new_state</b> */
3981 or_state_set(or_state_t
*new_state
)
3984 tor_assert(new_state
);
3986 config_free(&state_format
, global_state
);
3987 global_state
= new_state
;
3988 if (entry_guards_parse_state(global_state
, 1, &err
)<0) {
3989 log_warn(LD_GENERAL
,"%s",err
);
3992 if (rep_hist_load_state(global_state
, &err
)<0) {
3993 log_warn(LD_GENERAL
,"Unparseable bandwidth history state: %s",err
);
3998 /** Reload the persistent state from disk, generating a new state as needed.
3999 * Return 0 on success, less than 0 on failure.
4004 or_state_t
*new_state
= NULL
;
4005 char *contents
= NULL
, *fname
;
4006 char *errmsg
= NULL
;
4007 int r
= -1, badstate
= 0;
4009 fname
= get_or_state_fname();
4010 switch (file_status(fname
)) {
4012 if (!(contents
= read_file_to_str(fname
, 0, NULL
))) {
4013 log_warn(LD_FS
, "Unable to read state file \"%s\"", fname
);
4022 log_warn(LD_GENERAL
,"State file \"%s\" is not a file? Failing.", fname
);
4025 new_state
= tor_malloc_zero(sizeof(or_state_t
));
4026 new_state
->_magic
= OR_STATE_MAGIC
;
4027 config_init(&state_format
, new_state
);
4029 config_line_t
*lines
=NULL
;
4031 if (config_get_lines(contents
, &lines
)<0)
4033 assign_retval
= config_assign(&state_format
, new_state
,
4034 lines
, 0, 0, &errmsg
);
4035 config_free_lines(lines
);
4036 if (assign_retval
<0)
4039 log_warn(LD_GENERAL
, "%s", errmsg
);
4044 if (!badstate
&& or_state_validate(NULL
, new_state
, 1, &errmsg
) < 0)
4048 log_warn(LD_GENERAL
, "%s", errmsg
);
4052 if (badstate
&& !contents
) {
4053 log_warn(LD_BUG
, "Uh oh. We couldn't even validate our own default state."
4054 " This is a bug in Tor.");
4056 } else if (badstate
&& contents
) {
4058 file_status_t status
;
4059 size_t len
= strlen(fname
)+16;
4060 char *fname2
= tor_malloc(len
);
4061 for (i
= 0; i
< 100; ++i
) {
4062 tor_snprintf(fname2
, len
, "%s.%d", fname
, i
);
4063 status
= file_status(fname2
);
4064 if (status
== FN_NOENT
)
4068 log_warn(LD_BUG
, "Unable to parse state in \"%s\"; too many saved bad "
4069 "state files to move aside. Discarding the old state file.",
4073 log_warn(LD_BUG
, "Unable to parse state in \"%s\". Moving it aside "
4074 "to \"%s\". This could be a bug in Tor; please tell "
4075 "the developers.", fname
, fname2
);
4076 rename(fname
, fname2
);
4080 config_free(&state_format
, new_state
);
4082 new_state
= tor_malloc_zero(sizeof(or_state_t
));
4083 new_state
->_magic
= OR_STATE_MAGIC
;
4084 config_init(&state_format
, new_state
);
4085 } else if (contents
) {
4086 log_info(LD_GENERAL
, "Loaded state from \"%s\"", fname
);
4088 log_info(LD_GENERAL
, "Initialized state");
4090 or_state_set(new_state
);
4093 global_state
->next_write
= 0;
4094 or_state_save(time(NULL
));
4102 config_free(&state_format
, new_state
);
4107 /** Write the persistent state to disk. Return 0 for success, <0 on failure. */
4109 or_state_save(time_t now
)
4111 char *state
, *contents
;
4112 char tbuf
[ISO_TIME_LEN
+1];
4116 tor_assert(global_state
);
4118 if (global_state
->next_write
> now
)
4121 /* Call everything else that might dirty the state even more, in order
4122 * to avoid redundant writes. */
4123 entry_guards_update_state(global_state
);
4124 rep_hist_update_state(global_state
);
4125 if (accounting_is_enabled(get_options()))
4126 accounting_run_housekeeping(now
);
4128 global_state
->LastWritten
= time(NULL
);
4129 tor_free(global_state
->TorVersion
);
4130 global_state
->TorVersion
= tor_strdup("Tor " VERSION
);
4131 state
= config_dump(&state_format
, global_state
, 1, 0);
4132 len
= strlen(state
)+256;
4133 contents
= tor_malloc(len
);
4134 format_local_iso_time(tbuf
, time(NULL
));
4135 tor_snprintf(contents
, len
,
4136 "# Tor state file last generated on %s local time\n"
4137 "# Other times below are in GMT\n"
4138 "# You *do not* need to edit this file.\n\n%s",
4141 fname
= get_or_state_fname();
4142 if (write_str_to_file(fname
, contents
, 0)<0) {
4143 log_warn(LD_FS
, "Unable to write state to file \"%s\"", fname
);
4148 log_info(LD_GENERAL
, "Saved state to \"%s\"", fname
);
4152 global_state
->next_write
= TIME_MAX
;
4156 /** Helper to implement GETINFO functions about configuration variables (not
4157 * their values). Given a "config/names" question, set *<b>answer</b> to a
4158 * new string describing the supported configuration variables and their
4161 getinfo_helper_config(control_connection_t
*conn
,
4162 const char *question
, char **answer
)
4165 if (!strcmp(question
, "config/names")) {
4166 smartlist_t
*sl
= smartlist_create();
4168 for (i
= 0; _option_vars
[i
].name
; ++i
) {
4169 config_var_t
*var
= &_option_vars
[i
];
4170 const char *type
, *desc
;
4173 desc
= config_find_description(&options_format
, var
->name
);
4174 switch (var
->type
) {
4175 case CONFIG_TYPE_STRING
: type
= "String"; break;
4176 case CONFIG_TYPE_UINT
: type
= "Integer"; break;
4177 case CONFIG_TYPE_INTERVAL
: type
= "TimeInterval"; break;
4178 case CONFIG_TYPE_MEMUNIT
: type
= "DataSize"; break;
4179 case CONFIG_TYPE_DOUBLE
: type
= "Float"; break;
4180 case CONFIG_TYPE_BOOL
: type
= "Boolean"; break;
4181 case CONFIG_TYPE_ISOTIME
: type
= "Time"; break;
4182 case CONFIG_TYPE_CSV
: type
= "CommaList"; break;
4183 case CONFIG_TYPE_LINELIST
: type
= "LineList"; break;
4184 case CONFIG_TYPE_LINELIST_S
: type
= "Dependant"; break;
4185 case CONFIG_TYPE_LINELIST_V
: type
= "Virtual"; break;
4187 case CONFIG_TYPE_OBSOLETE
:
4192 len
= strlen(var
->name
)+strlen(type
)+16;
4194 len
+= strlen(desc
);
4195 line
= tor_malloc(len
);
4197 tor_snprintf(line
, len
, "%s %s %s\n",var
->name
,type
,desc
);
4199 tor_snprintf(line
, len
, "%s %s\n",var
->name
,type
);
4200 smartlist_add(sl
, line
);
4202 *answer
= smartlist_join_strings(sl
, "", 0, NULL
);
4203 SMARTLIST_FOREACH(sl
, char *, c
, tor_free(c
));
4209 #include "../common/ht.h"
4210 #include "../common/test.h"
4212 extern const char aes_c_id
[];
4213 extern const char compat_c_id
[];
4214 extern const char container_c_id
[];
4215 extern const char crypto_c_id
[];
4216 extern const char log_c_id
[];
4217 extern const char torgzip_c_id
[];
4218 extern const char tortls_c_id
[];
4219 extern const char util_c_id
[];
4221 extern const char buffers_c_id
[];
4222 extern const char circuitbuild_c_id
[];
4223 extern const char circuitlist_c_id
[];
4224 extern const char circuituse_c_id
[];
4225 extern const char command_c_id
[];
4226 // extern const char config_c_id[];
4227 extern const char connection_c_id
[];
4228 extern const char connection_edge_c_id
[];
4229 extern const char connection_or_c_id
[];
4230 extern const char control_c_id
[];
4231 extern const char cpuworker_c_id
[];
4232 extern const char directory_c_id
[];
4233 extern const char dirserv_c_id
[];
4234 extern const char dns_c_id
[];
4235 extern const char hibernate_c_id
[];
4236 extern const char main_c_id
[];
4237 extern const char onion_c_id
[];
4238 extern const char policies_c_id
[];
4239 extern const char relay_c_id
[];
4240 extern const char rendclient_c_id
[];
4241 extern const char rendcommon_c_id
[];
4242 extern const char rendmid_c_id
[];
4243 extern const char rendservice_c_id
[];
4244 extern const char rephist_c_id
[];
4245 extern const char router_c_id
[];
4246 extern const char routerlist_c_id
[];
4247 extern const char routerparse_c_id
[];
4249 /** Dump the version of every file to the log. */
4251 print_svn_version(void)
4255 puts(CONTAINER_H_ID
);
4266 puts(container_c_id
);
4275 puts(circuitbuild_c_id
);
4276 puts(circuitlist_c_id
);
4277 puts(circuituse_c_id
);
4280 puts(connection_c_id
);
4281 puts(connection_edge_c_id
);
4282 puts(connection_or_c_id
);
4284 puts(cpuworker_c_id
);
4285 puts(directory_c_id
);
4288 puts(hibernate_c_id
);
4291 puts(policies_c_id
);
4293 puts(rendclient_c_id
);
4294 puts(rendcommon_c_id
);
4296 puts(rendservice_c_id
);
4299 puts(routerlist_c_id
);
4300 puts(routerparse_c_id
);