Test and document last patch.
[tor.git] / src / or / config.c
blob01d5b8646edf20de3292ea4e548d59053fe79d62
1 /* Copyright (c) 2001 Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. */
4 /* See LICENSE for licensing information */
5 /* $Id$ */
6 const char config_c_id[] = \
7 "$Id$";
9 /**
10 * \file config.c
11 * \brief Code to parse and interpret configuration files.
12 **/
14 #include "or.h"
15 #ifdef MS_WINDOWS
16 #include <shlobj.h>
17 #endif
18 #include "../common/aes.h"
20 /** Enumeration of types which option values can take */
21 typedef enum config_type_t {
22 CONFIG_TYPE_STRING = 0, /**< An arbitrary string. */
23 CONFIG_TYPE_UINT, /**< A non-negative integer less than MAX_INT */
24 CONFIG_TYPE_INTERVAL, /**< A number of seconds, with optional units*/
25 CONFIG_TYPE_MEMUNIT, /**< A number of bytes, with optional units*/
26 CONFIG_TYPE_DOUBLE, /**< A floating-point value */
27 CONFIG_TYPE_BOOL, /**< A boolean value, expressed as 0 or 1. */
28 CONFIG_TYPE_ISOTIME, /**< An ISO-formated time relative to GMT. */
29 CONFIG_TYPE_CSV, /**< A list of strings, separated by commas and
30 * optional whitespace. */
31 CONFIG_TYPE_LINELIST, /**< Uninterpreted config lines */
32 CONFIG_TYPE_LINELIST_S, /**< Uninterpreted, context-sensitive config lines,
33 * mixed with other keywords. */
34 CONFIG_TYPE_LINELIST_V, /**< Catch-all "virtual" option to summarize
35 * context-sensitive config lines when fetching.
37 CONFIG_TYPE_OBSOLETE, /**< Obsolete (ignored) option. */
38 } config_type_t;
40 /** An abbreviation for a configuration option allowed on the command line. */
41 typedef struct config_abbrev_t {
42 const char *abbreviated;
43 const char *full;
44 int commandline_only;
45 int warn;
46 } config_abbrev_t;
48 /* Handy macro for declaring "In the config file or on the command line,
49 * you can abbreviate <b>tok</b>s as <b>tok</b>". */
50 #define PLURAL(tok) { #tok, #tok "s", 0, 0 }
52 /* A list of command-line abbreviations. */
53 static config_abbrev_t _option_abbrevs[] = {
54 PLURAL(ExitNode),
55 PLURAL(EntryNode),
56 PLURAL(ExcludeNode),
57 PLURAL(FirewallPort),
58 PLURAL(LongLivedPort),
59 PLURAL(HiddenServiceNode),
60 PLURAL(HiddenServiceExcludeNode),
61 PLURAL(NumCpu),
62 PLURAL(RendNode),
63 PLURAL(RendExcludeNode),
64 PLURAL(StrictEntryNode),
65 PLURAL(StrictExitNode),
66 { "l", "Log", 1, 0},
67 { "AllowUnverifiedNodes", "AllowInvalidNodes", 0, 0},
68 { "BandwidthRateBytes", "BandwidthRate", 0, 0},
69 { "BandwidthBurstBytes", "BandwidthBurst", 0, 0},
70 { "DirFetchPostPeriod", "StatusFetchPeriod", 0, 0},
71 { "MaxConn", "ConnLimit", 0, 1},
72 { "ORBindAddress", "ORListenAddress", 0, 0},
73 { "DirBindAddress", "DirListenAddress", 0, 0},
74 { "SocksBindAddress", "SocksListenAddress", 0, 0},
75 { "UseHelperNodes", "UseEntryGuards", 0, 0},
76 { "NumHelperNodes", "NumEntryGuards", 0, 0},
77 { "UseEntryNodes", "UseEntryGuards", 0, 0},
78 { "NumEntryNodes", "NumEntryGuards", 0, 0},
79 { NULL, NULL, 0, 0},
81 /* A list of state-file abbreviations, for compatibility. */
82 static config_abbrev_t _state_abbrevs[] = {
83 { "AccountingBytesReadInterval", "AccountingBytesReadInInterval", 0, 0 },
84 { "HelperNode", "EntryGuard", 0, 0 },
85 { "HelperNodeDownSince", "EntryGuardDownSince", 0, 0 },
86 { "HelperNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 },
87 { "EntryNode", "EntryGuard", 0, 0 },
88 { "EntryNodeDownSince", "EntryGuardDownSince", 0, 0 },
89 { "EntryNodeUnlistedSince", "EntryGuardUnlistedSince", 0, 0 },
90 { NULL, NULL, 0, 0},
92 #undef PLURAL
94 /** A variable allowed in the configuration file or on the command line. */
95 typedef struct config_var_t {
96 const char *name; /**< The full keyword (case insensitive). */
97 config_type_t type; /**< How to interpret the type and turn it into a
98 * value. */
99 off_t var_offset; /**< Offset of the corresponding member of or_options_t. */
100 const char *initvalue; /**< String (or null) describing initial value. */
101 } config_var_t;
103 /** Return the offset of <b>member</b> within the type <b>tp</b>, in bytes */
104 #define STRUCT_OFFSET(tp, member) \
105 ((off_t) (((char*)&((tp*)0)->member)-(char*)0))
107 #define STRUCT_VAR_P(st, off) \
108 ((void*) ( ((char*)st) + off ) )
110 /** An entry for config_vars: "The option <b>name</b> has type
111 * CONFIG_TYPE_<b>conftype</b>, and corresponds to
112 * or_options_t.<b>member</b>"
114 #define VAR(name,conftype,member,initvalue) \
115 { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_options_t, member), \
116 initvalue }
117 /** An entry for config_vars: "The option <b>name</b> is obsolete." */
118 #define OBSOLETE(name) { name, CONFIG_TYPE_OBSOLETE, 0, NULL }
120 /** Array of configuration options. Until we disallow nonstandard
121 * abbreviations, order is significant, since the first matching option will
122 * be chosen first.
124 static config_var_t _option_vars[] = {
125 VAR("AccountingMax", MEMUNIT, AccountingMax, "0 bytes"),
126 VAR("AccountingMaxKB", UINT, _AccountingMaxKB, "0"),
127 VAR("AccountingStart", STRING, AccountingStart, NULL),
128 VAR("Address", STRING, Address, NULL),
129 VAR("__AllDirActionsPrivate",BOOL, AllDirActionsPrivate, "0"),
130 VAR("AllowInvalidNodes", CSV, AllowInvalidNodes,
131 "middle,rendezvous"),
132 VAR("AssumeReachable", BOOL, AssumeReachable, "0"),
133 VAR("AuthDirInvalid", LINELIST, AuthDirInvalid, NULL),
134 VAR("AuthDirReject", LINELIST, AuthDirReject, NULL),
135 VAR("AuthDirRejectUnlisted",BOOL, AuthDirRejectUnlisted,"0"),
136 VAR("AuthoritativeDirectory",BOOL, AuthoritativeDir, "0"),
137 VAR("BandwidthBurst", MEMUNIT, BandwidthBurst, "6 MB"),
138 VAR("BandwidthRate", MEMUNIT, BandwidthRate, "3 MB"),
139 VAR("CircuitBuildTimeout", INTERVAL, CircuitBuildTimeout, "1 minute"),
140 VAR("CircuitIdleTimeout", INTERVAL, CircuitIdleTimeout, "1 hour"),
141 VAR("ClientOnly", BOOL, ClientOnly, "0"),
142 VAR("ConnLimit", UINT, ConnLimit, "1000"),
143 VAR("ContactInfo", STRING, ContactInfo, NULL),
144 VAR("ControlListenAddress",LINELIST, ControlListenAddress, NULL),
145 VAR("ControlPort", UINT, ControlPort, "0"),
146 VAR("CookieAuthentication",BOOL, CookieAuthentication, "0"),
147 VAR("DataDirectory", STRING, DataDirectory, NULL),
148 VAR("DebugLogFile", STRING, DebugLogFile, NULL),
149 VAR("DirAllowPrivateAddresses",BOOL, DirAllowPrivateAddresses, NULL),
150 VAR("DirListenAddress", LINELIST, DirListenAddress, NULL),
151 /* if DirFetchPeriod is 0, see get_dir_fetch_period() in main.c */
152 VAR("DirFetchPeriod", INTERVAL, DirFetchPeriod, "0 seconds"),
153 VAR("DirPolicy", LINELIST, DirPolicy, NULL),
154 VAR("DirPort", UINT, DirPort, "0"),
155 OBSOLETE("DirPostPeriod"),
156 VAR("DirServer", LINELIST, DirServers, NULL),
157 VAR("EntryNodes", STRING, EntryNodes, NULL),
158 VAR("ExcludeNodes", STRING, ExcludeNodes, NULL),
159 VAR("ExitNodes", STRING, ExitNodes, NULL),
160 VAR("ExitPolicy", LINELIST, ExitPolicy, NULL),
161 VAR("ExitPolicyRejectPrivate", BOOL, ExitPolicyRejectPrivate, "1"),
162 VAR("FascistFirewall", BOOL, FascistFirewall, "0"),
163 VAR("FirewallPorts", CSV, FirewallPorts, ""),
164 VAR("FastFirstHopPK", BOOL, FastFirstHopPK, "1"),
165 VAR("FetchServerDescriptors",BOOL, FetchServerDescriptors,"1"),
166 VAR("FetchHidServDescriptors",BOOL, FetchHidServDescriptors, "1"),
167 VAR("FetchUselessDescriptors",BOOL, FetchUselessDescriptors, "0"),
168 VAR("Group", STRING, Group, NULL),
169 VAR("HardwareAccel", BOOL, HardwareAccel, "0"),
170 VAR("HashedControlPassword",STRING, HashedControlPassword, NULL),
171 VAR("HiddenServiceDir", LINELIST_S, RendConfigLines, NULL),
172 VAR("HiddenServiceExcludeNodes", LINELIST_S, RendConfigLines, NULL),
173 VAR("HiddenServiceNodes", LINELIST_S, RendConfigLines, NULL),
174 VAR("HiddenServiceOptions",LINELIST_V, RendConfigLines, NULL),
175 VAR("HiddenServicePort", LINELIST_S, RendConfigLines, NULL),
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 VAR("LogFile", LINELIST_S, OldLogOptions, NULL),
185 VAR("LogLevel", LINELIST_S, OldLogOptions, NULL),
186 VAR("LongLivedPorts", CSV, LongLivedPorts,
187 "21,22,706,1863,5050,5190,5222,5223,6667,8300,8888"),
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("Nickname", STRING, Nickname, NULL),
197 VAR("NoPublish", BOOL, NoPublish, "0"),
198 VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
199 VAR("NumCpus", UINT, NumCpus, "1"),
200 VAR("NumEntryGuards", UINT, NumEntryGuards, "3"),
201 VAR("ORListenAddress", LINELIST, ORListenAddress, NULL),
202 VAR("ORPort", UINT, ORPort, "0"),
203 VAR("OutboundBindAddress", STRING, OutboundBindAddress, NULL),
204 VAR("PathlenCoinWeight", DOUBLE, PathlenCoinWeight, "0.3"),
205 VAR("PidFile", STRING, PidFile, NULL),
206 VAR("ProtocolWarnings", BOOL, ProtocolWarnings, "0"),
207 VAR("PublishServerDescriptor",BOOL, PublishServerDescriptor,"1"),
208 VAR("PublishHidServDescriptors",BOOL,PublishHidServDescriptors, "1"),
209 VAR("ReachableAddresses", LINELIST, ReachableAddresses, NULL),
210 VAR("ReachableDirAddresses",LINELIST,ReachableDirAddresses,NULL),
211 VAR("ReachableORAddresses",LINELIST, ReachableORAddresses, NULL),
212 VAR("RecommendedVersions", LINELIST, RecommendedVersions, NULL),
213 VAR("RecommendedClientVersions", LINELIST, RecommendedClientVersions, NULL),
214 VAR("RecommendedServerVersions", LINELIST, RecommendedServerVersions, NULL),
215 VAR("RedirectExit", LINELIST, RedirectExit, NULL),
216 VAR("RendExcludeNodes", STRING, RendExcludeNodes, NULL),
217 VAR("RendNodes", STRING, RendNodes, NULL),
218 VAR("RendPostPeriod", INTERVAL, RendPostPeriod, "1 hour"),
219 VAR("RephistTrackTime", INTERVAL, RephistTrackTime, "24 hours"),
220 OBSOLETE("RouterFile"),
221 VAR("RunAsDaemon", BOOL, RunAsDaemon, "0"),
222 VAR("RunTesting", BOOL, RunTesting, "0"),
223 VAR("SafeLogging", BOOL, SafeLogging, "1"),
224 VAR("SafeSocks", BOOL, SafeSocks, "0"),
225 VAR("ShutdownWaitLength", INTERVAL, ShutdownWaitLength, "30 seconds"),
226 VAR("SocksListenAddress", LINELIST, SocksListenAddress, NULL),
227 VAR("SocksPolicy", LINELIST, SocksPolicy, NULL),
228 VAR("SocksPort", UINT, SocksPort, "9050"),
229 VAR("SocksTimeout", INTERVAL, SocksTimeout, "2 minutes"),
230 /* if StatusFetchPeriod is 0, see get_status_fetch_period() in main.c */
231 VAR("StatusFetchPeriod", INTERVAL, StatusFetchPeriod, "0 seconds"),
232 VAR("StrictEntryNodes", BOOL, StrictEntryNodes, "0"),
233 VAR("StrictExitNodes", BOOL, StrictExitNodes, "0"),
234 VAR("SysLog", LINELIST_S, OldLogOptions, NULL),
235 VAR("TestSocks", BOOL, TestSocks, "0"),
236 VAR("TrackHostExits", CSV, TrackHostExits, NULL),
237 VAR("TrackHostExitsExpire",INTERVAL, TrackHostExitsExpire, "30 minutes"),
238 OBSOLETE("TrafficShaping"),
239 VAR("UseEntryGuards", BOOL, UseEntryGuards, "1"),
240 VAR("User", STRING, User, NULL),
241 VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"),
242 VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"),
243 VAR("VirtualAddrNetwork", STRING, VirtualAddrNetwork, "127.192.0.0/10"),
244 VAR("__LeaveStreamsUnattached", BOOL,LeaveStreamsUnattached, "0"),
245 { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
247 #undef VAR
249 #define VAR(name,conftype,member,initvalue) \
250 { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_state_t, member), \
251 initvalue }
252 static config_var_t _state_vars[] = {
253 VAR("AccountingBytesReadInInterval", MEMUNIT,
254 AccountingBytesReadInInterval, NULL),
255 VAR("AccountingBytesWrittenInInterval", MEMUNIT,
256 AccountingBytesWrittenInInterval, NULL),
257 VAR("AccountingExpectedUsage", MEMUNIT, AccountingExpectedUsage, NULL),
258 VAR("AccountingIntervalStart", ISOTIME, AccountingIntervalStart, NULL),
259 VAR("AccountingSecondsActive", INTERVAL, AccountingSecondsActive, NULL),
260 VAR("EntryGuard", LINELIST_S, EntryGuards, NULL),
261 VAR("EntryGuardDownSince", LINELIST_S, EntryGuards, NULL),
262 VAR("EntryGuardUnlistedSince", LINELIST_S, EntryGuards, NULL),
263 VAR("EntryGuards", LINELIST_V, EntryGuards, NULL),
265 VAR("BWHistoryReadEnds", ISOTIME, BWHistoryReadEnds, NULL),
266 VAR("BWHistoryReadInterval", UINT, BWHistoryReadInterval, NULL),
267 VAR("BWHistoryReadValues", CSV, BWHistoryReadValues, NULL),
268 VAR("BWHistoryWriteEnds", ISOTIME, BWHistoryWriteEnds, NULL),
269 VAR("BWHistoryWriteInterval", UINT, BWHistoryWriteInterval, NULL),
270 VAR("BWHistoryWriteValues", CSV, BWHistoryWriteValues, NULL),
272 VAR("TorVersion", STRING, TorVersion, NULL),
274 VAR("LastWritten", ISOTIME, LastWritten, NULL),
276 { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
279 #undef VAR
280 #undef OBSOLETE
282 /** Represents an English description of a configuration variable; used when
283 * generating configuration file comments. */
284 typedef struct config_var_description_t {
285 const char *name;
286 const char *description;
287 } config_var_description_t;
289 static config_var_description_t options_description[] = {
290 { "Address", "The advertised (external) address we should use." },
291 // { "AccountingStart", ""},
292 { NULL, NULL },
295 static config_var_description_t state_description[] = {
296 { "AccountingBytesReadInInterval",
297 "How many bytes have we read in this accounting period?" },
298 { "AccountingBytesWrittenInInterval",
299 "How many bytes have we written in this accounting period?" },
300 { "AccountingExpectedUsage",
301 "How many bytes did we expect to use per minute? (0 for no estimate.)" },
302 { "AccountingIntervalStart", "When did this accounting period begin?" },
303 { "AccountingSecondsActive", "How long have we been awake in this period?" },
305 { "BWHistoryReadEnds", "When does the last-recorded read-interval end?" },
306 { "BWHistoryReadInterval", "How long is each read-interval (in seconds)?" },
307 { "BWHistoryReadValues", "Number of bytes read in each interval." },
308 { "BWHistoryWriteEnds", "When does the last-recorded write-interval end?" },
309 { "BWHistoryWriteInterval", "How long is each write-interval (in seconds)?"},
310 { "BWHistoryWriteValues", "Number of bytes written in each interval." },
312 { "EntryGuard", "One of the nodes we have chosen as a fixed entry" },
313 { "EntryGuardDownSince",
314 "The last entry guard has been down since this time." },
315 { "EntryGuardUnlistedSince",
316 "The last entry guard has been unlisted since this time." },
317 { "LastWritten", "When was this state file last regenerated?" },
319 { "TorVersion", "Which version of Tor generated this state file?" },
320 { NULL, NULL },
323 typedef int (*validate_fn_t)(void*,void*,int,char**);
325 /** Information on the keys, value types, key-to-struct-member mappings,
326 * variable descriptions, validation functions, and abbreviations for a
327 * configuration or storage format. */
328 typedef struct {
329 size_t size;
330 uint32_t magic;
331 off_t magic_offset;
332 config_abbrev_t *abbrevs;
333 config_var_t *vars;
334 validate_fn_t validate_fn;
335 config_var_description_t *descriptions;
336 /** If present, extra is a LINELIST variable for unrecognized
337 * lines. Otherwise, unrecognized lines are an error. */
338 config_var_t *extra;
339 } config_format_t;
341 #define CHECK(fmt, cfg) do { \
342 tor_assert(fmt && cfg); \
343 tor_assert((fmt)->magic == \
344 *(uint32_t*)STRUCT_VAR_P(cfg,fmt->magic_offset)); \
345 } while (0)
347 static void config_line_append(config_line_t **lst,
348 const char *key, const char *val);
349 static void option_clear(config_format_t *fmt, or_options_t *options,
350 config_var_t *var);
351 static void option_reset(config_format_t *fmt, or_options_t *options,
352 config_var_t *var, int use_defaults);
353 static void config_free(config_format_t *fmt, void *options);
354 static int option_is_same(config_format_t *fmt,
355 or_options_t *o1, or_options_t *o2,
356 const char *name);
357 static or_options_t *options_dup(config_format_t *fmt, or_options_t *old);
358 static int options_validate(or_options_t *old_options, or_options_t *options,
359 int from_setconf, char **msg);
360 static int options_act_reversible(or_options_t *old_options, char **msg);
361 static int options_act(or_options_t *old_options);
362 static int options_transition_allowed(or_options_t *old, or_options_t *new,
363 char **msg);
364 static int options_transition_affects_workers(or_options_t *old_options,
365 or_options_t *new_options);
366 static int options_transition_affects_descriptor(or_options_t *old_options,
367 or_options_t *new_options);
368 static int check_nickname_list(const char *lst, const char *name, char **msg);
369 static void config_register_addressmaps(or_options_t *options);
371 static int parse_dir_server_line(const char *line, int validate_only);
372 static int parse_redirect_line(smartlist_t *result,
373 config_line_t *line, char **msg);
374 static int parse_log_severity_range(const char *range, int *min_out,
375 int *max_out);
376 static int convert_log_option(or_options_t *options,
377 config_line_t *level_opt,
378 config_line_t *file_opt, int isDaemon);
379 static int add_single_log_option(or_options_t *options, int minSeverity,
380 int maxSeverity,
381 const char *type, const char *fname);
382 static int normalize_log_options(or_options_t *options);
383 static int validate_data_directory(or_options_t *options);
384 static int write_configuration_file(const char *fname, or_options_t *options);
385 static config_line_t *get_assigned_option(config_format_t *fmt,
386 or_options_t *options, const char *key);
387 static void config_init(config_format_t *fmt, void *options);
388 static int or_state_validate(or_state_t *old_options, or_state_t *options,
389 int from_setconf, char **msg);
391 static uint64_t config_parse_memunit(const char *s, int *ok);
392 static int config_parse_interval(const char *s, int *ok);
393 static void print_cvs_version(void);
394 static void init_libevent(void);
395 static int opt_streq(const char *s1, const char *s2);
396 #if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
397 static void check_libevent_version(const char *m, const char *v, int server);
398 #endif
400 /*static*/ or_options_t *options_new(void);
402 #define OR_OPTIONS_MAGIC 9090909
404 static config_format_t options_format = {
405 sizeof(or_options_t),
406 OR_OPTIONS_MAGIC,
407 STRUCT_OFFSET(or_options_t, _magic),
408 _option_abbrevs,
409 _option_vars,
410 (validate_fn_t)options_validate,
411 options_description,
412 NULL
415 #define OR_STATE_MAGIC 0x57A73f57
417 static config_var_t state_extra_var = {
418 "__extra", CONFIG_TYPE_LINELIST, STRUCT_OFFSET(or_state_t, ExtraLines), NULL
421 static config_format_t state_format = {
422 sizeof(or_state_t),
423 OR_STATE_MAGIC,
424 STRUCT_OFFSET(or_state_t, _magic),
425 _state_abbrevs,
426 _state_vars,
427 (validate_fn_t)or_state_validate,
428 state_description,
429 &state_extra_var,
433 * Functions to read and write the global options pointer.
436 /** Command-line and config-file options. */
437 static or_options_t *global_options = NULL;
438 /** Name of most recently read torrc file. */
439 static char *torrc_fname = NULL;
440 /** Persistent serialized state. */
441 static or_state_t *global_state = NULL;
443 /** Allocate an empty configuration object of a given format type. */
444 static void *
445 config_alloc(config_format_t *fmt)
447 void *opts = opts = tor_malloc_zero(fmt->size);
448 *(uint32_t*)STRUCT_VAR_P(opts, fmt->magic_offset) = fmt->magic;
449 CHECK(fmt, opts);
450 return opts;
453 /** Return the currently configured options. */
454 or_options_t *
455 get_options(void)
457 tor_assert(global_options);
458 return global_options;
461 /** Change the current global options to contain <b>new_val</b> instead of
462 * their current value; take action based on the new value; free the old value
463 * as necessary.
466 set_options(or_options_t *new_val, char **msg)
468 or_options_t *old_options = global_options;
469 global_options = new_val;
470 /* Note that we pass the *old* options below, for comparison. It
471 * pulls the new options directly out of global_options. */
472 if (options_act_reversible(old_options, msg)<0) {
473 tor_assert(*msg);
474 global_options = old_options;
475 return -1;
477 if (options_act(old_options) < 0) { /* acting on the options failed. die. */
478 log_err(LD_BUG,
479 "Acting on config options left us in a broken state. Dying.");
480 exit(1);
482 if (old_options)
483 config_free(&options_format, old_options);
485 return 0;
488 /** Release all memory and resources held by global configuration structures.
490 void
491 config_free_all(void)
493 if (global_options) {
494 config_free(&options_format, global_options);
495 global_options = NULL;
497 if (global_state) {
498 config_free(&state_format, global_state);
499 global_state = NULL;
501 tor_free(torrc_fname);
504 /** If options->SafeLogging is on, return a not very useful string,
505 * else return address.
507 const char *
508 safe_str(const char *address)
510 if (get_options()->SafeLogging)
511 return "[scrubbed]";
512 else
513 return address;
516 /** Equivalent to escaped(safe_str(address)) */
517 const char *
518 escaped_safe_str(const char *address)
520 if (get_options()->SafeLogging)
521 return "[scrubbed]";
522 else
523 return escaped(address);
526 /** Add the default directory servers directly into the trusted dir list. */
527 static void
528 add_default_trusted_dirservers(void)
530 int i;
531 const char *dirservers[] = {
532 "moria1 v1 18.244.0.188:9031 "
533 "FFCB 46DB 1339 DA84 674C 70D7 CB58 6434 C437 0441",
534 "moria2 v1 18.244.0.114:80 "
535 "719B E45D E224 B607 C537 07D0 E214 3E2D 423E 74CF",
536 "tor26 v1 86.59.21.38:80 "
537 "847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D",
538 "lefkada 140.247.60.64:80 "
539 "38D4 F5FC F7B1 0232 28B8 95EA 56ED E7D5 CCDC AF32",
540 "dizum 194.109.206.212:80 "
541 "7EA6 EAD6 FD83 083C 538F 4403 8BBF A077 587D D755",
542 NULL
544 for (i=0; dirservers[i]; i++)
545 parse_dir_server_line(dirservers[i], 0);
548 /** Fetch the active option list, and take actions based on it. All of the
549 * things we do should survive being done repeatedly. If present,
550 * <b>old_options</b> contains the previous value of the options.
552 * Return 0 if all goes well, return -1 if things went badly.
554 static int
555 options_act_reversible(or_options_t *old_options, char **msg)
557 smartlist_t *new_listeners = smartlist_create();
558 smartlist_t *replaced_listeners = smartlist_create();
559 static int libevent_initialized = 0;
560 or_options_t *options = get_options();
561 int running_tor = options->command == CMD_RUN_TOR;
562 int set_conn_limit = 0;
563 int r = -1;
564 int logs_marked = 0;
566 if (running_tor && options->RunAsDaemon) {
567 /* No need to roll back, since you can't change the value. */
568 start_daemon();
571 /* Setuid/setgid as appropriate */
572 if (options->User || options->Group) {
573 if (switch_id(options->User, options->Group) != 0) {
574 /* No need to roll back, since you can't change the value. */
575 *msg = tor_strdup("Problem with User or Group value. "
576 "See logs for details.");
577 goto done;
581 /* Set up libevent. */
582 if (running_tor && !libevent_initialized) {
583 init_libevent();
584 libevent_initialized = 1;
587 /* Ensure data directory is private; create if possible. */
588 if (check_private_dir(options->DataDirectory, CPD_CREATE)<0) {
589 char buf[1024];
590 int tmp = tor_snprintf(buf, sizeof(buf),
591 "Couldn't access/create private data directory \"%s\"",
592 options->DataDirectory);
593 *msg = tor_strdup(tmp >= 0 ? buf : "internal error");
594 goto done;
595 /* No need to roll back, since you can't change the value. */
598 /* Bail out at this point if we're not going to be a client or server:
599 * we don't run Tor itself. */
600 if (options->command != CMD_RUN_TOR)
601 goto commit;
603 options->_ConnLimit =
604 set_max_file_descriptors((unsigned)options->ConnLimit, MAXCONNECTIONS);
605 if (options->_ConnLimit < 0) {
606 *msg = tor_strdup("Problem with ConnLimit value. See logs for details.");
607 goto rollback;
609 set_conn_limit = 1;
611 if (retry_all_listeners(0, replaced_listeners, new_listeners) < 0) {
612 *msg = tor_strdup("Failed to bind one of the listener ports.");
613 goto rollback;
616 mark_logs_temp(); /* Close current logs once new logs are open. */
617 logs_marked = 1;
618 if (options_init_logs(options, 0)<0) { /* Configure the log(s) */
619 *msg = tor_strdup("Failed to init Log options. See logs for details.");
620 goto rollback;
623 commit:
624 r = 0;
625 if (logs_marked) {
626 close_temp_logs();
627 add_callback_log(LOG_ERR, LOG_ERR, control_event_logmsg);
628 control_adjust_event_log_severity();
630 SMARTLIST_FOREACH(replaced_listeners, connection_t *, conn,
632 log_notice(LD_NET, "Closing old %s on %s:%d",
633 conn_type_to_string(conn->type), conn->address, conn->port);
634 connection_close_immediate(conn);
635 connection_mark_for_close(conn);
637 goto done;
639 rollback:
640 r = -1;
641 tor_assert(*msg);
643 if (logs_marked) {
644 rollback_log_changes();
645 control_adjust_event_log_severity();
648 if (set_conn_limit && old_options)
649 set_max_file_descriptors((unsigned)old_options->ConnLimit,MAXCONNECTIONS);
651 SMARTLIST_FOREACH(new_listeners, connection_t *, conn,
653 log_notice(LD_NET, "Closing %s on %s:%d",
654 conn_type_to_string(conn->type), conn->address, conn->port);
655 connection_close_immediate(conn);
656 connection_mark_for_close(conn);
659 done:
660 smartlist_free(new_listeners);
661 smartlist_free(replaced_listeners);
662 return r;
665 /** Fetch the active option list, and take actions based on it. All of the
666 * things we do should survive being done repeatedly. If present,
667 * <b>old_options</b> contains the previous value of the options.
669 * Return 0 if all goes well, return -1 if it's time to die.
671 * Note: We haven't moved all the "act on new configuration" logic
672 * here yet. Some is still in do_hup() and other places.
674 static int
675 options_act(or_options_t *old_options)
677 config_line_t *cl;
678 char *fn;
679 size_t len;
680 or_options_t *options = get_options();
681 int running_tor = options->command == CMD_RUN_TOR;
682 char *msg;
684 clear_trusted_dir_servers();
685 if (options->DirServers) {
686 for (cl = options->DirServers; cl; cl = cl->next) {
687 if (parse_dir_server_line(cl->value, 0)<0) {
688 log_err(LD_BUG,
689 "Bug: Previously validated DirServer line could not be added!");
690 return -1;
693 } else {
694 add_default_trusted_dirservers();
697 if (running_tor && rend_config_services(options, 0)<0) {
698 log_err(LD_BUG,
699 "Bug: Previously validated hidden services line could not be added!");
700 return -1;
703 if (running_tor) {
704 len = strlen(options->DataDirectory)+32;
705 fn = tor_malloc(len);
706 tor_snprintf(fn, len, "%s/cached-status", options->DataDirectory);
707 if (check_private_dir(fn, CPD_CREATE) != 0) {
708 log_err(LD_CONFIG,
709 "Couldn't access/create private data directory \"%s\"", fn);
710 tor_free(fn);
711 return -1;
713 tor_free(fn);
716 /* Bail out at this point if we're not going to be a client or server:
717 * we want to not fork, and to log stuff to stderr. */
718 if (options->command != CMD_RUN_TOR)
719 return 0;
721 /* Load state */
722 if (! global_state)
723 if (or_state_load())
724 return -1;
727 smartlist_t *sl = smartlist_create();
728 char *errmsg = NULL;
729 for (cl = options->RedirectExit; cl; cl = cl->next) {
730 if (parse_redirect_line(sl, cl, &errmsg)<0)
731 log_warn(LD_CONFIG, "%s", errmsg);
732 tor_free(errmsg);
733 return -1;
735 set_exit_redirects(sl);
738 /* Finish backgrounding the process */
739 if (running_tor && options->RunAsDaemon) {
740 /* We may be calling this for the n'th time (on SIGHUP), but it's safe. */
741 finish_daemon(options->DataDirectory);
744 /* Write our pid to the pid file. If we do not have write permissions we
745 * will log a warning */
746 if (running_tor && options->PidFile)
747 write_pidfile(options->PidFile);
749 /* Register addressmap directives */
750 config_register_addressmaps(options);
751 parse_virtual_addr_network(options->VirtualAddrNetwork, 0, &msg);
753 /* Update address policies. */
754 policies_parse_from_options(options);
756 init_cookie_authentication(options->CookieAuthentication);
758 /* reload keys as needed for rendezvous services. */
759 if (rend_service_load_keys()<0) {
760 log_err(LD_GENERAL,"Error loading rendezvous service keys");
761 return -1;
764 /* Set up accounting */
765 if (accounting_parse_options(options, 0)<0) {
766 log_err(LD_CONFIG,"Error in accounting options");
767 return -1;
769 if (accounting_is_enabled(options))
770 configure_accounting(time(NULL));
772 if (!running_tor)
773 return 0;
775 /* Check for transitions that need action. */
776 if (old_options) {
777 if (options->UseEntryGuards && !old_options->UseEntryGuards) {
778 log_info(LD_CIRC,
779 "Switching to entry guards; abandoning previous circuits");
780 circuit_mark_all_unused_circs();
781 circuit_expire_all_dirty_circs();
784 if (options_transition_affects_workers(old_options, options)) {
785 log_info(LD_GENERAL,
786 "Worker-related options changed. Rotating workers.");
787 if (server_mode(options) && !server_mode(old_options)) {
788 extern int has_completed_circuit;
789 if (init_keys() < 0) {
790 log_err(LD_GENERAL,"Error initializing keys; exiting");
791 return -1;
793 server_has_changed_ip();
794 if (has_completed_circuit)
795 inform_testing_reachability();
797 cpuworkers_rotate();
798 dnsworkers_rotate();
802 /* Check if we need to parse and add the EntryNodes config option. */
803 if (options->EntryNodes &&
804 (!old_options ||
805 !opt_streq(old_options->EntryNodes, options->EntryNodes)))
806 entry_nodes_should_be_added();
808 /* Since our options changed, we might need to regenerate and upload our
809 * server descriptor.
811 if (!old_options ||
812 options_transition_affects_descriptor(old_options, options))
813 mark_my_descriptor_dirty();
815 return 0;
819 * Functions to parse config options
822 /** If <b>option</b> is an official abbreviation for a longer option,
823 * return the longer option. Otherwise return <b>option</b>.
824 * If <b>command_line</b> is set, apply all abbreviations. Otherwise, only
825 * apply abbreviations that work for the config file and the command line.
826 * If <b>warn_obsolete</b> is set, warn about deprecated names. */
827 static const char *
828 expand_abbrev(config_format_t *fmt, const char *option, int command_line,
829 int warn_obsolete)
831 int i;
832 if (! fmt->abbrevs)
833 return option;
834 for (i=0; fmt->abbrevs[i].abbreviated; ++i) {
835 /* Abbreviations are casei. */
836 if (!strcasecmp(option,fmt->abbrevs[i].abbreviated) &&
837 (command_line || !fmt->abbrevs[i].commandline_only)) {
838 if (warn_obsolete && fmt->abbrevs[i].warn) {
839 log_warn(LD_CONFIG,
840 "The configuration option '%s' is deprecated; "
841 "use '%s' instead.",
842 fmt->abbrevs[i].abbreviated,
843 fmt->abbrevs[i].full);
845 return fmt->abbrevs[i].full;
848 return option;
851 /** Helper: Read a list of configuration options from the command line.
852 * If successful, put them in *<b>result</b> and return 0, and return
853 * -1 and leave *<b>result</b> alone. */
854 static int
855 config_get_commandlines(int argc, char **argv, config_line_t **result)
857 config_line_t *front = NULL;
858 config_line_t **new = &front;
859 char *s;
860 int i = 1;
862 while (i < argc) {
863 if (!strcmp(argv[i],"-f") ||
864 !strcmp(argv[i],"--hash-password")) {
865 i += 2; /* command-line option with argument. ignore them. */
866 continue;
867 } else if (!strcmp(argv[i],"--list-fingerprint") ||
868 !strcmp(argv[i],"--verify-config")) {
869 i += 1; /* command-line option. ignore it. */
870 continue;
871 } else if (!strcmp(argv[i],"--nt-service")) {
872 i += 1;
873 continue;
875 if (i == argc-1) {
876 log_warn(LD_CONFIG,"Command-line option '%s' with no value. Failing.",
877 argv[i]);
878 config_free_lines(front);
879 return -1;
882 *new = tor_malloc_zero(sizeof(config_line_t));
883 s = argv[i];
885 while (*s == '-')
886 s++;
888 (*new)->key = tor_strdup(expand_abbrev(&options_format, s, 1, 1));
889 (*new)->value = tor_strdup(argv[i+1]);
890 (*new)->next = NULL;
891 log(LOG_DEBUG, LD_CONFIG, "Commandline: parsed keyword '%s', value '%s'",
892 (*new)->key, (*new)->value);
894 new = &((*new)->next);
895 i += 2;
897 *result = front;
898 return 0;
901 /** Helper: allocate a new configuration option mapping 'key' to 'val',
902 * append it to *<b>lst</b>. */
903 static void
904 config_line_append(config_line_t **lst,
905 const char *key,
906 const char *val)
908 config_line_t *newline;
910 newline = tor_malloc(sizeof(config_line_t));
911 newline->key = tor_strdup(key);
912 newline->value = tor_strdup(val);
913 newline->next = NULL;
914 while (*lst)
915 lst = &((*lst)->next);
917 (*lst) = newline;
920 /** Helper: parse the config string and strdup into key/value
921 * strings. Set *result to the list, or NULL if parsing the string
922 * failed. Return 0 on success, -1 on failure. Warn and ignore any
923 * misformatted lines. */
925 config_get_lines(char *string, config_line_t **result)
927 config_line_t *list = NULL, **next;
928 char *k, *v;
930 next = &list;
931 do {
932 string = parse_line_from_str(string, &k, &v);
933 if (!string) {
934 config_free_lines(list);
935 return -1;
937 if (k && v) {
938 /* This list can get long, so we keep a pointer to the end of it
939 * rather than using config_line_append over and over and getting n^2
940 * performance. This is the only really long list. */
941 *next = tor_malloc(sizeof(config_line_t));
942 (*next)->key = tor_strdup(k);
943 (*next)->value = tor_strdup(v);
944 (*next)->next = NULL;
945 next = &((*next)->next);
947 } while (*string);
949 *result = list;
950 return 0;
954 * Free all the configuration lines on the linked list <b>front</b>.
956 void
957 config_free_lines(config_line_t *front)
959 config_line_t *tmp;
961 while (front) {
962 tmp = front;
963 front = tmp->next;
965 tor_free(tmp->key);
966 tor_free(tmp->value);
967 tor_free(tmp);
971 /** Return the description for a given configuration variable, or NULL if no
972 * description exists. */
973 static const char *
974 config_find_description(config_format_t *fmt, const char *name)
976 int i;
977 for (i=0; fmt->descriptions[i].name; ++i) {
978 if (!strcasecmp(name, fmt->descriptions[i].name))
979 return fmt->descriptions[i].description;
981 return NULL;
984 /** If <b>key</b> is a configuration option, return the corresponding
985 * config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation,
986 * warn, and return the corresponding config_var_t. Otherwise return NULL.
988 static config_var_t *
989 config_find_option(config_format_t *fmt, const char *key)
991 int i;
992 size_t keylen = strlen(key);
993 if (!keylen)
994 return NULL; /* if they say "--" on the commandline, it's not an option */
995 /* First, check for an exact (case-insensitive) match */
996 for (i=0; fmt->vars[i].name; ++i) {
997 if (!strcasecmp(key, fmt->vars[i].name)) {
998 return &fmt->vars[i];
1001 /* If none, check for an abbreviated match */
1002 for (i=0; fmt->vars[i].name; ++i) {
1003 if (!strncasecmp(key, fmt->vars[i].name, keylen)) {
1004 log_warn(LD_CONFIG, "The abbreviation '%s' is deprecated. "
1005 "Please use '%s' instead",
1006 key, fmt->vars[i].name);
1007 return &fmt->vars[i];
1010 /* Okay, unrecognized option */
1011 return NULL;
1015 * Functions to assign config options.
1018 /** <b>c</b>-\>key is known to be a real key. Update <b>options</b>
1019 * with <b>c</b>-\>value and return 0, or return -1 if bad value.
1021 * Called from config_assign_line() and option_reset().
1023 static int
1024 config_assign_value(config_format_t *fmt, or_options_t *options,
1025 config_line_t *c, char **msg)
1027 int i, r, ok;
1028 char buf[1024];
1029 config_var_t *var;
1030 void *lvalue;
1032 CHECK(fmt, options);
1034 var = config_find_option(fmt, c->key);
1035 tor_assert(var);
1037 lvalue = STRUCT_VAR_P(options, var->var_offset);
1039 switch (var->type) {
1041 case CONFIG_TYPE_UINT:
1042 i = tor_parse_long(c->value, 10, 0, INT_MAX, &ok, NULL);
1043 if (!ok) {
1044 r = tor_snprintf(buf, sizeof(buf),
1045 "Int keyword '%s %s' is malformed or out of bounds.",
1046 c->key, c->value);
1047 *msg = tor_strdup(r >= 0 ? buf : "internal error");
1048 return -1;
1050 *(int *)lvalue = i;
1051 break;
1053 case CONFIG_TYPE_INTERVAL: {
1054 i = config_parse_interval(c->value, &ok);
1055 if (!ok) {
1056 r = tor_snprintf(buf, sizeof(buf),
1057 "Interval '%s %s' is malformed or out of bounds.",
1058 c->key, c->value);
1059 *msg = tor_strdup(r >= 0 ? buf : "internal error");
1060 return -1;
1062 *(int *)lvalue = i;
1063 break;
1066 case CONFIG_TYPE_MEMUNIT: {
1067 uint64_t u64 = config_parse_memunit(c->value, &ok);
1068 if (!ok) {
1069 r = tor_snprintf(buf, sizeof(buf),
1070 "Value '%s %s' is malformed or out of bounds.",
1071 c->key, c->value);
1072 *msg = tor_strdup(r >= 0 ? buf : "internal error");
1073 return -1;
1075 *(uint64_t *)lvalue = u64;
1076 break;
1079 case CONFIG_TYPE_BOOL:
1080 i = tor_parse_long(c->value, 10, 0, 1, &ok, NULL);
1081 if (!ok) {
1082 r = tor_snprintf(buf, sizeof(buf),
1083 "Boolean '%s %s' expects 0 or 1.",
1084 c->key, c->value);
1085 *msg = tor_strdup(r >= 0 ? buf : "internal error");
1086 return -1;
1088 *(int *)lvalue = i;
1089 break;
1091 case CONFIG_TYPE_STRING:
1092 tor_free(*(char **)lvalue);
1093 *(char **)lvalue = tor_strdup(c->value);
1094 break;
1096 case CONFIG_TYPE_DOUBLE:
1097 *(double *)lvalue = atof(c->value);
1098 break;
1100 case CONFIG_TYPE_ISOTIME:
1101 if (parse_iso_time(c->value, (time_t *)lvalue)) {
1102 r = tor_snprintf(buf, sizeof(buf),
1103 "Invalid time '%s' for keyword '%s'", c->value, c->key);
1104 *msg = tor_strdup(r >= 0 ? buf : "internal error");
1105 return -1;
1107 break;
1109 case CONFIG_TYPE_CSV:
1110 if (*(smartlist_t**)lvalue) {
1111 SMARTLIST_FOREACH(*(smartlist_t**)lvalue, char *, cp, tor_free(cp));
1112 smartlist_clear(*(smartlist_t**)lvalue);
1113 } else {
1114 *(smartlist_t**)lvalue = smartlist_create();
1117 smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",",
1118 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
1119 break;
1121 case CONFIG_TYPE_LINELIST:
1122 case CONFIG_TYPE_LINELIST_S:
1123 config_line_append((config_line_t**)lvalue, c->key, c->value);
1124 break;
1126 case CONFIG_TYPE_OBSOLETE:
1127 log_warn(LD_CONFIG, "Skipping obsolete configuration option '%s'", c->key);
1128 break;
1129 case CONFIG_TYPE_LINELIST_V:
1130 r = tor_snprintf(buf, sizeof(buf),
1131 "You may not provide a value for virtual option '%s'", c->key);
1132 *msg = tor_strdup(r >= 0 ? buf : "internal error");
1133 return -1;
1134 default:
1135 tor_assert(0);
1136 break;
1138 return 0;
1141 /** If <b>c</b> is a syntactically valid configuration line, update
1142 * <b>options</b> with its value and return 0. Otherwise return -1 for bad
1143 * key, -2 for bad value.
1145 * If <b>clear_first</b> is set, clear the value first. Then if
1146 * <b>use_defaults</b> is set, set the value to the default.
1148 * Called from config_assign().
1150 static int
1151 config_assign_line(config_format_t *fmt, or_options_t *options,
1152 config_line_t *c, int use_defaults,
1153 int clear_first, char **msg)
1155 config_var_t *var;
1157 CHECK(fmt, options);
1159 var = config_find_option(fmt, c->key);
1160 if (!var) {
1161 if (fmt->extra) {
1162 void *lvalue = STRUCT_VAR_P(options, fmt->extra->var_offset);
1163 log_info(LD_CONFIG,
1164 "Found unrecognized option '%s'; saving it.", c->key);
1165 config_line_append((config_line_t**)lvalue, c->key, c->value);
1166 return 0;
1167 } else {
1168 char buf[1024];
1169 int tmp = tor_snprintf(buf, sizeof(buf),
1170 "Unknown option '%s'. Failing.", c->key);
1171 *msg = tor_strdup(tmp >= 0 ? buf : "internal error");
1172 return -1;
1175 /* Put keyword into canonical case. */
1176 if (strcmp(var->name, c->key)) {
1177 tor_free(c->key);
1178 c->key = tor_strdup(var->name);
1181 if (!strlen(c->value)) {
1182 /* reset or clear it, then return */
1183 if (!clear_first) {
1184 if (var->type == CONFIG_TYPE_LINELIST ||
1185 var->type == CONFIG_TYPE_LINELIST_S) {
1186 /* We got an empty linelist from the torrc or commandline.
1187 As a special case, call this an error. Warn and ignore. */
1188 log_warn(LD_CONFIG,
1189 "Linelist option '%s' has no value. Skipping.", c->key);
1190 } else { /* not already cleared */
1191 option_reset(fmt, options, var, use_defaults);
1194 return 0;
1197 if (config_assign_value(fmt, options, c, msg) < 0)
1198 return -2;
1199 return 0;
1202 /** Restore the option named <b>key</b> in options to its default value.
1203 * Called from config_assign(). */
1204 static void
1205 config_reset_line(config_format_t *fmt, or_options_t *options,
1206 const char *key, int use_defaults)
1208 config_var_t *var;
1210 CHECK(fmt, options);
1212 var = config_find_option(fmt, key);
1213 if (!var)
1214 return; /* give error on next pass. */
1216 option_reset(fmt, options, var, use_defaults);
1219 /** Return true iff key is a valid configuration option. */
1221 option_is_recognized(const char *key)
1223 config_var_t *var = config_find_option(&options_format, key);
1224 return (var != NULL);
1227 /** Return the canonical name of a configuration option. */
1228 const char *
1229 option_get_canonical_name(const char *key)
1231 config_var_t *var = config_find_option(&options_format, key);
1232 return var->name;
1235 /** Return a canonicalized list of the options assigned for key.
1237 config_line_t *
1238 option_get_assignment(or_options_t *options, const char *key)
1240 return get_assigned_option(&options_format, options, key);
1243 static config_line_t *
1244 config_lines_dup(const config_line_t *inp)
1246 config_line_t *result = NULL;
1247 config_line_t **next_out = &result;
1248 while (inp) {
1249 *next_out = tor_malloc(sizeof(config_line_t));
1250 (*next_out)->key = tor_strdup(inp->key);
1251 (*next_out)->value = tor_strdup(inp->value);
1252 inp = inp->next;
1253 next_out = &((*next_out)->next);
1255 (*next_out) = NULL;
1256 return result;
1259 static config_line_t *
1260 get_assigned_option(config_format_t *fmt, or_options_t *options,
1261 const char *key)
1263 config_var_t *var;
1264 const void *value;
1265 char buf[32];
1266 config_line_t *result;
1267 tor_assert(options && key);
1269 CHECK(fmt, options);
1271 var = config_find_option(fmt, key);
1272 if (!var) {
1273 log_warn(LD_CONFIG, "Unknown option '%s'. Failing.", key);
1274 return NULL;
1275 } else if (var->type == CONFIG_TYPE_LINELIST_S) {
1276 log_warn(LD_CONFIG,
1277 "Can't return context-sensitive '%s' on its own", key);
1278 return NULL;
1280 value = STRUCT_VAR_P(options, var->var_offset);
1282 if (var->type == CONFIG_TYPE_LINELIST ||
1283 var->type == CONFIG_TYPE_LINELIST_V) {
1284 /* Linelist requires special handling: we just copy and return it. */
1285 return config_lines_dup(*(const config_line_t**)value);
1288 result = tor_malloc_zero(sizeof(config_line_t));
1289 result->key = tor_strdup(var->name);
1290 switch (var->type)
1292 case CONFIG_TYPE_STRING:
1293 if (*(char**)value) {
1294 result->value = tor_strdup(*(char**)value);
1295 } else {
1296 tor_free(result->key);
1297 tor_free(result);
1298 return NULL;
1300 break;
1301 case CONFIG_TYPE_ISOTIME:
1302 if (*(time_t*)value) {
1303 result->value = tor_malloc(ISO_TIME_LEN+1);
1304 format_iso_time(result->value, *(time_t*)value);
1305 } else {
1306 tor_free(result->key);
1307 tor_free(result);
1309 break;
1310 case CONFIG_TYPE_INTERVAL:
1311 case CONFIG_TYPE_UINT:
1312 /* This means every or_options_t uint or bool element
1313 * needs to be an int. Not, say, a uint16_t or char. */
1314 tor_snprintf(buf, sizeof(buf), "%d", *(int*)value);
1315 result->value = tor_strdup(buf);
1316 break;
1317 case CONFIG_TYPE_MEMUNIT:
1318 tor_snprintf(buf, sizeof(buf), U64_FORMAT,
1319 U64_PRINTF_ARG(*(uint64_t*)value));
1320 result->value = tor_strdup(buf);
1321 break;
1322 case CONFIG_TYPE_DOUBLE:
1323 tor_snprintf(buf, sizeof(buf), "%f", *(double*)value);
1324 result->value = tor_strdup(buf);
1325 break;
1326 case CONFIG_TYPE_BOOL:
1327 result->value = tor_strdup(*(int*)value ? "1" : "0");
1328 break;
1329 case CONFIG_TYPE_CSV:
1330 if (*(smartlist_t**)value)
1331 result->value =
1332 smartlist_join_strings(*(smartlist_t**)value, ",", 0, NULL);
1333 else
1334 result->value = tor_strdup("");
1335 break;
1336 case CONFIG_TYPE_OBSOLETE:
1337 log_warn(LD_CONFIG,
1338 "You asked me for the value of an obsolete config option '%s'.",
1339 key);
1340 tor_free(result->key);
1341 tor_free(result);
1342 return NULL;
1343 default:
1344 tor_free(result->key);
1345 tor_free(result);
1346 log_warn(LD_BUG,"Bug: unknown type %d for known key '%s'",
1347 var->type, key);
1348 return NULL;
1351 return result;
1354 /** Iterate through the linked list of requested options <b>list</b>.
1355 * For each item, convert as appropriate and assign to <b>options</b>.
1356 * If an item is unrecognized, set *msg and return -1 immediately,
1357 * else return 0 for success.
1359 * If <b>clear_first</b>, interpret config options as replacing (not
1360 * extending) their previous values. If <b>clear_first</b> is set,
1361 * then <b>use_defaults</b> to decide if you set to defaults after
1362 * clearing, or make the value 0 or NULL.
1364 * Here are the use cases:
1365 * 1. A non-empty AllowInvalid line in your torrc. Appends to current
1366 * if linelist, replaces current if csv.
1367 * 2. An empty AllowInvalid line in your torrc. Should clear it.
1368 * 3. "RESETCONF AllowInvalid" sets it to default.
1369 * 4. "SETCONF AllowInvalid" makes it NULL.
1370 * 5. "SETCONF AllowInvalid=foo" clears it and sets it to "foo".
1372 * Use_defaults Clear_first
1373 * 0 0 "append"
1374 * 1 0 undefined, don't use
1375 * 0 1 "set to null first"
1376 * 1 1 "set to defaults first"
1377 * Return 0 on success, -1 on bad key, -2 on bad value.
1379 * As an additional special case, if a LINELIST config option has
1380 * no value and clear_first is 0, then warn and ignore it.
1384 There are three call cases for config_assign() currently.
1386 Case one: Torrc entry
1387 options_init_from_torrc() calls config_assign(0, 0)
1388 calls config_assign_line(0, 0).
1389 if value is empty, calls option_reset(0) and returns.
1390 calls config_assign_value(), appends.
1392 Case two: setconf
1393 options_trial_assign() calls config_assign(0, 1)
1394 calls config_reset_line(0)
1395 calls option_reset(0)
1396 calls option_clear().
1397 calls config_assign_line(0, 1).
1398 if value is empty, returns.
1399 calls config_assign_value(), appends.
1401 Case three: resetconf
1402 options_trial_assign() calls config_assign(1, 1)
1403 calls config_reset_line(1)
1404 calls option_reset(1)
1405 calls option_clear().
1406 calls config_assign_value(default)
1407 calls config_assign_line(1, 1).
1408 returns.
1410 static int
1411 config_assign(config_format_t *fmt, void *options, config_line_t *list,
1412 int use_defaults, int clear_first, char **msg)
1414 config_line_t *p;
1416 CHECK(fmt, options);
1418 /* pass 1: normalize keys */
1419 for (p = list; p; p = p->next) {
1420 const char *full = expand_abbrev(fmt, p->key, 0, 1);
1421 if (strcmp(full,p->key)) {
1422 tor_free(p->key);
1423 p->key = tor_strdup(full);
1427 /* pass 2: if we're reading from a resetting source, clear all
1428 * mentioned config options, and maybe set to their defaults. */
1429 if (clear_first) {
1430 for (p = list; p; p = p->next)
1431 config_reset_line(fmt, options, p->key, use_defaults);
1434 /* pass 3: assign. */
1435 while (list) {
1436 int r;
1437 if ((r=config_assign_line(fmt, options, list, use_defaults,
1438 clear_first, msg)))
1439 return r;
1440 list = list->next;
1442 return 0;
1445 /** Try assigning <b>list</b> to the global options. You do this by duping
1446 * options, assigning list to the new one, then validating it. If it's
1447 * ok, then throw out the old one and stick with the new one. Else,
1448 * revert to old and return failure. Return 0 on success, -1 on bad
1449 * keys, -2 on bad values, -3 on bad transition, and -4 on failed-to-set.
1451 * If not success, point *<b>msg</b> to a newly allocated string describing
1452 * what went wrong.
1455 options_trial_assign(config_line_t *list, int use_defaults,
1456 int clear_first, char **msg)
1458 int r;
1459 or_options_t *trial_options = options_dup(&options_format, get_options());
1461 if ((r=config_assign(&options_format, trial_options,
1462 list, use_defaults, clear_first, msg)) < 0) {
1463 config_free(&options_format, trial_options);
1464 return r;
1467 if (options_validate(get_options(), trial_options, 1, msg) < 0) {
1468 config_free(&options_format, trial_options);
1469 return -2;
1472 if (options_transition_allowed(get_options(), trial_options, msg) < 0) {
1473 config_free(&options_format, trial_options);
1474 return -3;
1477 if (set_options(trial_options, msg)<0) {
1478 config_free(&options_format, trial_options);
1479 return -4;
1482 /* we liked it. put it in place. */
1483 return 0;
1486 /** Reset config option <b>var</b> to 0, 0.0, NULL, or the equivalent.
1487 * Called from option_reset() and config_free(). */
1488 static void
1489 option_clear(config_format_t *fmt, or_options_t *options, config_var_t *var)
1491 void *lvalue = STRUCT_VAR_P(options, var->var_offset);
1492 switch (var->type) {
1493 case CONFIG_TYPE_STRING:
1494 tor_free(*(char**)lvalue);
1495 break;
1496 case CONFIG_TYPE_DOUBLE:
1497 *(double*)lvalue = 0.0;
1498 break;
1499 case CONFIG_TYPE_ISOTIME:
1500 *(time_t*)lvalue = 0;
1501 case CONFIG_TYPE_INTERVAL:
1502 case CONFIG_TYPE_UINT:
1503 case CONFIG_TYPE_BOOL:
1504 *(int*)lvalue = 0;
1505 break;
1506 case CONFIG_TYPE_MEMUNIT:
1507 *(uint64_t*)lvalue = 0;
1508 break;
1509 case CONFIG_TYPE_CSV:
1510 if (*(smartlist_t**)lvalue) {
1511 SMARTLIST_FOREACH(*(smartlist_t **)lvalue, char *, cp, tor_free(cp));
1512 smartlist_free(*(smartlist_t **)lvalue);
1513 *(smartlist_t **)lvalue = NULL;
1515 break;
1516 case CONFIG_TYPE_LINELIST:
1517 case CONFIG_TYPE_LINELIST_S:
1518 config_free_lines(*(config_line_t **)lvalue);
1519 *(config_line_t **)lvalue = NULL;
1520 break;
1521 case CONFIG_TYPE_LINELIST_V:
1522 /* handled by linelist_s. */
1523 break;
1524 case CONFIG_TYPE_OBSOLETE:
1525 break;
1529 /** Clear the option indexed by <b>var</b> in <b>options</b>. Then if
1530 * <b>use_defaults</b>, set it to its default value.
1531 * Called by config_init() and option_reset_line() and option_assign_line(). */
1532 static void
1533 option_reset(config_format_t *fmt, or_options_t *options,
1534 config_var_t *var, int use_defaults)
1536 config_line_t *c;
1537 void *lvalue;
1538 char *msg = NULL;
1539 CHECK(fmt, options);
1540 option_clear(fmt, options, var); /* clear it first */
1541 if (!use_defaults)
1542 return; /* all done */
1543 lvalue = STRUCT_VAR_P(options, var->var_offset);
1544 if (var->initvalue) {
1545 c = tor_malloc_zero(sizeof(config_line_t));
1546 c->key = tor_strdup(var->name);
1547 c->value = tor_strdup(var->initvalue);
1548 if (config_assign_value(fmt, options, c, &msg) < 0) {
1549 log_warn(LD_BUG, "Failed to assign default: %s", msg);
1550 tor_free(msg); /* if this happens it's a bug */
1552 config_free_lines(c);
1556 /** Print a usage message for tor. */
1557 static void
1558 print_usage(void)
1560 printf(
1561 "Copyright 2001-2005 Roger Dingledine, Nick Mathewson.\n\n"
1562 "tor -f <torrc> [args]\n"
1563 "See man page for options, or http://tor.eff.org/ for documentation.\n");
1567 * Based on <b>options-\>Address</b>, guess our public IP address and put it
1568 * (in host order) into *<b>addr_out</b>. If <b>hostname_out</b> is provided,
1569 * set *<b>hostname_out</b> to a new string holding the hostname we used to
1570 * get the address. Return 0 if all is well, or -1 if we can't find a suitable
1571 * public IP address.
1574 resolve_my_address(or_options_t *options, uint32_t *addr_out,
1575 char **hostname_out)
1577 struct in_addr in;
1578 struct hostent *rent;
1579 char hostname[256];
1580 int explicit_ip=1;
1581 int explicit_hostname=1;
1582 char tmpbuf[INET_NTOA_BUF_LEN];
1583 static uint32_t old_addr=0;
1584 const char *address = options->Address;
1586 tor_assert(addr_out);
1588 if (address && *address) {
1589 strlcpy(hostname, address, sizeof(hostname));
1590 } else { /* then we need to guess our address */
1591 explicit_ip = 0; /* it's implicit */
1592 explicit_hostname = 0; /* it's implicit */
1594 if (gethostname(hostname, sizeof(hostname)) < 0) {
1595 log_warn(LD_NET,"Error obtaining local hostname");
1596 return -1;
1598 log_debug(LD_CONFIG,"Guessed local host name as '%s'",hostname);
1601 /* now we know hostname. resolve it and keep only the IP */
1603 if (tor_inet_aton(hostname, &in) == 0) {
1604 /* then we have to resolve it */
1605 explicit_ip = 0;
1606 rent = (struct hostent *)gethostbyname(hostname);
1607 if (!rent) {
1608 uint32_t interface_ip;
1610 if (explicit_hostname) {
1611 log_warn(LD_CONFIG,"Could not resolve local Address '%s'. Failing.",
1612 hostname);
1613 return -1;
1615 log_notice(LD_CONFIG, "Could not resolve guessed local hostname '%s'. "
1616 "Trying something else.", hostname);
1617 if (get_interface_address(&interface_ip)) {
1618 log_warn(LD_CONFIG, "Could not get local interface IP address. "
1619 "Failing.");
1620 return -1;
1622 in.s_addr = htonl(interface_ip);
1623 tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
1624 log_notice(LD_CONFIG, "Learned IP address '%s' for local interface."
1625 " Using that.", tmpbuf);
1626 strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
1627 } else {
1628 tor_assert(rent->h_length == 4);
1629 memcpy(&in.s_addr, rent->h_addr, rent->h_length);
1631 if (!explicit_hostname &&
1632 is_internal_IP(ntohl(in.s_addr), 0)) {
1633 uint32_t interface_ip;
1635 tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
1636 log_notice(LD_CONFIG, "Guessed local hostname '%s' resolves to a "
1637 "private IP address (%s). Trying something else.", hostname,
1638 tmpbuf);
1640 if (get_interface_address(&interface_ip)) {
1641 log_warn(LD_CONFIG, "Could not get local interface IP address. "
1642 "Too bad.");
1643 } else if (is_internal_IP(interface_ip, 0)) {
1644 struct in_addr in2;
1645 in2.s_addr = htonl(interface_ip);
1646 tor_inet_ntoa(&in2,tmpbuf,sizeof(tmpbuf));
1647 log_notice(LD_CONFIG, "Interface IP '%s' is a private address "
1648 "too. Ignoring.", tmpbuf);
1649 } else {
1650 in.s_addr = htonl(interface_ip);
1651 tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
1652 log_notice(LD_CONFIG, "Learned IP address '%s' for local interface."
1653 " Using that.", tmpbuf);
1654 strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
1660 tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
1661 if (is_internal_IP(ntohl(in.s_addr), 0) &&
1662 options->PublishServerDescriptor) {
1663 /* make sure we're ok with publishing an internal IP */
1664 if (!options->DirServers) {
1665 /* if they are using the default dirservers, disallow internal IPs
1666 * always. */
1667 log_warn(LD_CONFIG,"Address '%s' resolves to private IP '%s'. "
1668 "Tor servers that use the default DirServers must have public "
1669 "IP addresses.",
1670 hostname, tmpbuf);
1671 return -1;
1673 if (!explicit_ip) {
1674 /* even if they've set their own dirservers, require an explicit IP if
1675 * they're using an internal address. */
1676 log_warn(LD_CONFIG,"Address '%s' resolves to private IP '%s'. Please "
1677 "set the Address config option to be the IP you want to use.",
1678 hostname, tmpbuf);
1679 return -1;
1683 log_debug(LD_CONFIG, "Resolved Address to '%s'.", tmpbuf);
1684 *addr_out = ntohl(in.s_addr);
1685 if (old_addr && old_addr != *addr_out) {
1686 log_notice(LD_NET, "Your IP seems to have changed. Updating.");
1687 server_has_changed_ip();
1689 old_addr = *addr_out;
1690 if (hostname_out)
1691 *hostname_out = tor_strdup(hostname);
1692 return 0;
1695 /** Called when we don't have a nickname set. Try to guess a good nickname
1696 * based on the hostname, and return it in a newly allocated string. If we
1697 * can't, return NULL and let the caller warn if it wants to. */
1698 static char *
1699 get_default_nickname(void)
1701 char localhostname[256];
1702 char *cp, *out, *outp;
1704 if (gethostname(localhostname, sizeof(localhostname)) < 0)
1705 return NULL;
1707 /* Put it in lowercase; stop at the first dot. */
1708 for (cp = localhostname; *cp; ++cp) {
1709 if (*cp == '.') {
1710 *cp = '\0';
1711 break;
1713 *cp = tolower(*cp);
1716 /* Strip invalid characters. */
1717 cp = localhostname;
1718 out = outp = tor_malloc(strlen(localhostname) + 1);
1719 while (*cp) {
1720 if (strchr(LEGAL_NICKNAME_CHARACTERS, *cp))
1721 *outp++ = *cp++;
1722 else
1723 cp++;
1725 *outp = '\0';
1727 /* Enforce length. */
1728 if (strlen(out) > MAX_NICKNAME_LEN)
1729 out[MAX_NICKNAME_LEN]='\0';
1731 return out;
1734 /** Release storage held by <b>options</b> */
1735 static void
1736 config_free(config_format_t *fmt, void *options)
1738 int i;
1740 tor_assert(options);
1742 for (i=0; fmt->vars[i].name; ++i)
1743 option_clear(fmt, options, &(fmt->vars[i]));
1744 if (fmt->extra) {
1745 config_line_t **linep = STRUCT_VAR_P(options, fmt->extra->var_offset);
1746 config_free_lines(*linep);
1747 *linep = NULL;
1749 tor_free(options);
1752 /** Return true iff a and b contain identical keys and values in identical
1753 * order. */
1754 static int
1755 config_lines_eq(config_line_t *a, config_line_t *b)
1757 while (a && b) {
1758 if (strcasecmp(a->key, b->key) || strcmp(a->value, b->value))
1759 return 0;
1760 a = a->next;
1761 b = b->next;
1763 if (a || b)
1764 return 0;
1765 return 1;
1768 /** Return true iff the option <b>var</b> has the same value in <b>o1</b>
1769 * and <b>o2</b>. Must not be called for LINELIST_S or OBSOLETE options.
1771 static int
1772 option_is_same(config_format_t *fmt,
1773 or_options_t *o1, or_options_t *o2, const char *name)
1775 config_line_t *c1, *c2;
1776 int r = 1;
1777 CHECK(fmt, o1);
1778 CHECK(fmt, o2);
1780 c1 = get_assigned_option(fmt, o1, name);
1781 c2 = get_assigned_option(fmt, o2, name);
1782 r = config_lines_eq(c1, c2);
1783 config_free_lines(c1);
1784 config_free_lines(c2);
1785 return r;
1788 /** Copy storage held by <b>old</b> into a new or_options_t and return it. */
1789 static or_options_t *
1790 options_dup(config_format_t *fmt, or_options_t *old)
1792 or_options_t *newopts;
1793 int i;
1794 config_line_t *line;
1796 newopts = config_alloc(fmt);
1797 for (i=0; fmt->vars[i].name; ++i) {
1798 if (fmt->vars[i].type == CONFIG_TYPE_LINELIST_S)
1799 continue;
1800 if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE)
1801 continue;
1802 line = get_assigned_option(fmt, old, fmt->vars[i].name);
1803 if (line) {
1804 char *msg = NULL;
1805 if (config_assign(fmt, newopts, line, 0, 0, &msg) < 0) {
1806 log_err(LD_BUG, "Bug: config_get_assigned_option() generated "
1807 "something we couldn't config_assign(): %s", msg);
1808 tor_free(msg);
1809 tor_assert(0);
1812 config_free_lines(line);
1814 return newopts;
1817 /** Return a new empty or_options_t. Used for testing. */
1818 or_options_t *
1819 options_new(void)
1821 return config_alloc(&options_format);
1824 /** Set <b>options</b> to hold reasonable defaults for most options.
1825 * Each option defaults to zero. */
1826 void
1827 options_init(or_options_t *options)
1829 config_init(&options_format, options);
1832 /* Set all vars in the configuration object 'options' to their default
1833 * values. */
1834 static void
1835 config_init(config_format_t *fmt, void *options)
1837 int i;
1838 config_var_t *var;
1839 CHECK(fmt, options);
1841 for (i=0; fmt->vars[i].name; ++i) {
1842 var = &fmt->vars[i];
1843 if (!var->initvalue)
1844 continue; /* defaults to NULL or 0 */
1845 option_reset(fmt, options, var, 1);
1849 /* Allocate and return a new string holding the written-out values of the vars
1850 * in 'options' If 'minimal', do not write out any default-valued vars. */
1851 static char *
1852 config_dump(config_format_t *fmt, void *options, int minimal)
1854 smartlist_t *elements;
1855 or_options_t *defaults;
1856 config_line_t *line, *assigned;
1857 char *result;
1858 int i;
1859 const char *desc;
1860 char *msg = NULL;
1862 defaults = config_alloc(fmt);
1863 config_init(fmt, defaults);
1865 /* XXX use a 1 here so we don't add a new log line while dumping */
1866 if (fmt->validate_fn(NULL,defaults, 1, &msg) < 0) {
1867 log_err(LD_BUG, "Failed to validate default config.");
1868 tor_free(msg);
1869 tor_assert(0);
1872 elements = smartlist_create();
1873 for (i=0; fmt->vars[i].name; ++i) {
1874 if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE ||
1875 fmt->vars[i].type == CONFIG_TYPE_LINELIST_S)
1876 continue;
1877 /* Don't save 'hidden' control variables. */
1878 if (!strcmpstart(fmt->vars[i].name, "__"))
1879 continue;
1880 if (minimal && option_is_same(fmt, options, defaults, fmt->vars[i].name))
1881 continue;
1883 desc = config_find_description(fmt, fmt->vars[i].name);
1884 line = assigned = get_assigned_option(fmt, options, fmt->vars[i].name);
1886 if (line && desc) {
1887 /* Only dump the description if there's something to describe. */
1888 size_t len = strlen(desc)+8;
1889 char *tmp = tor_malloc(len);
1890 tor_snprintf(tmp, len, "# %s\n",desc);
1891 smartlist_add(elements, tmp);
1894 for (; line; line = line->next) {
1895 size_t len = strlen(line->key) + strlen(line->value) + 3;
1896 char *tmp;
1897 tmp = tor_malloc(len);
1898 if (tor_snprintf(tmp, len, "%s %s\n", line->key, line->value)<0) {
1899 log_err(LD_BUG,"Internal error writing option value");
1900 tor_assert(0);
1902 smartlist_add(elements, tmp);
1904 config_free_lines(assigned);
1907 if (fmt->extra) {
1908 line = *(config_line_t**)STRUCT_VAR_P(options, fmt->extra->var_offset);
1909 for (; line; line = line->next) {
1910 size_t len = strlen(line->key) + strlen(line->value) + 3;
1911 char *tmp;
1912 tmp = tor_malloc(len);
1913 if (tor_snprintf(tmp, len, "%s %s\n", line->key, line->value)<0) {
1914 log_err(LD_BUG,"Internal error writing option value");
1915 tor_assert(0);
1917 smartlist_add(elements, tmp);
1921 result = smartlist_join_strings(elements, "", 0, NULL);
1922 SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
1923 smartlist_free(elements);
1924 config_free(fmt, defaults);
1925 return result;
1928 /** Return a string containing a possible configuration file that would give
1929 * the configuration in <b>options</b>. If <b>minimal</b> is true, do not
1930 * include options that are the same as Tor's defaults.
1932 char *
1933 options_dump(or_options_t *options, int minimal)
1935 return config_dump(&options_format, options, minimal);
1938 /* Return 0 if every element of sl is a string holding a decimal
1939 * representation of a port number, or if sl is NULL.
1940 * Otherwise set *msg and return -1. */
1941 static int
1942 validate_ports_csv(smartlist_t *sl, const char *name, char **msg)
1944 int i;
1945 char buf[1024];
1946 tor_assert(name);
1948 if (!sl)
1949 return 0;
1951 SMARTLIST_FOREACH(sl, const char *, cp,
1953 i = atoi(cp);
1954 if (i < 1 || i > 65535) {
1955 int r = tor_snprintf(buf, sizeof(buf),
1956 "Port '%s' out of range in %s", cp, name);
1957 *msg = tor_strdup(r >= 0 ? buf : "internal error");
1958 return -1;
1961 return 0;
1964 /** Lowest allowable value for DirFetchPeriod; if this is too low, clients can
1965 * overload the directory system. */
1966 #define MIN_DIR_FETCH_PERIOD (10*60)
1967 /** Lowest allowable value for RendPostPeriod; if this is too low, hidden
1968 * services can overload the directory system. */
1969 #define MIN_REND_POST_PERIOD (5*60)
1970 /** Lowest allowable value for StatusFetchPeriod; if this is too low, clients
1971 * can overload the directory system. */
1972 #define MIN_STATUS_FETCH_PERIOD (5*60)
1974 /** Highest allowable value for DirFetchPeriod, StatusFetchPeriod, and
1975 * RendPostPeriod. */
1976 #define MAX_DIR_PERIOD (MIN_ONION_KEY_LIFETIME/2)
1977 /** Highest allowable value for DirFetchPeriod for directory caches. */
1978 #define MAX_CACHE_DIR_FETCH_PERIOD (60*60)
1979 /** Highest allowable value for StatusFetchPeriod for directory caches. */
1980 #define MAX_CACHE_STATUS_FETCH_PERIOD (15*60)
1982 /** Return 0 if every setting in <b>options</b> is reasonable, and a
1983 * permissible transition from <b>old_options</b>. Else return -1.
1984 * Should have no side effects, except for normalizing the contents of
1985 * <b>options</b>.
1987 * On error, tor_strdup an error explanation into *<b>msg</b>.
1989 * XXX
1990 * If <b>from_setconf</b>, we were called by the controller, and our
1991 * Log line should stay empty. If it's 0, then give us a default log
1992 * if there are no logs defined.
1994 static int
1995 options_validate(or_options_t *old_options, or_options_t *options,
1996 int from_setconf, char **msg)
1998 int i, r;
1999 config_line_t *cl;
2000 const char *uname;
2001 char buf[1024];
2002 #define REJECT(arg) \
2003 do { *msg = tor_strdup(arg); return -1; } while (0)
2004 #define COMPLAIN(arg) do { log(LOG_WARN, LD_CONFIG, arg); } while (0)
2006 tor_assert(msg);
2007 *msg = NULL;
2009 if (options->ORPort < 0 || options->ORPort > 65535)
2010 REJECT("ORPort option out of bounds.");
2012 uname = get_uname();
2013 if (server_mode(options) &&
2014 (!strcmpstart(uname, "Windows 95") ||
2015 !strcmpstart(uname, "Windows 98") ||
2016 !strcmpstart(uname, "Windows Me"))) {
2017 log(LOG_WARN, LD_CONFIG, "Tor is running as a server, but you are "
2018 "running %s; this probably won't work. See "
2019 "http://wiki.noreply.org/noreply/TheOnionRouter/TorFAQ#ServerOS "
2020 "for details.", get_uname());
2023 if (options->ORPort == 0 && options->ORListenAddress != NULL)
2024 REJECT("ORPort must be defined if ORListenAddress is defined.");
2026 if (options->DirPort == 0 && options->DirListenAddress != NULL)
2027 REJECT("DirPort must be defined if DirListenAddress is defined.");
2029 if (options->ControlPort == 0 && options->ControlListenAddress != NULL)
2030 REJECT("ControlPort must be defined if ControlListenAddress is defined.");
2032 #if 0 /* don't complain, since a standard configuration does this! */
2033 if (options->SocksPort == 0 && options->SocksListenAddress != NULL)
2034 REJECT("SocksPort must be defined if SocksListenAddress is defined.");
2035 #endif
2037 if (options->SocksListenAddress) {
2038 config_line_t *line = NULL;
2039 char *address = NULL;
2040 for (line = options->SocksListenAddress; line; line = line->next) {
2041 uint16_t port;
2042 uint32_t addr;
2043 if (parse_addr_port(line->value, &address, &addr, &port)<0)
2044 continue; /* We'll warn about this later. */
2045 if (!is_internal_IP(addr, 1) &&
2046 (!old_options || !config_lines_eq(old_options->SocksListenAddress,
2047 options->SocksListenAddress))) {
2048 log_warn(LD_CONFIG,
2049 "You specified a public address '%s' for a SOCKS listener. Other "
2050 "people on the Internet might find your computer and use it as "
2051 "an open SOCKS proxy. Please don't allow this unless you have "
2052 "a good reason.", address);
2054 tor_free(address);
2058 if (validate_data_directory(options)<0)
2059 REJECT("Invalid DataDirectory");
2061 if (options->Nickname == NULL) {
2062 if (server_mode(options)) {
2063 if (!(options->Nickname = get_default_nickname()))
2064 REJECT("Error obtaining local hostname");
2065 log_notice(LD_CONFIG, "Choosing default nickname '%s'",
2066 options->Nickname);
2068 } else {
2069 if (!is_legal_nickname(options->Nickname)) {
2070 r = tor_snprintf(buf, sizeof(buf),
2071 "Nickname '%s' is wrong length or contains illegal characters.",
2072 options->Nickname);
2073 *msg = tor_strdup(r >= 0 ? buf : "internal error");
2074 return -1;
2078 if (server_mode(options) && !options->ContactInfo)
2079 log(LOG_NOTICE, LD_CONFIG, "Your ContactInfo config option is not set. "
2080 "Please consider setting it, so we can contact you if your server is "
2081 "misconfigured or something else goes wrong.");
2083 if (normalize_log_options(options))
2084 REJECT("Failed to normalize old Log options. See logs for details.");
2086 /* Special case on first boot if no Log options are given. */
2087 if (!options->Logs && !from_setconf)
2088 config_line_append(&options->Logs, "Log", "notice stdout");
2090 if (options_init_logs(options, 1)<0) /* Validate the log(s) */
2091 REJECT("Failed to validate Log options. See logs for details.");
2093 if (options->NoPublish) {
2094 log(LOG_WARN, LD_CONFIG,
2095 "NoPublish is obsolete. Use PublishServerDescriptor instead.");
2096 options->PublishServerDescriptor = 0;
2099 if (server_mode(options)) {
2100 /* confirm that our address isn't broken, so we can complain now */
2101 uint32_t tmp;
2102 if (resolve_my_address(options, &tmp, NULL) < 0)
2103 REJECT("Failed to resolve/guess local address. See logs for details.");
2106 #ifndef MS_WINDOWS
2107 if (options->RunAsDaemon && torrc_fname && path_is_relative(torrc_fname))
2108 REJECT("Can't use a relative path to torrc when RunAsDaemon is set.");
2109 #endif
2111 if (options->SocksPort < 0 || options->SocksPort > 65535)
2112 REJECT("SocksPort option out of bounds.");
2114 if (options->SocksPort == 0 && options->ORPort == 0)
2115 REJECT("SocksPort and ORPort are both undefined? Quitting.");
2117 if (options->ControlPort < 0 || options->ControlPort > 65535)
2118 REJECT("ControlPort option out of bounds.");
2120 if (options->DirPort < 0 || options->DirPort > 65535)
2121 REJECT("DirPort option out of bounds.");
2123 if (options->StrictExitNodes &&
2124 (!options->ExitNodes || !strlen(options->ExitNodes)) &&
2125 (!old_options ||
2126 (old_options->StrictExitNodes != options->StrictExitNodes) ||
2127 (!opt_streq(old_options->ExitNodes, options->ExitNodes))))
2128 COMPLAIN("StrictExitNodes set, but no ExitNodes listed.");
2130 if (options->StrictEntryNodes &&
2131 (!options->EntryNodes || !strlen(options->EntryNodes)) &&
2132 (!old_options ||
2133 (old_options->StrictEntryNodes != options->StrictEntryNodes) ||
2134 (!opt_streq(old_options->EntryNodes, options->EntryNodes))))
2135 COMPLAIN("StrictEntryNodes set, but no EntryNodes listed.");
2137 if (options->AuthoritativeDir) {
2138 if (!options->ContactInfo)
2139 REJECT("Authoritative directory servers must set ContactInfo");
2140 if (options->V1AuthoritativeDir && !options->RecommendedVersions)
2141 REJECT("V1 auth dir servers must set RecommendedVersions.");
2142 if (!options->RecommendedClientVersions)
2143 options->RecommendedClientVersions =
2144 config_lines_dup(options->RecommendedVersions);
2145 if (!options->RecommendedServerVersions)
2146 options->RecommendedServerVersions =
2147 config_lines_dup(options->RecommendedVersions);
2148 if (options->VersioningAuthoritativeDir &&
2149 (!options->RecommendedClientVersions ||
2150 !options->RecommendedServerVersions))
2151 REJECT("Versioning auth dir servers must set Recommended*Versions.");
2152 if (options->UseEntryGuards) {
2153 log_info(LD_CONFIG, "Authoritative directory servers can't set "
2154 "UseEntryGuards. Disabling.");
2155 options->UseEntryGuards = 0;
2159 if (options->AuthoritativeDir && !options->DirPort)
2160 REJECT("Running as authoritative directory, but no DirPort set.");
2162 if (options->AuthoritativeDir && !options->ORPort)
2163 REJECT("Running as authoritative directory, but no ORPort set.");
2165 if (options->AuthoritativeDir && options->ClientOnly)
2166 REJECT("Running as authoritative directory, but ClientOnly also set.");
2168 if (options->ConnLimit <= 0) {
2169 r = tor_snprintf(buf, sizeof(buf),
2170 "ConnLimit must be greater than 0, but was set to %d",
2171 options->ConnLimit);
2172 *msg = tor_strdup(r >= 0 ? buf : "internal error");
2173 return -1;
2176 if (options->_AccountingMaxKB) {
2177 log(LOG_WARN, LD_CONFIG, "AccountingMaxKB is deprecated. "
2178 "Say 'AccountingMax %d KB' instead.", options->_AccountingMaxKB);
2179 options->AccountingMax = U64_LITERAL(1024)*options->_AccountingMaxKB;
2180 options->_AccountingMaxKB = 0;
2183 if (validate_ports_csv(options->FirewallPorts, "FirewallPorts", msg) < 0)
2184 return -1;
2186 if (validate_ports_csv(options->LongLivedPorts, "LongLivedPorts", msg) < 0)
2187 return -1;
2189 if (options->FascistFirewall && !options->ReachableAddresses) {
2190 if (smartlist_len(options->FirewallPorts)) {
2191 /* We already have firewall ports set, so migrate them to
2192 * ReachableAddresses, which will set ReachableORAddresses and
2193 * ReachableDirAddresses if they aren't set explicitly. */
2194 smartlist_t *instead = smartlist_create();
2195 config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
2196 new_line->key = tor_strdup("ReachableAddresses");
2197 /* If we're configured with the old format, we need to prepend some
2198 * open ports. */
2199 SMARTLIST_FOREACH(options->FirewallPorts, const char *, portno,
2201 int p = atoi(portno);
2202 char *s;
2203 if (p<0) continue;
2204 s = tor_malloc(16);
2205 tor_snprintf(s, 16, "*:%d", p);
2206 smartlist_add(instead, s);
2208 new_line->value = smartlist_join_strings(instead,",",0,NULL);
2209 /* These have been deprecated since 0.1.1.5-alpha-cvs */
2210 log(LOG_NOTICE, LD_CONFIG,
2211 "Converting FascistFirewall and FirewallPorts "
2212 "config options to new format: \"ReachableAddresses %s\"",
2213 new_line->value);
2214 options->ReachableAddresses = new_line;
2215 SMARTLIST_FOREACH(instead, char *, cp, tor_free(cp));
2216 smartlist_free(instead);
2217 } else {
2218 /* We do not have FirewallPorts set, so add 80 to
2219 * ReachableDirAddresses, and 443 to ReachableORAddresses. */
2220 if (!options->ReachableDirAddresses) {
2221 config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
2222 new_line->key = tor_strdup("ReachableDirAddresses");
2223 new_line->value = tor_strdup("*:80");
2224 options->ReachableDirAddresses = new_line;
2225 log(LOG_NOTICE, LD_CONFIG, "Converting FascistFirewall config option "
2226 "to new format: \"ReachableDirAddresses *:80\"");
2228 if (!options->ReachableORAddresses) {
2229 config_line_t *new_line = tor_malloc_zero(sizeof(config_line_t));
2230 new_line->key = tor_strdup("ReachableORAddresses");
2231 new_line->value = tor_strdup("*:443");
2232 options->ReachableORAddresses = new_line;
2233 log(LOG_NOTICE, LD_CONFIG, "Converting FascistFirewall config option "
2234 "to new format: \"ReachableORAddresses *:443\"");
2239 for (i=0; i<3; i++) {
2240 config_line_t **linep =
2241 (i==0) ? &options->ReachableAddresses :
2242 (i==1) ? &options->ReachableORAddresses :
2243 &options->ReachableDirAddresses;
2244 if (!*linep)
2245 continue;
2246 /* We need to end with a reject *:*, not an implicit accept *:* */
2247 for (;;) {
2248 if (!strcmp((*linep)->value, "reject *:*")) /* already there */
2249 break;
2250 linep = &((*linep)->next);
2251 if (!*linep) {
2252 *linep = tor_malloc_zero(sizeof(config_line_t));
2253 (*linep)->key = tor_strdup(
2254 (i==0) ? "ReachableAddresses" :
2255 (i==1) ? "ReachableORAddresses" :
2256 "ReachableDirAddresses");
2257 (*linep)->value = tor_strdup("reject *:*");
2258 break;
2263 if ((options->ReachableAddresses ||
2264 options->ReachableORAddresses ||
2265 options->ReachableDirAddresses) &&
2266 server_mode(options))
2267 REJECT("Servers must be able to freely connect to the rest "
2268 "of the Internet, so they must not set Reachable*Addresses "
2269 "or FascistFirewall.");
2271 options->_AllowInvalid = 0;
2272 if (options->AllowInvalidNodes) {
2273 SMARTLIST_FOREACH(options->AllowInvalidNodes, const char *, cp, {
2274 if (!strcasecmp(cp, "entry"))
2275 options->_AllowInvalid |= ALLOW_INVALID_ENTRY;
2276 else if (!strcasecmp(cp, "exit"))
2277 options->_AllowInvalid |= ALLOW_INVALID_EXIT;
2278 else if (!strcasecmp(cp, "middle"))
2279 options->_AllowInvalid |= ALLOW_INVALID_MIDDLE;
2280 else if (!strcasecmp(cp, "introduction"))
2281 options->_AllowInvalid |= ALLOW_INVALID_INTRODUCTION;
2282 else if (!strcasecmp(cp, "rendezvous"))
2283 options->_AllowInvalid |= ALLOW_INVALID_RENDEZVOUS;
2284 else {
2285 r = tor_snprintf(buf, sizeof(buf),
2286 "Unrecognized value '%s' in AllowInvalidNodes", cp);
2287 *msg = tor_strdup(r >= 0 ? buf : "internal error");
2288 return -1;
2293 if (options->SocksPort >= 1 &&
2294 (options->PathlenCoinWeight < 0.0 || options->PathlenCoinWeight >= 1.0))
2295 REJECT("PathlenCoinWeight option must be >=0.0 and <1.0.");
2297 if (options->DirFetchPeriod &&
2298 options->DirFetchPeriod < MIN_DIR_FETCH_PERIOD) {
2299 log(LOG_WARN, LD_CONFIG,
2300 "DirFetchPeriod option must be at least %d seconds. Clipping.",
2301 MIN_DIR_FETCH_PERIOD);
2302 options->DirFetchPeriod = MIN_DIR_FETCH_PERIOD;
2304 if (options->StatusFetchPeriod &&
2305 options->StatusFetchPeriod < MIN_STATUS_FETCH_PERIOD) {
2306 log(LOG_WARN, LD_CONFIG,
2307 "StatusFetchPeriod option must be at least %d seconds. Clipping.",
2308 MIN_STATUS_FETCH_PERIOD);
2309 options->StatusFetchPeriod = MIN_STATUS_FETCH_PERIOD;
2311 if (options->RendPostPeriod < MIN_REND_POST_PERIOD) {
2312 log(LOG_WARN,LD_CONFIG,"RendPostPeriod option must be at least %d seconds."
2313 " Clipping.", MIN_REND_POST_PERIOD);
2314 options->RendPostPeriod = MIN_REND_POST_PERIOD;
2317 if (options->DirPort && ! options->AuthoritativeDir) {
2318 if (options->DirFetchPeriod > MAX_CACHE_DIR_FETCH_PERIOD) {
2319 log(LOG_WARN, LD_CONFIG, "Caching directory servers must have "
2320 "DirFetchPeriod less than %d seconds. Clipping.",
2321 MAX_CACHE_DIR_FETCH_PERIOD);
2322 options->DirFetchPeriod = MAX_CACHE_DIR_FETCH_PERIOD;
2324 if (options->StatusFetchPeriod > MAX_CACHE_STATUS_FETCH_PERIOD) {
2325 log(LOG_WARN, LD_CONFIG, "Caching directory servers must have "
2326 "StatusFetchPeriod less than %d seconds. Clipping.",
2327 MAX_CACHE_STATUS_FETCH_PERIOD);
2328 options->StatusFetchPeriod = MAX_CACHE_STATUS_FETCH_PERIOD;
2332 if (options->DirFetchPeriod > MAX_DIR_PERIOD) {
2333 log(LOG_WARN, LD_CONFIG, "DirFetchPeriod is too large; clipping to %ds.",
2334 MAX_DIR_PERIOD);
2335 options->DirFetchPeriod = MAX_DIR_PERIOD;
2337 if (options->StatusFetchPeriod > MAX_DIR_PERIOD) {
2338 log(LOG_WARN, LD_CONFIG,"StatusFetchPeriod is too large; clipping to %ds.",
2339 MAX_DIR_PERIOD);
2340 options->StatusFetchPeriod = MAX_DIR_PERIOD;
2342 if (options->RendPostPeriod > MAX_DIR_PERIOD) {
2343 log(LOG_WARN, LD_CONFIG, "RendPostPeriod is too large; clipping to %ds.",
2344 MAX_DIR_PERIOD);
2345 options->RendPostPeriod = MAX_DIR_PERIOD;
2348 if (options->KeepalivePeriod < 1)
2349 REJECT("KeepalivePeriod option must be positive.");
2351 if (options->BandwidthRate > INT_MAX) {
2352 r = tor_snprintf(buf, sizeof(buf),
2353 "BandwidthRate must be less than %d",INT_MAX);
2354 *msg = tor_strdup(r >= 0 ? buf : "internal error");
2355 return -1;
2357 if (options->BandwidthBurst > INT_MAX) {
2358 r = tor_snprintf(buf, sizeof(buf),
2359 "BandwidthBurst must be less than %d",INT_MAX);
2360 *msg = tor_strdup(r >= 0 ? buf : "internal error");
2361 return -1;
2363 if (server_mode(options) &&
2364 options->BandwidthRate < ROUTER_REQUIRED_MIN_BANDWIDTH*2) {
2365 r = tor_snprintf(buf, sizeof(buf),
2366 "BandwidthRate is set to %d bytes/second. "
2367 "For servers, it must be at least %d.",
2368 (int)options->BandwidthRate,
2369 ROUTER_REQUIRED_MIN_BANDWIDTH*2);
2370 *msg = tor_strdup(r >= 0 ? buf : "internal error");
2371 return -1;
2373 if (options->BandwidthRate > options->BandwidthBurst)
2374 REJECT("BandwidthBurst must be at least equal to BandwidthRate.");
2376 if (accounting_parse_options(options, 1)<0)
2377 REJECT("Failed to parse accounting options. See logs for details.");
2379 if (options->HttpProxy) { /* parse it now */
2380 if (parse_addr_port(options->HttpProxy, NULL,
2381 &options->HttpProxyAddr, &options->HttpProxyPort) < 0)
2382 REJECT("HttpProxy failed to parse or resolve. Please fix.");
2383 if (options->HttpProxyPort == 0) { /* give it a default */
2384 options->HttpProxyPort = 80;
2388 if (options->HttpProxyAuthenticator) {
2389 if (strlen(options->HttpProxyAuthenticator) >= 48)
2390 REJECT("HttpProxyAuthenticator is too long (>= 48 chars).");
2393 if (options->HttpsProxy) { /* parse it now */
2394 if (parse_addr_port(options->HttpsProxy, NULL,
2395 &options->HttpsProxyAddr, &options->HttpsProxyPort) <0)
2396 REJECT("HttpsProxy failed to parse or resolve. Please fix.");
2397 if (options->HttpsProxyPort == 0) { /* give it a default */
2398 options->HttpsProxyPort = 443;
2402 if (options->HttpsProxyAuthenticator) {
2403 if (strlen(options->HttpsProxyAuthenticator) >= 48)
2404 REJECT("HttpsProxyAuthenticator is too long (>= 48 chars).");
2407 if (options->HashedControlPassword) {
2408 if (decode_hashed_password(NULL, options->HashedControlPassword)<0)
2409 REJECT("Bad HashedControlPassword: wrong length or bad encoding");
2411 if (options->HashedControlPassword && options->CookieAuthentication)
2412 REJECT("Cannot set both HashedControlPassword and CookieAuthentication");
2414 if (options->UseEntryGuards && ! options->NumEntryGuards)
2415 REJECT("Cannot enable UseEntryGuards with NumEntryGuards set to 0");
2417 if (check_nickname_list(options->ExitNodes, "ExitNodes", msg))
2418 return -1;
2419 if (check_nickname_list(options->EntryNodes, "EntryNodes", msg))
2420 return -1;
2421 if (check_nickname_list(options->ExcludeNodes, "ExcludeNodes", msg))
2422 return -1;
2423 if (check_nickname_list(options->RendNodes, "RendNodes", msg))
2424 return -1;
2425 if (check_nickname_list(options->RendNodes, "RendExcludeNodes", msg))
2426 return -1;
2427 if (check_nickname_list(options->MyFamily, "MyFamily", msg))
2428 return -1;
2429 for (cl = options->NodeFamilies; cl; cl = cl->next) {
2430 if (check_nickname_list(cl->value, "NodeFamily", msg))
2431 return -1;
2434 if (validate_addr_policies(options, msg) < 0)
2435 return -1;
2437 for (cl = options->RedirectExit; cl; cl = cl->next) {
2438 if (parse_redirect_line(NULL, cl, msg)<0)
2439 return -1;
2442 if (options->DirServers) {
2443 if (!old_options ||
2444 !config_lines_eq(options->DirServers, old_options->DirServers))
2445 COMPLAIN("You have used DirServer to specify directory authorities in "
2446 "your configuration. This is potentially dangerous: it can "
2447 "make you look different from all other Tor users, and hurt "
2448 "your anonymity. Even if you've specified the same "
2449 "authorities as Tor uses by default, the defaults could "
2450 "change in the future. Be sure you know what you're doing.");
2451 for (cl = options->DirServers; cl; cl = cl->next) {
2452 if (parse_dir_server_line(cl->value, 1)<0)
2453 REJECT("DirServer line did not parse. See logs for details.");
2457 if (rend_config_services(options, 1) < 0)
2458 REJECT("Failed to configure rendezvous options. See logs for details.");
2460 if (parse_virtual_addr_network(options->VirtualAddrNetwork, 1, NULL)<0)
2461 return -1;
2463 return 0;
2464 #undef REJECT
2465 #undef COMPLAIN
2468 /** Helper: return true iff s1 and s2 are both NULL, or both non-NULL
2469 * equal strings. */
2470 static int
2471 opt_streq(const char *s1, const char *s2)
2473 if (!s1 && !s2)
2474 return 1;
2475 else if (s1 && s2 && !strcmp(s1,s2))
2476 return 1;
2477 else
2478 return 0;
2481 /** Check if any of the previous options have changed but aren't allowed to. */
2482 static int
2483 options_transition_allowed(or_options_t *old, or_options_t *new_val,
2484 char **msg)
2486 if (!old)
2487 return 0;
2489 if (!opt_streq(old->PidFile, new_val->PidFile)) {
2490 *msg = tor_strdup("PidFile is not allowed to change.");
2491 return -1;
2494 if (old->RunAsDaemon != new_val->RunAsDaemon) {
2495 *msg = tor_strdup("While Tor is running, changing RunAsDaemon "
2496 "is not allowed.");
2497 return -1;
2500 if (strcmp(old->DataDirectory,new_val->DataDirectory)!=0) {
2501 char buf[1024];
2502 int r = tor_snprintf(buf, sizeof(buf),
2503 "While Tor is running, changing DataDirectory "
2504 "(\"%s\"->\"%s\") is not allowed.",
2505 old->DataDirectory, new_val->DataDirectory);
2506 *msg = tor_strdup(r >= 0 ? buf : "internal error");
2507 return -1;
2510 if (!opt_streq(old->User, new_val->User)) {
2511 *msg = tor_strdup("While Tor is running, changing User is not allowed.");
2512 return -1;
2515 if (!opt_streq(old->Group, new_val->Group)) {
2516 *msg = tor_strdup("While Tor is running, changing Group is not allowed.");
2517 return -1;
2520 if (old->HardwareAccel != new_val->HardwareAccel) {
2521 *msg = tor_strdup("While Tor is running, changing HardwareAccel is "
2522 "not allowed.");
2523 return -1;
2526 return 0;
2529 /** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
2530 * will require us to rotate the cpu and dns workers; else return 0. */
2531 static int
2532 options_transition_affects_workers(or_options_t *old_options,
2533 or_options_t *new_options)
2535 if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) ||
2536 old_options->NumCpus != new_options->NumCpus ||
2537 old_options->ORPort != new_options->ORPort ||
2538 old_options->SafeLogging != new_options->SafeLogging ||
2539 !config_lines_eq(old_options->Logs, new_options->Logs))
2540 return 1;
2542 /* Check whether log options match. */
2544 /* Nothing that changed matters. */
2545 return 0;
2548 /** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
2549 * will require us to generate a new descriptor; else return 0. */
2550 static int
2551 options_transition_affects_descriptor(or_options_t *old_options,
2552 or_options_t *new_options)
2554 if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) ||
2555 !opt_streq(old_options->Nickname,new_options->Nickname) ||
2556 !opt_streq(old_options->Address,new_options->Address) ||
2557 !config_lines_eq(old_options->ExitPolicy,new_options->ExitPolicy) ||
2558 old_options->ORPort != new_options->ORPort ||
2559 old_options->DirPort != new_options->DirPort ||
2560 old_options->ClientOnly != new_options->ClientOnly ||
2561 old_options->NoPublish != new_options->NoPublish ||
2562 old_options->PublishServerDescriptor !=
2563 new_options->PublishServerDescriptor ||
2564 old_options->BandwidthRate != new_options->BandwidthRate ||
2565 old_options->BandwidthBurst != new_options->BandwidthBurst ||
2566 !opt_streq(old_options->ContactInfo, new_options->ContactInfo) ||
2567 !opt_streq(old_options->MyFamily, new_options->MyFamily) ||
2568 !opt_streq(old_options->AccountingStart, new_options->AccountingStart) ||
2569 old_options->AccountingMax != new_options->AccountingMax)
2570 return 1;
2572 return 0;
2575 #ifdef MS_WINDOWS
2576 /** Return the directory on windows where we expect to find our application
2577 * data. */
2578 static char *
2579 get_windows_conf_root(void)
2581 static int is_set = 0;
2582 static char path[MAX_PATH+1];
2584 LPITEMIDLIST idl;
2585 IMalloc *m;
2586 HRESULT result;
2588 if (is_set)
2589 return path;
2591 /* Find X:\documents and settings\username\application data\ .
2592 * We would use SHGetSpecialFolder path, but that wasn't added until IE4.
2594 if (!SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA,
2595 &idl))) {
2596 GetCurrentDirectory(MAX_PATH, path);
2597 is_set = 1;
2598 log_warn(LD_CONFIG,
2599 "I couldn't find your application data folder: are you "
2600 "running an ancient version of Windows 95? Defaulting to \"%s\"",
2601 path);
2602 return path;
2604 /* Convert the path from an "ID List" (whatever that is!) to a path. */
2605 result = SHGetPathFromIDList(idl, path);
2606 /* Now we need to free the */
2607 SHGetMalloc(&m);
2608 if (m) {
2609 m->lpVtbl->Free(m, idl);
2610 m->lpVtbl->Release(m);
2612 if (!SUCCEEDED(result)) {
2613 return NULL;
2615 strlcat(path,"\\tor",MAX_PATH);
2616 is_set = 1;
2617 return path;
2619 #endif
2621 /** Return the default location for our torrc file. */
2622 static const char *
2623 get_default_conf_file(void)
2625 #ifdef MS_WINDOWS
2626 static char path[MAX_PATH+1];
2627 strlcpy(path, get_windows_conf_root(), MAX_PATH);
2628 strlcat(path,"\\torrc",MAX_PATH);
2629 return path;
2630 #else
2631 return (CONFDIR "/torrc");
2632 #endif
2635 /** Verify whether lst is a string containing valid-looking space-separated
2636 * nicknames, or NULL. Return 0 on success. Warn and return -1 on failure.
2638 static int
2639 check_nickname_list(const char *lst, const char *name, char **msg)
2641 int r = 0;
2642 smartlist_t *sl;
2644 if (!lst)
2645 return 0;
2646 sl = smartlist_create();
2647 smartlist_split_string(sl, lst, ",", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
2648 SMARTLIST_FOREACH(sl, const char *, s,
2650 if (!is_legal_nickname_or_hexdigest(s)) {
2651 char buf[1024];
2652 int tmp = tor_snprintf(buf, sizeof(buf),
2653 "Invalid nickname '%s' in %s line", s, name);
2654 *msg = tor_strdup(tmp >= 0 ? buf : "internal error");
2655 r = -1;
2656 break;
2659 SMARTLIST_FOREACH(sl, char *, s, tor_free(s));
2660 smartlist_free(sl);
2661 return r;
2664 /** Read a configuration file into <b>options</b>, finding the configuration
2665 * file location based on the command line. After loading the options,
2666 * validate them for consistency, then take actions based on them.
2667 * Return 0 if success, -1 if failure. */
2669 options_init_from_torrc(int argc, char **argv)
2671 or_options_t *oldoptions, *newoptions;
2672 config_line_t *cl;
2673 char *cf=NULL, *fname=NULL, *errmsg=NULL;
2674 int i, retval;
2675 int using_default_torrc;
2676 static char **backup_argv;
2677 static int backup_argc;
2679 if (argv) { /* first time we're called. save commandline args */
2680 backup_argv = argv;
2681 backup_argc = argc;
2682 oldoptions = NULL;
2683 } else { /* we're reloading. need to clean up old options first. */
2684 argv = backup_argv;
2685 argc = backup_argc;
2686 oldoptions = get_options();
2688 if (argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1],"--help"))) {
2689 print_usage();
2690 exit(0);
2693 if (argc > 1 && (!strcmp(argv[1],"--version"))) {
2694 printf("Tor version %s.\n",VERSION);
2695 if (argc > 2 && (!strcmp(argv[2],"--version"))) {
2696 print_cvs_version();
2698 exit(0);
2701 newoptions = tor_malloc_zero(sizeof(or_options_t));
2702 newoptions->_magic = OR_OPTIONS_MAGIC;
2703 options_init(newoptions);
2705 /* learn config file name */
2706 fname = NULL;
2707 using_default_torrc = 1;
2708 newoptions->command = CMD_RUN_TOR;
2709 for (i = 1; i < argc; ++i) {
2710 if (i < argc-1 && !strcmp(argv[i],"-f")) {
2711 if (fname) {
2712 log(LOG_WARN, LD_CONFIG, "Duplicate -f options on command line.");
2713 tor_free(fname);
2715 fname = tor_strdup(argv[i+1]);
2716 using_default_torrc = 0;
2717 ++i;
2718 } else if (!strcmp(argv[i],"--list-fingerprint")) {
2719 newoptions->command = CMD_LIST_FINGERPRINT;
2720 } else if (!strcmp(argv[i],"--hash-password")) {
2721 newoptions->command = CMD_HASH_PASSWORD;
2722 newoptions->command_arg = tor_strdup( (i < argc-1) ? argv[i+1] : "");
2723 ++i;
2724 } else if (!strcmp(argv[i],"--verify-config")) {
2725 newoptions->command = CMD_VERIFY_CONFIG;
2728 if (using_default_torrc) {
2729 /* didn't find one, try CONFDIR */
2730 const char *dflt = get_default_conf_file();
2731 char *fn = NULL;
2732 if (dflt && file_status(dflt) == FN_FILE) {
2733 fname = tor_strdup(dflt);
2734 } else {
2735 #ifndef MS_WINDOWS
2736 fn = expand_filename("~/.torrc");
2737 if (fn && file_status(fn) == FN_FILE) {
2738 fname = fn;
2739 } else {
2740 tor_free(fn);
2741 fname = tor_strdup(dflt);
2743 #else
2744 fname = tor_strdup(dflt);
2745 #endif
2748 tor_assert(fname);
2749 log(LOG_DEBUG, LD_CONFIG, "Opening config file \"%s\"", fname);
2751 tor_free(torrc_fname);
2752 torrc_fname = fname;
2754 /* get config lines, assign them */
2755 if (file_status(fname) != FN_FILE ||
2756 !(cf = read_file_to_str(fname,0))) {
2757 if (using_default_torrc == 1) {
2758 log(LOG_NOTICE, LD_CONFIG, "Configuration file \"%s\" not present, "
2759 "using reasonable defaults.", fname);
2760 tor_free(fname); /* sets fname to NULL */
2761 torrc_fname = NULL;
2762 } else {
2763 log(LOG_WARN, LD_CONFIG,
2764 "Unable to open configuration file \"%s\".", fname);
2765 goto err;
2767 } else { /* it opened successfully. use it. */
2768 retval = config_get_lines(cf, &cl);
2769 tor_free(cf);
2770 if (retval < 0)
2771 goto err;
2772 retval = config_assign(&options_format, newoptions, cl, 0, 0, &errmsg);
2773 config_free_lines(cl);
2774 if (retval < 0)
2775 goto err;
2778 /* Go through command-line variables too */
2779 if (config_get_commandlines(argc, argv, &cl) < 0)
2780 goto err;
2781 retval = config_assign(&options_format, newoptions, cl, 0, 0, &errmsg);
2782 config_free_lines(cl);
2783 if (retval < 0)
2784 goto err;
2786 /* Validate newoptions */
2787 if (options_validate(oldoptions, newoptions, 0, &errmsg) < 0)
2788 goto err;
2790 if (options_transition_allowed(oldoptions, newoptions, &errmsg) < 0)
2791 goto err;
2793 if (set_options(newoptions, &errmsg))
2794 goto err; /* frees and replaces old options */
2796 return 0;
2797 err:
2798 tor_free(fname);
2799 torrc_fname = NULL;
2800 config_free(&options_format, newoptions);
2801 if (errmsg) {
2802 log(LOG_WARN,LD_CONFIG,"Failed to parse/validate config: %s", errmsg);
2803 tor_free(errmsg);
2805 return -1;
2808 /** Return the location for our configuration file.
2810 const char *
2811 get_torrc_fname(void)
2813 if (torrc_fname)
2814 return torrc_fname;
2815 else
2816 return get_default_conf_file();
2819 /** Adjust the address map mased on the MapAddress elements in the
2820 * configuration <b>options</b>
2822 static void
2823 config_register_addressmaps(or_options_t *options)
2825 smartlist_t *elts;
2826 config_line_t *opt;
2827 char *from, *to;
2829 addressmap_clear_configured();
2830 elts = smartlist_create();
2831 for (opt = options->AddressMap; opt; opt = opt->next) {
2832 smartlist_split_string(elts, opt->value, NULL,
2833 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
2834 if (smartlist_len(elts) >= 2) {
2835 from = smartlist_get(elts,0);
2836 to = smartlist_get(elts,1);
2837 if (!is_plausible_address(from)) {
2838 log_warn(LD_CONFIG,
2839 "Skipping invalid argument '%s' to MapAddress", from);
2840 } else if (!is_plausible_address(to)) {
2841 log_warn(LD_CONFIG,
2842 "Skipping invalid argument '%s' to MapAddress", to);
2843 } else {
2844 addressmap_register(from, tor_strdup(to), 0);
2845 if (smartlist_len(elts)>2) {
2846 log_warn(LD_CONFIG,"Ignoring extra arguments to MapAddress.");
2849 } else {
2850 log_warn(LD_CONFIG,"MapAddress '%s' has too few arguments. Ignoring.",
2851 opt->value);
2853 SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp));
2854 smartlist_clear(elts);
2856 smartlist_free(elts);
2859 /** If <b>range</b> is of the form MIN-MAX, for MIN and MAX both
2860 * recognized log severity levels, set *<b>min_out</b> to MIN and
2861 * *<b>max_out</b> to MAX and return 0. Else, if <b>range</b> is of
2862 * the form MIN, act as if MIN-err had been specified. Else, warn and
2863 * return -1.
2865 static int
2866 parse_log_severity_range(const char *range, int *min_out, int *max_out)
2868 int levelMin, levelMax;
2869 const char *cp;
2870 cp = strchr(range, '-');
2871 if (cp) {
2872 if (cp == range) {
2873 levelMin = LOG_DEBUG;
2874 } else {
2875 char *tmp_sev = tor_strndup(range, cp - range);
2876 levelMin = parse_log_level(tmp_sev);
2877 if (levelMin < 0) {
2878 log_warn(LD_CONFIG, "Unrecognized log severity '%s': must be one of "
2879 "err|warn|notice|info|debug", tmp_sev);
2880 tor_free(tmp_sev);
2881 return -1;
2883 tor_free(tmp_sev);
2885 if (!*(cp+1)) {
2886 levelMax = LOG_ERR;
2887 } else {
2888 levelMax = parse_log_level(cp+1);
2889 if (levelMax < 0) {
2890 log_warn(LD_CONFIG, "Unrecognized log severity '%s': must be one of "
2891 "err|warn|notice|info|debug", cp+1);
2892 return -1;
2895 } else {
2896 levelMin = parse_log_level(range);
2897 if (levelMin < 0) {
2898 log_warn(LD_CONFIG, "Unrecognized log severity '%s': must be one of "
2899 "err|warn|notice|info|debug", range);
2900 return -1;
2902 levelMax = LOG_ERR;
2905 *min_out = levelMin;
2906 *max_out = levelMax;
2908 return 0;
2911 /** Try to convert a pair of old-style logging options [LogLevel, and
2912 * (LogFile/Syslog)] to a new-style option, and add the new option to
2913 * options->Logs. */
2914 static int
2915 convert_log_option(or_options_t *options, config_line_t *level_opt,
2916 config_line_t *file_opt, int isDaemon)
2918 int levelMin = -1, levelMax = -1;
2920 if (level_opt) {
2921 if (parse_log_severity_range(level_opt->value, &levelMin, &levelMax))
2922 return -1;
2924 if (levelMin < 0 && levelMax < 0) {
2925 levelMin = LOG_NOTICE;
2926 levelMax = LOG_ERR;
2927 } else if (levelMin < 0) {
2928 levelMin = levelMax;
2929 } else {
2930 levelMax = LOG_ERR;
2933 if (file_opt && !strcasecmp(file_opt->key, "LogFile")) {
2934 if (add_single_log_option(options, levelMin, levelMax, "file",
2935 file_opt->value) < 0) {
2936 log_warn(LD_FS, "Cannot write to LogFile \"%s\": %s.", file_opt->value,
2937 strerror(errno));
2938 return -1;
2940 } else if (file_opt && !strcasecmp(file_opt->key, "SysLog")) {
2941 if (add_single_log_option(options, levelMin, levelMax, "syslog", NULL) < 0)
2942 return -1;
2943 } else if (!isDaemon) {
2944 add_single_log_option(options, levelMin, levelMax, "stdout", NULL);
2946 return 0;
2950 * Initialize the logs based on the configuration file.
2953 options_init_logs(or_options_t *options, int validate_only)
2955 config_line_t *opt;
2956 int ok;
2957 smartlist_t *elts;
2958 int daemon = options->RunAsDaemon;
2960 ok = 1;
2961 elts = smartlist_create();
2963 for (opt = options->Logs; opt; opt = opt->next) {
2964 int levelMin=LOG_DEBUG, levelMax=LOG_ERR;
2965 smartlist_split_string(elts, opt->value, NULL,
2966 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
2967 if (smartlist_len(elts) == 0) {
2968 log_warn(LD_CONFIG, "Bad syntax on Log option 'Log %s'", opt->value);
2969 ok = 0; goto cleanup;
2971 if (parse_log_severity_range(smartlist_get(elts,0), &levelMin,
2972 &levelMax)) {
2973 ok = 0; goto cleanup;
2975 if (smartlist_len(elts) < 2) { /* only loglevels were provided */
2976 if (!validate_only) {
2977 if (daemon) {
2978 log_warn(LD_CONFIG,
2979 "Can't log to stdout with RunAsDaemon set; skipping stdout");
2980 } else {
2981 add_stream_log(levelMin, levelMax, "<stdout>", stdout);
2984 goto cleanup;
2986 if (!strcasecmp(smartlist_get(elts,1), "file")) {
2987 if (smartlist_len(elts) != 3) {
2988 log_warn(LD_CONFIG, "Bad syntax on Log option 'Log %s'", opt->value);
2989 ok = 0; goto cleanup;
2991 if (!validate_only) {
2992 if (add_file_log(levelMin, levelMax, smartlist_get(elts, 2)) < 0) {
2993 log_warn(LD_CONFIG, "Couldn't open file for 'Log %s'", opt->value);
2994 ok = 0;
2997 goto cleanup;
2999 if (smartlist_len(elts) != 2) {
3000 log_warn(LD_CONFIG, "Bad syntax on Log option 'Log %s'", opt->value);
3001 ok = 0; goto cleanup;
3003 if (!strcasecmp(smartlist_get(elts,1), "stdout")) {
3004 if (daemon) {
3005 log_warn(LD_CONFIG, "Can't log to stdout with RunAsDaemon set.");
3006 ok = 0; goto cleanup;
3008 if (!validate_only) {
3009 add_stream_log(levelMin, levelMax, "<stdout>", stdout);
3011 } else if (!strcasecmp(smartlist_get(elts,1), "stderr")) {
3012 if (daemon) {
3013 log_warn(LD_CONFIG, "Can't log to stderr with RunAsDaemon set.");
3014 ok = 0; goto cleanup;
3016 if (!validate_only) {
3017 add_stream_log(levelMin, levelMax, "<stderr>", stderr);
3019 } else if (!strcasecmp(smartlist_get(elts,1), "syslog")) {
3020 #ifdef HAVE_SYSLOG_H
3021 if (!validate_only)
3022 add_syslog_log(levelMin, levelMax);
3023 #else
3024 log_warn(LD_CONFIG, "Syslog is not supported in this compilation.");
3025 #endif
3026 } else {
3027 log_warn(LD_CONFIG, "Unrecognized log type %s",
3028 (const char*)smartlist_get(elts,1));
3029 if (strchr(smartlist_get(elts,1), '/') ||
3030 strchr(smartlist_get(elts,1), '\\')) {
3031 log_warn(LD_CONFIG, "Did you mean to say 'Log file %s' ?",
3032 (const char *)smartlist_get(elts,1));
3034 ok = 0; goto cleanup;
3036 cleanup:
3037 SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp));
3038 smartlist_clear(elts);
3040 smartlist_free(elts);
3042 return ok?0:-1;
3045 /** Add a single option of the form Log min-max \<type\> [fname] to options. */
3046 static int
3047 add_single_log_option(or_options_t *options, int minSeverity, int maxSeverity,
3048 const char *type, const char *fname)
3050 char *buf;
3051 size_t len;
3053 len = 256 + fname?strlen(fname):0;
3054 buf = tor_malloc(len);
3056 if (tor_snprintf(buf, len, "%s%s%s %s%s%s",
3057 log_level_to_string(minSeverity),
3058 maxSeverity == LOG_ERR ? "" : "-",
3059 maxSeverity == LOG_ERR ? "" : log_level_to_string(maxSeverity),
3060 type, fname?" ":"", fname?fname:"")<0) {
3061 log_warn(LD_BUG, "Normalized log option too long.");
3062 tor_free(buf);
3063 return -1;
3066 log(LOG_WARN, LD_CONFIG, "The old LogLevel/LogFile/DebugLogFile/SysLog "
3067 "options are deprecated, and will go away soon. Your new torrc line "
3068 "should be: 'Log %s'", buf);
3069 config_line_append(&options->Logs, "Log", buf);
3070 tor_free(buf);
3071 return 0;
3074 /** Convert all old-style logging options to new-style Log options. Return 0
3075 * on success, -1 on failure. */
3076 static int
3077 normalize_log_options(or_options_t *options)
3079 /* The order of options is: Level? (File Level?)+
3081 config_line_t *opt = options->OldLogOptions;
3083 /* Special case for if first option is LogLevel. */
3084 if (opt && !strcasecmp(opt->key, "LogLevel")) {
3085 if (opt->next && (!strcasecmp(opt->next->key, "LogFile") ||
3086 !strcasecmp(opt->next->key, "SysLog"))) {
3087 if (convert_log_option(options, opt, opt->next, options->RunAsDaemon)< 0)
3088 return -1;
3089 opt = opt->next->next;
3090 } else if (!opt->next) {
3091 if (convert_log_option(options, opt, NULL, options->RunAsDaemon) < 0)
3092 return -1;
3093 opt = opt->next;
3094 } else {
3095 ; /* give warning below */
3099 while (opt) {
3100 if (!strcasecmp(opt->key, "LogLevel")) {
3101 log_warn(LD_CONFIG, "Two LogLevel options in a row without "
3102 "intervening LogFile or SysLog");
3103 opt = opt->next;
3104 } else {
3105 tor_assert(!strcasecmp(opt->key, "LogFile") ||
3106 !strcasecmp(opt->key, "SysLog"));
3107 if (opt->next && !strcasecmp(opt->next->key, "LogLevel")) {
3108 /* LogFile/SysLog followed by LogLevel */
3109 if (convert_log_option(options,opt->next,opt, options->RunAsDaemon) <0)
3110 return -1;
3111 opt = opt->next->next;
3112 } else {
3113 /* LogFile/SysLog followed by LogFile/SysLog or end of list. */
3114 if (convert_log_option(options,NULL, opt, options->RunAsDaemon) < 0)
3115 return -1;
3116 opt = opt->next;
3121 if (options->DebugLogFile) {
3122 if (add_single_log_option(options, LOG_DEBUG, LOG_ERR, "file",
3123 options->DebugLogFile) < 0)
3124 return -1;
3127 tor_free(options->DebugLogFile);
3128 config_free_lines(options->OldLogOptions);
3129 options->OldLogOptions = NULL;
3131 return 0;
3134 /** Parse a single RedirectExit line's contents from <b>line</b>. If
3135 * they are valid, and <b>result</b> is not NULL, add an element to
3136 * <b>result</b> and return 0. Else if they are valid, return 0.
3137 * Else set *msg and return -1. */
3138 static int
3139 parse_redirect_line(smartlist_t *result, config_line_t *line, char **msg)
3141 smartlist_t *elements = NULL;
3142 exit_redirect_t *r;
3144 tor_assert(line);
3146 r = tor_malloc_zero(sizeof(exit_redirect_t));
3147 elements = smartlist_create();
3148 smartlist_split_string(elements, line->value, NULL,
3149 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
3150 if (smartlist_len(elements) != 2) {
3151 *msg = tor_strdup("Wrong number of elements in RedirectExit line");
3152 goto err;
3154 if (parse_addr_and_port_range(smartlist_get(elements,0),&r->addr,&r->mask,
3155 &r->port_min,&r->port_max)) {
3156 *msg = tor_strdup("Error parsing source address in RedirectExit line");
3157 goto err;
3159 if (0==strcasecmp(smartlist_get(elements,1), "pass")) {
3160 r->is_redirect = 0;
3161 } else {
3162 if (parse_addr_port(smartlist_get(elements,1),NULL,&r->addr_dest,
3163 &r->port_dest)) {
3164 *msg = tor_strdup("Error parsing dest address in RedirectExit line");
3165 goto err;
3167 r->is_redirect = 1;
3170 goto done;
3171 err:
3172 tor_free(r);
3173 done:
3174 SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
3175 smartlist_free(elements);
3176 if (r) {
3177 if (result)
3178 smartlist_add(result, r);
3179 else
3180 tor_free(r);
3181 return 0;
3182 } else {
3183 tor_assert(*msg);
3184 return -1;
3188 /** Read the contents of a DirServer line from <b>line</b>. Return 0
3189 * if the line is well-formed, and -1 if it isn't. If
3190 * <b>validate_only</b> is 0, and the line is well-formed, then add
3191 * the dirserver described in the line as a valid server. */
3192 static int
3193 parse_dir_server_line(const char *line, int validate_only)
3195 smartlist_t *items = NULL;
3196 int r, idx;
3197 char *addrport=NULL, *address=NULL, *nickname=NULL, *fingerprint=NULL;
3198 uint16_t port;
3199 char digest[DIGEST_LEN];
3200 int is_v1_authority = 0;
3202 items = smartlist_create();
3203 smartlist_split_string(items, line, NULL,
3204 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
3205 if (smartlist_len(items) < 2) {
3206 log_warn(LD_CONFIG, "Too few arguments to DirServer line.");
3207 goto err;
3210 idx = 0;
3211 if (is_legal_nickname(smartlist_get(items, 0))) {
3212 nickname = smartlist_get(items, 0);
3213 smartlist_del_keeporder(items, 0);
3216 if (!strcmp(smartlist_get(items, 0), "v1")) {
3217 char *v1 = smartlist_get(items, 0);
3218 tor_free(v1);
3219 is_v1_authority = 1;
3220 smartlist_del_keeporder(items, 0);
3223 if (smartlist_len(items) < 2) {
3224 log_warn(LD_CONFIG, "Too few arguments to DirServer line.");
3225 goto err;
3227 addrport = smartlist_get(items, 0);
3228 if (parse_addr_port(addrport, &address, NULL, &port)<0) {
3229 log_warn(LD_CONFIG, "Error parsing DirServer address '%s'", addrport);
3230 goto err;
3232 if (!port) {
3233 log_warn(LD_CONFIG, "Missing port in DirServer address '%s'",addrport);
3234 goto err;
3236 smartlist_del_keeporder(items, 0);
3238 fingerprint = smartlist_join_strings(items, "", 0, NULL);
3239 if (strlen(fingerprint) != HEX_DIGEST_LEN) {
3240 log_warn(LD_CONFIG, "Key digest for DirServer is wrong length.");
3241 goto err;
3243 if (base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN)<0) {
3244 log_warn(LD_CONFIG, "Unable to decode DirServer key digest.");
3245 goto err;
3248 if (!validate_only) {
3249 log_debug(LD_DIR, "Trusted dirserver at %s:%d (%s)", address, (int)port,
3250 (char*)smartlist_get(items,1));
3251 add_trusted_dir_server(nickname, address, port, digest, is_v1_authority);
3254 r = 0;
3255 goto done;
3257 err:
3258 r = -1;
3260 done:
3261 SMARTLIST_FOREACH(items, char*, s, tor_free(s));
3262 smartlist_free(items);
3263 tor_free(addrport);
3264 tor_free(address);
3265 tor_free(nickname);
3266 tor_free(fingerprint);
3267 return r;
3270 /** Adjust the value of options->DataDirectory, or fill it in if it's
3271 * absent. Return 0 on success, -1 on failure. */
3272 static int
3273 normalize_data_directory(or_options_t *options)
3275 #ifdef MS_WINDOWS
3276 char *p;
3277 if (options->DataDirectory)
3278 return 0; /* all set */
3279 p = tor_malloc(MAX_PATH);
3280 strlcpy(p,get_windows_conf_root(),MAX_PATH);
3281 options->DataDirectory = p;
3282 return 0;
3283 #else
3284 const char *d = options->DataDirectory;
3285 if (!d)
3286 d = "~/.tor";
3288 if (strncmp(d,"~/",2) == 0) {
3289 char *fn = expand_filename(d);
3290 if (!fn) {
3291 log_err(LD_CONFIG,"Failed to expand filename \"%s\".", d);
3292 return -1;
3294 if (!options->DataDirectory && !strcmp(fn,"/.tor")) {
3295 /* If our homedir is /, we probably don't want to use it. */
3296 /* XXXX Default to /var/lib/tor? */
3297 log_warn(LD_CONFIG,
3298 "Default DataDirectory is \"~/.tor\". This expands to "
3299 "\"%s\", which is probably not what you want. Using \"%s/tor\" "
3300 "instead", fn, LOCALSTATEDIR);
3301 tor_free(fn);
3302 fn = tor_strdup(LOCALSTATEDIR"/tor");
3305 tor_free(options->DataDirectory);
3306 options->DataDirectory = fn;
3308 return 0;
3309 #endif
3312 /** Check and normalize the value of options->DataDirectory; return 0 if it
3313 * sane, -1 otherwise. */
3314 static int
3315 validate_data_directory(or_options_t *options)
3317 if (normalize_data_directory(options) < 0)
3318 return -1;
3319 tor_assert(options->DataDirectory);
3320 if (strlen(options->DataDirectory) > (512-128)) {
3321 log_err(LD_CONFIG, "DataDirectory is too long.");
3322 return -1;
3324 return 0;
3327 /** This string must remain the same forevermore. It is how we
3328 * recognize that the torrc file doesn't need to be backed up. */
3329 #define GENERATED_FILE_PREFIX "# This file was generated by Tor; " \
3330 "if you edit it, comments will not be preserved"
3331 /** This string can change; it tries to give the reader an idea
3332 * that editing this file by hand is not a good plan. */
3333 #define GENERATED_FILE_COMMENT "# If you want a config file with " \
3334 "comments, look for torrc.orig.1 or similar"
3336 /** Save a configuration file for the configuration in <b>options</b>
3337 * into the file <b>fname</b>. If the file already exists, and
3338 * doesn't begin with GENERATED_FILE_PREFIX, rename it. Otherwise
3339 * replace it. Return 0 on success, -1 on failure. */
3340 static int
3341 write_configuration_file(const char *fname, or_options_t *options)
3343 char *old_val=NULL, *new_val=NULL, *new_conf=NULL;
3344 int rename_old = 0, r;
3345 size_t len;
3347 if (fname) {
3348 switch (file_status(fname)) {
3349 case FN_FILE:
3350 old_val = read_file_to_str(fname, 0);
3351 if (strcmpstart(old_val, GENERATED_FILE_PREFIX)) {
3352 rename_old = 1;
3354 tor_free(old_val);
3355 break;
3356 case FN_NOENT:
3357 break;
3358 default:
3359 log_warn(LD_CONFIG,
3360 "Config file \"%s\" is not a file? Failing.", fname);
3361 return -1;
3365 if (!(new_conf = options_dump(options, 1))) {
3366 log_warn(LD_BUG, "Couldn't get configuration string");
3367 goto err;
3370 len = strlen(new_conf)+256;
3371 new_val = tor_malloc(len);
3372 tor_snprintf(new_val, len, "%s\n%s\n\n%s",
3373 GENERATED_FILE_PREFIX, GENERATED_FILE_COMMENT, new_conf);
3375 if (rename_old) {
3376 int i = 1;
3377 size_t fn_tmp_len = strlen(fname)+32;
3378 char *fn_tmp;
3379 tor_assert(fn_tmp_len > strlen(fname)); /*check for overflow*/
3380 fn_tmp = tor_malloc(fn_tmp_len);
3381 while (1) {
3382 if (tor_snprintf(fn_tmp, fn_tmp_len, "%s.orig.%d", fname, i)<0) {
3383 log_warn(LD_BUG, "tor_snprintf failed inexplicably");
3384 tor_free(fn_tmp);
3385 goto err;
3387 if (file_status(fn_tmp) == FN_NOENT)
3388 break;
3389 ++i;
3391 log_notice(LD_CONFIG, "Renaming old configuration file to \"%s\"", fn_tmp);
3392 if (rename(fname, fn_tmp) < 0) {
3393 log_warn(LD_FS, "Couldn't rename \"%s\" to \"%s\": %s",
3394 fname, fn_tmp, strerror(errno));
3395 tor_free(fn_tmp);
3396 goto err;
3398 tor_free(fn_tmp);
3401 if (write_str_to_file(fname, new_val, 0) < 0)
3402 goto err;
3404 r = 0;
3405 goto done;
3406 err:
3407 r = -1;
3408 done:
3409 tor_free(new_val);
3410 tor_free(new_conf);
3411 return r;
3415 * Save the current configuration file value to disk. Return 0 on
3416 * success, -1 on failure.
3419 options_save_current(void)
3421 if (torrc_fname) {
3422 /* XXX This fails if we can't write to our configuration file.
3423 * Arguably, we should try falling back to datadirectory or something.
3424 * But just as arguably, we shouldn't. */
3425 return write_configuration_file(torrc_fname, get_options());
3427 return write_configuration_file(get_default_conf_file(), get_options());
3430 /** Mapping from a unit name to a multiplier for converting that unit into a
3431 * base unit. */
3432 struct unit_table_t {
3433 const char *unit;
3434 uint64_t multiplier;
3437 static struct unit_table_t memory_units[] = {
3438 { "", 1 },
3439 { "b", 1<< 0 },
3440 { "byte", 1<< 0 },
3441 { "bytes", 1<< 0 },
3442 { "kb", 1<<10 },
3443 { "kilobyte", 1<<10 },
3444 { "kilobytes", 1<<10 },
3445 { "m", 1<<20 },
3446 { "mb", 1<<20 },
3447 { "megabyte", 1<<20 },
3448 { "megabytes", 1<<20 },
3449 { "gb", 1<<30 },
3450 { "gigabyte", 1<<30 },
3451 { "gigabytes", 1<<30 },
3452 { "tb", U64_LITERAL(1)<<40 },
3453 { "terabyte", U64_LITERAL(1)<<40 },
3454 { "terabytes", U64_LITERAL(1)<<40 },
3455 { NULL, 0 },
3458 static struct unit_table_t time_units[] = {
3459 { "", 1 },
3460 { "second", 1 },
3461 { "seconds", 1 },
3462 { "minute", 60 },
3463 { "minutes", 60 },
3464 { "hour", 60*60 },
3465 { "hours", 60*60 },
3466 { "day", 24*60*60 },
3467 { "days", 24*60*60 },
3468 { "week", 7*24*60*60 },
3469 { "weeks", 7*24*60*60 },
3470 { NULL, 0 },
3473 /** Parse a string <b>val</b> containing a number, zero or more
3474 * spaces, and an optional unit string. If the unit appears in the
3475 * table <b>u</b>, then multiply the number by the unit multiplier.
3476 * On success, set *<b>ok</b> to 1 and return this product.
3477 * Otherwise, set *<b>ok</b> to 0.
3479 static uint64_t
3480 config_parse_units(const char *val, struct unit_table_t *u, int *ok)
3482 uint64_t v;
3483 char *cp;
3485 tor_assert(ok);
3487 v = tor_parse_uint64(val, 10, 0, UINT64_MAX, ok, &cp);
3488 if (!*ok)
3489 return 0;
3490 if (!cp) {
3491 *ok = 1;
3492 return v;
3494 while (TOR_ISSPACE(*cp))
3495 ++cp;
3496 for ( ;u->unit;++u) {
3497 if (!strcasecmp(u->unit, cp)) {
3498 v *= u->multiplier;
3499 *ok = 1;
3500 return v;
3503 log_warn(LD_CONFIG, "Unknown unit '%s'.", cp);
3504 *ok = 0;
3505 return 0;
3508 /** Parse a string in the format "number unit", where unit is a unit of
3509 * information (byte, KB, M, etc). On success, set *<b>ok</b> to true
3510 * and return the number of bytes specified. Otherwise, set
3511 * *<b>ok</b> to false and return 0. */
3512 static uint64_t
3513 config_parse_memunit(const char *s, int *ok)
3515 return config_parse_units(s, memory_units, ok);
3518 /** Parse a string in the format "number unit", where unit is a unit of time.
3519 * On success, set *<b>ok</b> to true and return the number of seconds in
3520 * the provided interval. Otherwise, set *<b>ok</b> to 0 and return -1.
3522 static int
3523 config_parse_interval(const char *s, int *ok)
3525 uint64_t r;
3526 r = config_parse_units(s, time_units, ok);
3527 if (!ok)
3528 return -1;
3529 if (r > INT_MAX) {
3530 log_warn(LD_CONFIG, "Interval '%s' is too long", s);
3531 *ok = 0;
3532 return -1;
3534 return (int)r;
3538 * Initialize the libevent library.
3540 static void
3541 init_libevent(void)
3543 configure_libevent_logging();
3544 /* If the kernel complains that some method (say, epoll) doesn't
3545 * exist, we don't care about it, since libevent will cope.
3547 suppress_libevent_log_msg("Function not implemented");
3548 #ifdef __APPLE__
3549 setenv("EVENT_NOKQUEUE","1",1);
3550 #endif
3551 event_init();
3552 suppress_libevent_log_msg(NULL);
3553 #if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
3554 /* Making this a NOTICE for now so we can link bugs to a libevent versions
3555 * or methods better. */
3556 log(LOG_NOTICE, LD_GENERAL,
3557 "Initialized libevent version %s using method %s. Good.",
3558 event_get_version(), event_get_method());
3559 check_libevent_version(event_get_method(), event_get_version(),
3560 get_options()->ORPort != 0);
3561 #else
3562 log(LOG_NOTICE, LD_GENERAL,
3563 "Initialized old libevent (version 1.0b or earlier).");
3564 log(LOG_WARN, LD_GENERAL,
3565 "You have a very old version of libevent. It is likely to be buggy; "
3566 "please consider building Tor with a more recent version.");
3567 #endif
3570 #if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD)
3572 * Compare the given libevent method and version to a list of versions
3573 * which are known not to work. Warn the user as appropriate.
3576 static void
3577 check_libevent_version(const char *m, const char *v, int server)
3579 int buggy = 0, iffy = 0, slow = 0;
3581 tor_assert(m && v);
3583 if (!strcmp(m, "kqueue")) {
3584 if (!strcmp(v, "1.0c") || !strcmp(v, "1.0d") || !strcmp(v, "1.0e") ||
3585 !strcmp(v, "1.1")) {
3586 buggy = 1;
3588 } else if (!strcmp(m, "epoll")) {
3589 if (!strcmp(v, "1.0c") || !strcmp(v, "1.0d") || !strcmp(v, "1.0e"))
3590 iffy = 1;
3591 } else if (!strcmp(m, "poll")) {
3592 if (!strcmp(v, "1.0c") || !strcmp(v, "1.0d"))
3593 buggy = 1;
3594 else if (!strcmp(v, "1.0e"))
3595 slow = 1;
3596 } else if (!strcmp(m, "poll")) {
3597 if (!strcmp(v, "1.0c") || !strcmp(v, "1.0d") || !strcmp(v, "1.0e"))
3598 slow = 1;
3601 if (buggy) {
3602 log(LOG_WARN, LD_GENERAL,
3603 "There are known bugs in using %s with libevent %s. "
3604 "Please use the latest version of libevent.", m, v);
3605 } else if (iffy) {
3606 log(LOG_WARN, LD_GENERAL,
3607 "There are minor bugs in using %s with libevent %s. "
3608 "You may want to use the latest version of libevent.", m, v);
3609 } else if (slow && server) {
3610 log(LOG_WARN, LD_GENERAL,
3611 "libevent %s can be very slow with %s. "
3612 "When running a server, please use the latest version of libevent.",
3613 v,m);
3617 #endif
3619 /** Return the persistent state struct for this Tor. */
3620 or_state_t *
3621 get_or_state(void)
3623 return global_state;
3626 /** Return the filename used to write and read the persistent state. */
3627 static char *
3628 get_or_state_fname(void)
3630 char *fname = NULL;
3631 or_options_t *options = get_options();
3632 size_t len = strlen(options->DataDirectory) + 16;
3633 fname = tor_malloc(len);
3634 tor_snprintf(fname, len, "%s/state", options->DataDirectory);
3635 return fname;
3638 /** Return 0 if every setting in <b>state</b> is reasonable, and a
3639 * permissible transition from <b>old_state</b>. Else warn and return -1.
3640 * Should have no side effects, except for normalizing the contents of
3641 * <b>state</b>.
3643 /* XXX from_setconf is here because of bug 238 */
3644 static int
3645 or_state_validate(or_state_t *old_state, or_state_t *state,
3646 int from_setconf, char **msg)
3648 if (entry_guards_parse_state(state, 0, msg)<0) {
3649 return -1;
3651 if (state->TorVersion) {
3652 tor_version_t v;
3653 if (tor_version_parse(state->TorVersion, &v)) {
3654 log_warn(LD_GENERAL, "Can't parse Tor version '%s' from your state "
3655 "file. Proceeding anyway.", state->TorVersion);
3656 } else { /* take action based on v */
3657 if (tor_version_as_new_as(state->TorVersion, "0.1.1.10-alpha") &&
3658 !tor_version_as_new_as(state->TorVersion, "0.1.1.16-rc-cvs")) {
3659 log_notice(LD_CONFIG, "Detected state file from buggy version '%s'. "
3660 "Enabling workaround to choose working entry guards.",
3661 state->TorVersion);
3662 config_free_lines(state->EntryGuards);
3663 state->EntryGuards = NULL;
3667 return 0;
3670 /** Replace the current persistent state with <b>new_state</b> */
3671 static void
3672 or_state_set(or_state_t *new_state)
3674 char *err = NULL;
3675 tor_assert(new_state);
3676 if (global_state)
3677 config_free(&state_format, global_state);
3678 global_state = new_state;
3679 if (entry_guards_parse_state(global_state, 1, &err)<0) {
3680 log_warn(LD_GENERAL,"%s",err);
3681 tor_free(err);
3683 if (rep_hist_load_state(global_state, &err)<0) {
3684 log_warn(LD_GENERAL,"Unparseable bandwidth history state: %s",err);
3685 tor_free(err);
3689 /** Reload the persistent state from disk, generating a new state as needed.
3690 * Return 0 on success, less than 0 on failure.
3693 or_state_load(void)
3695 or_state_t *new_state = NULL;
3696 char *contents = NULL, *fname;
3697 char *errmsg = NULL;
3698 int r = -1;
3700 fname = get_or_state_fname();
3701 switch (file_status(fname)) {
3702 case FN_FILE:
3703 if (!(contents = read_file_to_str(fname, 0))) {
3704 log_warn(LD_FS, "Unable to read state file \"%s\"", fname);
3705 goto done;
3707 break;
3708 case FN_NOENT:
3709 break;
3710 default:
3711 log_warn(LD_GENERAL,"State file \"%s\" is not a file? Failing.", fname);
3712 goto done;
3714 new_state = tor_malloc_zero(sizeof(or_state_t));
3715 new_state->_magic = OR_STATE_MAGIC;
3716 config_init(&state_format, new_state);
3717 if (contents) {
3718 config_line_t *lines=NULL;
3719 int assign_retval;
3720 if (config_get_lines(contents, &lines)<0)
3721 goto done;
3722 assign_retval = config_assign(&state_format, new_state,
3723 lines, 0, 0, &errmsg);
3724 config_free_lines(lines);
3725 if (assign_retval<0)
3726 goto done;
3729 if (or_state_validate(NULL, new_state, 1, &errmsg) < 0) {
3730 goto done;
3733 if (contents)
3734 log_info(LD_GENERAL, "Loaded state from \"%s\"", fname);
3735 else
3736 log_info(LD_GENERAL, "Initialized state");
3737 or_state_set(new_state);
3738 new_state = NULL;
3739 if (!contents) {
3740 global_state->dirty = 1;
3741 or_state_save();
3744 r = 0;
3745 done:
3746 if (errmsg) {
3747 log_warn(LD_GENERAL, "%s", errmsg);
3748 tor_free(errmsg);
3750 tor_free(fname);
3751 tor_free(contents);
3752 if (new_state)
3753 config_free(&state_format, new_state);
3755 return r;
3758 /** Write the persistent state to disk. Return 0 for success, <0 on failure. */
3760 or_state_save(void)
3762 char *state, *contents;
3763 char tbuf[ISO_TIME_LEN+1];
3764 size_t len;
3765 char *fname;
3767 tor_assert(global_state);
3769 entry_guards_update_state(global_state);
3770 rep_hist_update_state(global_state);
3772 if (!global_state->dirty)
3773 return 0;
3775 global_state->LastWritten = time(NULL);
3776 tor_free(global_state->TorVersion);
3777 global_state->TorVersion = tor_strdup("Tor " VERSION);
3778 state = config_dump(&state_format, global_state, 0);
3779 len = strlen(state)+128;
3780 contents = tor_malloc(len);
3781 format_local_iso_time(tbuf, time(NULL));
3782 tor_snprintf(contents, len,
3783 "# Tor state file last generated on %s\n"
3784 "# You *do not* need to edit this file.\n\n%s",
3785 tbuf, state);
3786 tor_free(state);
3787 fname = get_or_state_fname();
3788 if (write_str_to_file(fname, contents, 0)<0) {
3789 log_warn(LD_FS, "Unable to write state to file \"%s\"", fname);
3790 tor_free(fname);
3791 tor_free(contents);
3792 return -1;
3794 log_info(LD_GENERAL, "Saved state to \"%s\"", fname);
3795 tor_free(fname);
3796 tor_free(contents);
3798 global_state->dirty = 0;
3799 return 0;
3802 /** Helper to implement GETINFO functions about configuration variables (not
3803 * their values). Given a "config/names" question, set *<b>answer</b> to a
3804 * new string describing the supported configuration variables and their
3805 * types. */
3807 config_getinfo_helper(const char *question, char **answer)
3809 if (!strcmp(question, "config/names")) {
3810 smartlist_t *sl = smartlist_create();
3811 int i;
3812 for (i = 0; _option_vars[i].name; ++i) {
3813 config_var_t *var = &_option_vars[i];
3814 const char *type, *desc;
3815 char *line;
3816 size_t len;
3817 desc = config_find_description(&options_format, var->name);
3818 switch (var->type) {
3819 case CONFIG_TYPE_STRING: type = "String"; break;
3820 case CONFIG_TYPE_UINT: type = "Integer"; break;
3821 case CONFIG_TYPE_INTERVAL: type = "TimeInterval"; break;
3822 case CONFIG_TYPE_MEMUNIT: type = "DataSize"; break;
3823 case CONFIG_TYPE_DOUBLE: type = "Float"; break;
3824 case CONFIG_TYPE_BOOL: type = "Boolean"; break;
3825 case CONFIG_TYPE_ISOTIME: type = "Time"; break;
3826 case CONFIG_TYPE_CSV: type = "CommaList"; break;
3827 case CONFIG_TYPE_LINELIST: type = "LineList"; break;
3828 case CONFIG_TYPE_LINELIST_S: type = "Dependant"; break;
3829 case CONFIG_TYPE_LINELIST_V: type = "Virtual"; break;
3830 default:
3831 case CONFIG_TYPE_OBSOLETE:
3832 type = NULL; break;
3834 if (!type)
3835 continue;
3836 len = strlen(var->name)+strlen(type)+16;
3837 if (desc)
3838 len += strlen(desc);
3839 line = tor_malloc(len);
3840 if (desc)
3841 tor_snprintf(line, len, "%s %s %s\n",var->name,type,desc);
3842 else
3843 tor_snprintf(line, len, "%s %s\n",var->name,type);
3844 smartlist_add(sl, line);
3846 *answer = smartlist_join_strings(sl, "", 0, NULL);
3847 SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
3848 smartlist_free(sl);
3850 return 0;
3853 #include "../common/ht.h"
3854 #include "../common/test.h"
3856 /** Dump the version of every file to the log. */
3857 static void
3858 print_cvs_version(void)
3860 extern const char aes_c_id[];
3861 extern const char compat_c_id[];
3862 extern const char container_c_id[];
3863 extern const char crypto_c_id[];
3864 extern const char log_c_id[];
3865 extern const char torgzip_c_id[];
3866 extern const char tortls_c_id[];
3867 extern const char util_c_id[];
3869 extern const char buffers_c_id[];
3870 extern const char circuitbuild_c_id[];
3871 extern const char circuitlist_c_id[];
3872 extern const char circuituse_c_id[];
3873 extern const char command_c_id[];
3874 // extern const char config_c_id[];
3875 extern const char connection_c_id[];
3876 extern const char connection_edge_c_id[];
3877 extern const char connection_or_c_id[];
3878 extern const char control_c_id[];
3879 extern const char cpuworker_c_id[];
3880 extern const char directory_c_id[];
3881 extern const char dirserv_c_id[];
3882 extern const char dns_c_id[];
3883 extern const char hibernate_c_id[];
3884 extern const char main_c_id[];
3885 extern const char onion_c_id[];
3886 extern const char policies_c_id[];
3887 extern const char relay_c_id[];
3888 extern const char rendclient_c_id[];
3889 extern const char rendcommon_c_id[];
3890 extern const char rendmid_c_id[];
3891 extern const char rendservice_c_id[];
3892 extern const char rephist_c_id[];
3893 extern const char router_c_id[];
3894 extern const char routerlist_c_id[];
3895 extern const char routerparse_c_id[];
3897 puts(AES_H_ID);
3898 puts(COMPAT_H_ID);
3899 puts(CONTAINER_H_ID);
3900 puts(CRYPTO_H_ID);
3901 puts(HT_H_ID);
3902 puts(TEST_H_ID);
3903 puts(LOG_H_ID);
3904 puts(TORGZIP_H_ID);
3905 puts(TORINT_H_ID);
3906 puts(TORTLS_H_ID);
3907 puts(UTIL_H_ID);
3908 puts(aes_c_id);
3909 puts(compat_c_id);
3910 puts(container_c_id);
3911 puts(crypto_c_id);
3912 puts(log_c_id);
3913 puts(torgzip_c_id);
3914 puts(tortls_c_id);
3915 puts(util_c_id);
3917 puts(OR_H_ID);
3918 puts(buffers_c_id);
3919 puts(circuitbuild_c_id);
3920 puts(circuitlist_c_id);
3921 puts(circuituse_c_id);
3922 puts(command_c_id);
3923 puts(config_c_id);
3924 puts(connection_c_id);
3925 puts(connection_edge_c_id);
3926 puts(connection_or_c_id);
3927 puts(control_c_id);
3928 puts(cpuworker_c_id);
3929 puts(directory_c_id);
3930 puts(dirserv_c_id);
3931 puts(dns_c_id);
3932 puts(hibernate_c_id);
3933 puts(main_c_id);
3934 puts(onion_c_id);
3935 puts(policies_c_id);
3936 puts(relay_c_id);
3937 puts(rendclient_c_id);
3938 puts(rendcommon_c_id);
3939 puts(rendmid_c_id);
3940 puts(rendservice_c_id);
3941 puts(rephist_c_id);
3942 puts(router_c_id);
3943 puts(routerlist_c_id);
3944 puts(routerparse_c_id);