config.c 79 KB
Newer Older
Roger Dingledine's avatar
Roger Dingledine committed
1
2
3
/* Copyright 2001 Matej Pfajfar.
 * Copyright 2001-2004 Roger Dingledine.
 * Copyright 2004 Roger Dingledine, Nick Mathewson. */
4
5
/* See LICENSE for licensing information */
/* $Id$ */
6
const char config_c_id[] = "$Id$";
7

Nick Mathewson's avatar
Nick Mathewson committed
8
/**
9
 * \file config.c
Nick Mathewson's avatar
Nick Mathewson committed
10
 *
11
 * \brief Code to parse and interpret configuration files.
Nick Mathewson's avatar
Nick Mathewson committed
12
13
 **/

Roger Dingledine's avatar
Roger Dingledine committed
14
#include "or.h"
15
16
17
#ifdef MS_WINDOWS
#include <shlobj.h>
#endif
18
#include "../common/aes.h"
Roger Dingledine's avatar
Roger Dingledine committed
19

Nick Mathewson's avatar
Nick Mathewson committed
20
21
/** Enumeration of types which option values can take */
typedef enum config_type_t {
22
23
  CONFIG_TYPE_STRING = 0,   /**< An arbitrary string. */
  CONFIG_TYPE_UINT,         /**< A non-negative integer less than MAX_INT */
24
25
  CONFIG_TYPE_INTERVAL,     /**< A number of seconds, with optional units*/
  CONFIG_TYPE_MEMUNIT,      /**< A number of bytes, with optional units*/
26
27
28
29
30
  CONFIG_TYPE_DOUBLE,       /**< A floating-point value */
  CONFIG_TYPE_BOOL,         /**< A boolean value, expressed as 0 or 1. */
  CONFIG_TYPE_CSV,          /**< A list of strings, separated by commas and optional
                              * whitespace. */
  CONFIG_TYPE_LINELIST,     /**< Uninterpreted config lines */
31
32
33
34
35
  CONFIG_TYPE_LINELIST_S,   /**< Uninterpreted, context-sensitive config lines,
                             * mixed with other keywords. */
  CONFIG_TYPE_LINELIST_V,   /**< Catch-all "virtual" option to summarize
                             * context-sensitive config lines when fetching.
                             */
36
  CONFIG_TYPE_OBSOLETE,     /**< Obsolete (ignored) option. */
Nick Mathewson's avatar
Nick Mathewson committed
37
} config_type_t;
38

Nick Mathewson's avatar
Nick Mathewson committed
39
/* An abbreviation for a configuration option allowed on the command line */
40
typedef struct config_abbrev_t {
41
42
  const char *abbreviated;
  const char *full;
43
  int commandline_only;
44
45
} config_abbrev_t;

46
47
48
49
/* Handy macro for declaring "In the config file or on the command line,
 * you can abbreviate <b>tok</b>s as <b>tok</b>". */
#define PLURAL(tok) { #tok, #tok "s", 0 }

Nick Mathewson's avatar
Nick Mathewson committed
50
/* A list of command-line abbreviations. */
51
static config_abbrev_t config_abbrevs[] = {
52
  PLURAL(ExitNode),
53
  PLURAL(EntryNode),
54
55
  PLURAL(ExcludeNode),
  PLURAL(FirewallPort),
56
  PLURAL(LongLivedPort),
57
58
59
60
  PLURAL(HiddenServiceNode),
  PLURAL(HiddenServiceExcludeNode),
  PLURAL(RendNode),
  PLURAL(RendExcludeNode),
61
62
  PLURAL(StrictEntryNode),
  PLURAL(StrictExitNode),
63
  { "l", "Log", 1},
64
65
  { "BandwidthRateBytes", "BandwidthRate", 0},
  { "BandwidthBurstBytes", "BandwidthBurst", 0},
66
  { "DirFetchPostPeriod", "StatusFetchPeriod", 0},
67
  { "MaxConn", "ConnLimit", 0},
68
  { NULL, NULL , 0},
69
};
70
#undef PLURAL
71

72
/** A variable allowed in the configuration file or on the command line. */
73
typedef struct config_var_t {
74
75
76
77
  const char *name; /**< The full keyword (case insensitive). */
  config_type_t type; /**< How to interpret the type and turn it into a value. */
  off_t var_offset; /**< Offset of the corresponding member of or_options_t. */
  const char *initvalue; /**< String (or null) describing initial value. */
78
79
} config_var_t;

Nick Mathewson's avatar
Nick Mathewson committed
80
/** Return the offset of <b>member</b> within the type <b>tp</b>, in bytes */
Nick Mathewson's avatar
Nick Mathewson committed
81
#define STRUCT_OFFSET(tp, member) ((off_t) (((char*)&((tp*)0)->member)-(char*)0))
Nick Mathewson's avatar
Nick Mathewson committed
82
83
84
85
/** An entry for config_vars: "The option <b>name</b> has type
 * CONFIG_TYPE_<b>conftype</b>, and corresponds to
 * or_options_t.<b>member</b>"
 */
86
87
#define VAR(name,conftype,member,initvalue) \
  { name, CONFIG_TYPE_ ## conftype, STRUCT_OFFSET(or_options_t, member), initvalue }
Nick Mathewson's avatar
Nick Mathewson committed
88
/** An entry for config_vars: "The option <b>name</b> is obsolete." */
89
#define OBSOLETE(name) { name, CONFIG_TYPE_OBSOLETE, 0, NULL }
90

Nick Mathewson's avatar
Nick Mathewson committed
91
92
93
94
/** Array of configuration options.  Until we disallow nonstandard
 * abbreviations, order is significant, since the first matching option will
 * be chosen first.
 */
95
static config_var_t config_vars[] = {
96
  VAR("Address",             STRING,   Address,              NULL),
97
  VAR("AccountingStart",     STRING,   AccountingStart,      NULL),
98
  VAR("AllowUnverifiedNodes",CSV,      AllowUnverifiedNodes, "middle,rendezvous"),
99
  VAR("AuthoritativeDirectory",BOOL,   AuthoritativeDir,     "0"),
100
  VAR("BandwidthRate",       MEMUNIT,  BandwidthRate,        "1 MB"),
101
  VAR("BandwidthBurst",      MEMUNIT,  BandwidthBurst,       "5 MB"),
102
  VAR("MaxAdvertisedBandwidth",MEMUNIT,MaxAdvertisedBandwidth,"128 TB"),
103
104
  VAR("ClientOnly",          BOOL,     ClientOnly,           "0"),
  VAR("ContactInfo",         STRING,   ContactInfo,          NULL),
105
  VAR("ControlPort",         UINT,     ControlPort,          "0"),
106
  VAR("CookieAuthentication",BOOL,     CookieAuthentication, "0"),
107
108
  VAR("DebugLogFile",        STRING,   DebugLogFile,         NULL),
  VAR("DataDirectory",       STRING,   DataDirectory,        NULL),
109
  VAR("DirAllowPrivateAddresses",BOOL, DirAllowPrivateAddresses, NULL),
110
111
  VAR("DirPort",             UINT,     DirPort,              "0"),
  VAR("DirBindAddress",      LINELIST, DirBindAddress,       NULL),
112
113
  /** DOCDOC **/
  VAR("DirFetchPeriod",      INTERVAL, DirFetchPeriod,       "0 seconds"),
114
115
  VAR("DirPostPeriod",       INTERVAL, DirPostPeriod,        "20 minutes"),
  VAR("RendPostPeriod",      INTERVAL, RendPostPeriod,       "20 minutes"),
116
117
118
119
120
121
122
123
  VAR("DirPolicy",           LINELIST, DirPolicy,            NULL),
  VAR("DirServer",           LINELIST, DirServers,           NULL),
  VAR("ExitNodes",           STRING,   ExitNodes,            NULL),
  VAR("EntryNodes",          STRING,   EntryNodes,           NULL),
  VAR("StrictExitNodes",     BOOL,     StrictExitNodes,      "0"),
  VAR("StrictEntryNodes",    BOOL,     StrictEntryNodes,     "0"),
  VAR("ExitPolicy",          LINELIST, ExitPolicy,           NULL),
  VAR("ExcludeNodes",        STRING,   ExcludeNodes,         NULL),
124
125
  VAR("TrackHostExits",      CSV,      TrackHostExits,       NULL),
  VAR("TrackHostExitsExpire",INTERVAL, TrackHostExitsExpire, "30 minutes"),
126
  VAR("MapAddress",          LINELIST, AddressMap,           NULL),
127
  VAR("FascistFirewall",     BOOL,     FascistFirewall,      "0"),
128
  VAR("FirewallPorts",       CSV,      FirewallPorts,        "80,443"),
129
130
131
  VAR("MyFamily",            STRING,   MyFamily,             NULL),
  VAR("NodeFamily",          LINELIST, NodeFamilies,         NULL),
  VAR("Group",               STRING,   Group,                NULL),
132
  VAR("HashedControlPassword",STRING,  HashedControlPassword, NULL),
133
  VAR("HttpProxy",           STRING,   HttpProxy,            NULL),
134
  VAR("HttpsProxy",          STRING,   HttpsProxy,           NULL),
135
136
137
138
139
  VAR("HiddenServiceOptions",LINELIST_V, RendConfigLines,    NULL),
  VAR("HiddenServiceDir",    LINELIST_S, RendConfigLines,    NULL),
  VAR("HiddenServicePort",   LINELIST_S, RendConfigLines,    NULL),
  VAR("HiddenServiceNodes",  LINELIST_S, RendConfigLines,    NULL),
  VAR("HiddenServiceExcludeNodes", LINELIST_S, RendConfigLines, NULL),
140
  VAR("IgnoreVersion",       BOOL,     IgnoreVersion,        "0"),
141
  VAR("KeepalivePeriod",     INTERVAL, KeepalivePeriod,      "5 minutes"),
142
143
144
  VAR("Log",                 LINELIST, Logs,                 NULL),
  VAR("LogLevel",            LINELIST_S, OldLogOptions,      NULL),
  VAR("LogFile",             LINELIST_S, OldLogOptions,      NULL),
145
  OBSOLETE("LinkPadding"),
146
  VAR("ConnLimit",           UINT,     ConnLimit,            "1024"),
147
  VAR("MaxOnionsPending",    UINT,     MaxOnionsPending,     "100"),
148
  VAR("MonthlyAccountingStart",UINT,   _MonthlyAccountingStart,"0"),
149
150
  VAR("AccountingMaxKB",     UINT,     _AccountingMaxKB,     "0"),
  VAR("AccountingMax",       MEMUNIT,   AccountingMax,        "0 bytes"),
151
  VAR("Nickname",            STRING,   Nickname,             NULL),
152
  VAR("NewCircuitPeriod",    INTERVAL, NewCircuitPeriod,     "30 seconds"),
153
  VAR("MaxCircuitDirtiness", INTERVAL, MaxCircuitDirtiness,  "10 minutes"),
154
155
156
157
158
  VAR("NumCpus",             UINT,     NumCpus,              "1"),
  VAR("ORPort",              UINT,     ORPort,               "0"),
  VAR("ORBindAddress",       LINELIST, ORBindAddress,        NULL),
  VAR("OutboundBindAddress", STRING,   OutboundBindAddress,  NULL),
  VAR("PidFile",             STRING,   PidFile,              NULL),
159
  VAR("LongLivedPorts",      CSV,      LongLivedPorts,       "21,22,706,1863,5050,5190,5222,5223,6667,8300,8888"),
160
161
  VAR("PathlenCoinWeight",   DOUBLE,   PathlenCoinWeight,    "0.3"),
  VAR("RedirectExit",        LINELIST, RedirectExit,         NULL),
162
  OBSOLETE("RouterFile"),
163
164
165
166
167
  VAR("RunAsDaemon",         BOOL,     RunAsDaemon,          "0"),
  VAR("RunTesting",          BOOL,     RunTesting,           "0"),
  VAR("RecommendedVersions", LINELIST, RecommendedVersions,  NULL),
  VAR("RendNodes",           STRING,   RendNodes,            NULL),
  VAR("RendExcludeNodes",    STRING,   RendExcludeNodes,     NULL),
168
  VAR("ShutdownWaitLength",  INTERVAL, ShutdownWaitLength,   "30 seconds"),
169
  VAR("SocksPort",           UINT,     SocksPort,            "9050"),
170
171
  VAR("SocksBindAddress",    LINELIST, SocksBindAddress,     NULL),
  VAR("SocksPolicy",         LINELIST, SocksPolicy,          NULL),
172
173
  /** DOCDOC */
  VAR("StatusFetchPeriod",   INTERVAL, StatusFetchPeriod,    "0 seconds"),
174
  VAR("SysLog",              LINELIST_S, OldLogOptions,      NULL),
175
  OBSOLETE("TrafficShaping"),
176
  VAR("User",                STRING,   User,                 NULL),
177
  VAR("__ManageConnections", BOOL,     ManageConnections,    "1"),
178
  { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
179
180
181
182
};
#undef VAR
#undef OBSOLETE

Nick Mathewson's avatar
Nick Mathewson committed
183
/** Largest allowed config line */
184
#define CONFIG_LINE_T_MAXLEN 4096
185

186
187
static void config_line_append(struct config_line_t **lst,
                               const char *key, const char *val);
188
189
static void option_reset(or_options_t *options, config_var_t *var);
static void options_free(or_options_t *options);
190
static int option_is_same(or_options_t *o1, or_options_t *o2,const char *name);
191
192
193
194
static or_options_t *options_dup(or_options_t *old);
static int options_validate(or_options_t *options);
static int options_transition_allowed(or_options_t *old, or_options_t *new);
static int check_nickname_list(const char *lst, const char *name);
195
static void config_register_addressmaps(or_options_t *options);
196

197
static int parse_dir_server_line(const char *line, int validate_only);
198
static int parse_redirect_line(smartlist_t *result,
Roger Dingledine's avatar
Roger Dingledine committed
199
                               struct config_line_t *line);
200
201
202
203
204
205
206
207
208
static int parse_log_severity_range(const char *range, int *min_out,
                                    int *max_out);
static int convert_log_option(or_options_t *options,
                              struct config_line_t *level_opt,
                              struct config_line_t *file_opt, int isDaemon);
static int add_single_log_option(or_options_t *options, int minSeverity,
                                 int maxSeverity,
                                 const char *type, const char *fname);
static int normalize_log_options(or_options_t *options);
209
static int validate_data_directory(or_options_t *options);
210
static int write_configuration_file(const char *fname, or_options_t *options);
211

212
213
static uint64_t config_parse_memunit(const char *s, int *ok);
static int config_parse_interval(const char *s, int *ok);
214
static void print_cvs_version(void);
215

216
217
218
219
220
221
/*
 * Functions to read and write the global options pointer.
 */

/** Command-line and config-file options. */
static or_options_t *global_options=NULL;
Roger Dingledine's avatar
Roger Dingledine committed
222
/** Name of most recently read torrc file. */
223
static char *config_fname = NULL;
224

225
226
227
/** Return the currently configured options. */
or_options_t *
get_options(void) {
228
229
230
  tor_assert(global_options);
  return global_options;
}
231

Roger Dingledine's avatar
Roger Dingledine committed
232
/** Change the current global options to contain <b>new_val</b> instead
233
 * of their current value; free the old value as necessary.
234
235
236
237
238
239
 */
void
set_options(or_options_t *new_val) {
  if (global_options)
    options_free(global_options);
  global_options = new_val;
240
241
}

242
243
244
245
246
247
248
void
config_free_all(void)
{
  options_free(global_options);
  tor_free(config_fname);
}

249
250
251
/** Fetch the active option list, and take actions based on it. All
 * of the things we do should survive being done repeatedly.
 * Return 0 if all goes well, return -1 if it's time to die.
252
253
254
255
256
257
 *
 * Note 1: <b>new_val</b> must have previously been validated with
 * options_validate(), or Tor may freak out and exit.
 *
 * Note 2: We haven't moved all the "act on new configuration" logic
 * here yet.  Some is still in do_hup() and other places.
258
259
260
261
262
 */
int
options_act(void) {
  struct config_line_t *cl;
  or_options_t *options = get_options();
263
264
265
266
267
268
269
270
271
272
273
274
  static int libevent_initialized = 0;

  /* XXXX009 We once had a reason to separate start_daemon and finish_daemon:
   *    It let us have the parent process stick around until we were sure Tor
   *    was started.  Should we make start_daemon get called earlier? -NM */
  if (options->RunAsDaemon) {
    start_daemon(options->DataDirectory);
  }
  if (!libevent_initialized) {
    event_init();
    libevent_initialized = 1;
  }
275
276

  clear_trusted_dir_servers();
277
  for (cl = options->DirServers; cl; cl = cl->next) {
278
279
    if (parse_dir_server_line(cl->value, 0)<0) {
      log_fn(LOG_ERR,
280
             "Bug: Previously validated DirServer line could not be added!");
281
      return -1;
282
283
284
    }
  }

285
  if (rend_config_services(options, 0)<0) {
286
    log_fn(LOG_ERR,
287
           "Bug: Previously validated hidden services line could not be added!");
288
    return -1;
289
  }
290
291

  /* Setuid/setgid as appropriate */
292
293
  if (options->User || options->Group) {
    if (switch_id(options->User, options->Group) != 0) {
294
295
296
297
298
      return -1;
    }
  }

  /* Ensure data directory is private; create if possible. */
299
  if (check_private_dir(options->DataDirectory, CPD_CREATE) != 0) {
300
    log_fn(LOG_ERR, "Couldn't access/create private data directory %s",
301
           options->DataDirectory);
302
303
304
305
306
307
308
309
    return -1;
  }

  /* Bail out at this point if we're not going to be a server: we want
   * to not fork, and to log stuff to stderr. */
  if (options->command != CMD_RUN_TOR)
    return 0;

310
  mark_logs_temp(); /* Close current logs once new logs are open. */
311
  if (config_init_logs(options, 0)<0) /* Configure the log(s) */
312
313
314
315
    return -1;
  /* Close the temporary log we used while starting up, if it isn't already
   * gone. */
  close_temp_logs();
316
  add_callback_log(LOG_NOTICE, LOG_ERR, control_event_logmsg);
317

318
  options->_ConnLimit =
319
    set_max_file_descriptors((unsigned)options->ConnLimit, MAXCONNECTIONS);
320
  if (options->_ConnLimit < 0)
321
322
    return -1;

323
324
325
326
327
328
329
330
331
  {
    smartlist_t *sl = smartlist_create();
    for (cl = options->RedirectExit; cl; cl = cl->next) {
      if (parse_redirect_line(sl, cl)<0)
        return -1;
    }
    set_exit_redirects(sl);
  }

332
  /* Start backgrounding the process, if requested. */
333

334
  /* Finish backgrounding the process */
335
  if (options->RunAsDaemon) {
336
    /* We may be calling this for the n'th time (on SIGHUP), but it's safe. */
337
338
339
340
341
    finish_daemon();
  }

  /* Write our pid to the pid file. If we do not have write permissions we
   * will log a warning */
342
  if (options->PidFile)
343
344
    write_pidfile(options->PidFile);

345
346
347
  /* Register addressmap directives */
  config_register_addressmaps(options);

348
349
350
351
  /* Update address policies. */
  parse_socks_policy();
  parse_dir_policy();

352
353
  init_cookie_authentication(options->CookieAuthentication);

354
355
  /* reload keys as needed for rendezvous services. */
  if (rend_service_load_keys()<0) {
356
    log_fn(LOG_ERR,"Error loading rendezvous service keys");
357
358
359
    return -1;
  }

360
  /* Set up accounting */
361
  if (accounting_parse_options(options, 0)<0) {
362
    log_fn(LOG_ERR,"Error in accounting options");
363
364
    return -1;
  }
365
  if (accounting_is_enabled(options))
366
367
    configure_accounting(time(NULL));

368
  if (!we_are_hibernating() && retry_all_listeners(1) < 0) {
369
370
371
372
    log_fn(LOG_ERR,"Failed to bind one of the listener ports.");
    return -1;
  }

373
374
375
376
377
378
#if 0
  {
    char *smin, *smax;
    smin = config_dump_options(options, 1);
    smax = config_dump_options(options, 0);
    log_fn(LOG_DEBUG, "These are our options:\n%s",smax);
Roger Dingledine's avatar
Roger Dingledine committed
379
    log_fn(LOG_DEBUG, "We changed these options:\n%s",smin);
380
381
382
383
384
    tor_free(smin);
    tor_free(smax);
  }
#endif

385
386
387
388
389
390
  /* Since our options changed, we might need to regenerate and upload our
   * server descriptor.  (We could probably be more clever about only calling
   * this when something significant changed.)
   */
  mark_my_descriptor_dirty();

391
  return 0;
392
393
394
395
396
397
}

/*
 * Functions to parse config options
 */

Nick Mathewson's avatar
Nick Mathewson committed
398
/** If <b>option</b> is an official abbreviation for a longer option,
399
400
401
 * return the longer option.  Otherwise return <b>option</b>.
 * If <b>command_line</b> is set, apply all abbreviations.  Otherwise, only
 * apply abbreviations that work for the config file and the command line. */
402
static const char *
403
expand_abbrev(const char *option, int command_line)
404
405
406
407
{
  int i;
  for (i=0; config_abbrevs[i].abbreviated; ++i) {
    /* Abbreviations aren't casei. */
408
    if (!strcasecmp(option,config_abbrevs[i].abbreviated) &&
409
        (command_line || !config_abbrevs[i].commandline_only)) {
410
      return config_abbrevs[i].full;
411
    }
412
413
414
  }
  return option;
}
Nick Mathewson's avatar
Nick Mathewson committed
415

Nick Mathewson's avatar
Nick Mathewson committed
416
/** Helper: Read a list of configuration options from the command line. */
417
418
419
static struct config_line_t *
config_get_commandlines(int argc, char **argv)
{
420
421
  struct config_line_t *new;
  struct config_line_t *front = NULL;
422
423
424
  char *s;
  int i = 1;

425
  while (i < argc-1) {
426
427
428
    if (!strcmp(argv[i],"-f") ||
        !strcmp(argv[i],"--hash-password")) {
      i += 2; /* command-line option with argument. ignore them. */
429
      continue;
430
431
    } else if (!strcmp(argv[i],"--list-fingerprint")) {
      i += 1; /* command-line option. ignore it. */
432
      continue;
Nick Mathewson's avatar
Nick Mathewson committed
433
434
435
    } else if (!strcmp(argv[i],"--nt-service")) {
      i += 1;
      continue;
436
437
    }

438
    new = tor_malloc(sizeof(struct config_line_t));
439
    s = argv[i];
440

441
    while (*s == '-')
442
      s++;
443

444
    new->key = tor_strdup(expand_abbrev(s, 1));
445
    new->value = tor_strdup(argv[i+1]);
446
447

    log(LOG_DEBUG,"Commandline: parsed keyword '%s', value '%s'",
448
        new->key, new->value);
449
450
451
452
453
454
455
    new->next = front;
    front = new;
    i += 2;
  }
  return front;
}

Nick Mathewson's avatar
Nick Mathewson committed
456
/** Helper: allocate a new configuration option mapping 'key' to 'val',
457
458
459
460
461
 * append it to *<b>lst</b>. */
static void
config_line_append(struct config_line_t **lst,
                   const char *key,
                   const char *val)
462
463
{
  struct config_line_t *newline;
464

465
466
467
  newline = tor_malloc(sizeof(struct config_line_t));
  newline->key = tor_strdup(key);
  newline->value = tor_strdup(val);
468
469
470
471
472
  newline->next = NULL;
  while (*lst)
    lst = &((*lst)->next);

  (*lst) = newline;
473
474
}

475
476
/** Helper: parse the config string and strdup into key/value
 * strings. Set *result to the list, or NULL if parsing the string
477
478
 * failed.  Return 0 on success, -1 on failure. Warn and ignore any
 * misformatted lines. */
479
480
int
config_get_lines(char *string, struct config_line_t **result)
481
{
482
  struct config_line_t *list = NULL, **next;
483
  char *k, *v;
484

485
  next = &list;
486
487
488
489
490
491
  do {
    string = parse_line_from_str(string, &k, &v);
    if (!string) {
      config_free_lines(list);
      return -1;
    }
492
493
494
495
496
497
498
499
500
501
    if (k && v) {
      /* This list can get long, so we keep a pointer to the end of it
       * rather than using config_line_append over and over and getting n^2
       * performance.  This is the only really long list. */
      *next = tor_malloc(sizeof(struct config_line_t));
      (*next)->key = tor_strdup(k);
      (*next)->value = tor_strdup(v);
      (*next)->next = NULL;
      next = &((*next)->next);
    }
502
  } while (*string);
503

504
  *result = list;
505
  return 0;
Roger Dingledine's avatar
Roger Dingledine committed
506
507
}

Nick Mathewson's avatar
Nick Mathewson committed
508
509
510
/**
 * Free all the configuration lines on the linked list <b>front</b>.
 */
511
void
512
513
config_free_lines(struct config_line_t *front)
{
514
  struct config_line_t *tmp;
515

516
  while (front) {
517
518
519
    tmp = front;
    front = tmp->next;

Roger Dingledine's avatar
Roger Dingledine committed
520
521
522
    tor_free(tmp->key);
    tor_free(tmp->value);
    tor_free(tmp);
523
524
525
  }
}

Nick Mathewson's avatar
Nick Mathewson committed
526
527
528
529
/** If <b>key</b> is a configuration option, return the corresponding
 * config_var_t.  Otherwise, if <b>key</b> is a non-standard abbreviation,
 * warn, and return the corresponding config_var_t.  Otherwise return NULL.
 */
530
531
532
static config_var_t *config_find_option(const char *key)
{
  int i;
533
  size_t keylen = strlen(key);
534
  if (!keylen)
535
    return NULL; /* if they say "--" on the commandline, it's not an option */
Nick Mathewson's avatar
Nick Mathewson committed
536
  /* First, check for an exact (case-insensitive) match */
537
  for (i=0; config_vars[i].name; ++i) {
Nick Mathewson's avatar
Nick Mathewson committed
538
    if (!strcasecmp(key, config_vars[i].name))
539
      return &config_vars[i];
Nick Mathewson's avatar
Nick Mathewson committed
540
541
542
  }
  /* If none, check for an abbreviated match */
  for (i=0; config_vars[i].name; ++i) {
543
    if (!strncasecmp(key, config_vars[i].name, keylen)) {
544
545
546
547
548
549
      log_fn(LOG_WARN, "The abbreviation '%s' is deprecated. "
          "Tell Nick and Roger to make it official, or just use '%s' instead",
             key, config_vars[i].name);
      return &config_vars[i];
    }
  }
550
  /* Okay, unrecognized options */
551
552
553
  return NULL;
}

Nick Mathewson's avatar
Nick Mathewson committed
554
/** If <b>c</b> is a syntactically valid configuration line, update
555
556
 * <b>options</b> with its value and return 0.  Otherwise return -1 for bad key,
 * -2 for bad value.
557
558
559
560
 *
 * If 'reset' is set, and we get a line containing no value, restore the
 * option to its default value.
 */
561
static int
562
config_assign_line(or_options_t *options, struct config_line_t *c, int reset)
563
{
564
  int i, ok;
565
566
  config_var_t *var;
  void *lvalue;
567

568
569
570
571
572
573
574
  var = config_find_option(c->key);
  if (!var) {
    log_fn(LOG_WARN, "Unknown option '%s'.  Failing.", c->key);
    return -1;
  }
  /* Put keyword into canonical case. */
  if (strcmp(var->name, c->key)) {
575
    tor_free(c->key);
576
    c->key = tor_strdup(var->name);
577
578
  }

579
  if (reset && !strlen(c->value)) {
580
    option_reset(options, var);
581
582
583
    return 0;
  }

Nick Mathewson's avatar
Nick Mathewson committed
584
  lvalue = ((char*)options) + var->var_offset;
585
  switch (var->type) {
586

587
588
589
  case CONFIG_TYPE_UINT:
    i = tor_parse_long(c->value, 10, 0, INT_MAX, &ok, NULL);
    if (!ok) {
590
      log(LOG_WARN, "Int keyword '%s %s' is malformed or out of bounds.",
591
          c->key,c->value);
592
      return -2;
593
    }
594
    *(int *)lvalue = i;
595
596
    break;

597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
  case CONFIG_TYPE_INTERVAL: {
    i = config_parse_interval(c->value, &ok);
    if (!ok) {
      return -2;
    }
    *(int *)lvalue = i;
    break;
  }

  case CONFIG_TYPE_MEMUNIT: {
    uint64_t u64 = config_parse_memunit(c->value, &ok);
    if (!ok) {
      return -2;
    }
    *(uint64_t *)lvalue = u64;
    break;
  }

615
616
617
  case CONFIG_TYPE_BOOL:
    i = tor_parse_long(c->value, 10, 0, 1, &ok, NULL);
    if (!ok) {
618
      log(LOG_WARN, "Boolean keyword '%s' expects 0 or 1.", c->key);
619
      return -2;
620
    }
621
    *(int *)lvalue = i;
622
623
624
    break;

  case CONFIG_TYPE_STRING:
625
626
    tor_free(*(char **)lvalue);
    *(char **)lvalue = tor_strdup(c->value);
627
628
629
    break;

  case CONFIG_TYPE_DOUBLE:
630
    *(double *)lvalue = atof(c->value);
631
632
633
    break;

  case CONFIG_TYPE_CSV:
634
635
636
637
    if (*(smartlist_t**)lvalue) {
      SMARTLIST_FOREACH(*(smartlist_t**)lvalue, char *, cp, tor_free(cp));
      smartlist_clear(*(smartlist_t**)lvalue);
    } else {
638
      *(smartlist_t**)lvalue = smartlist_create();
639
    }
640

641
    smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",",
642
643
644
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
    break;

645
646
  case CONFIG_TYPE_LINELIST:
  case CONFIG_TYPE_LINELIST_S:
647
    config_line_append((struct config_line_t**)lvalue, c->key, c->value);
648
    break;
649
650
651
652

  case CONFIG_TYPE_OBSOLETE:
    log_fn(LOG_WARN, "Skipping obsolete configuration option '%s'", c->key);
    break;
653
654
  case CONFIG_TYPE_LINELIST_V:
    log_fn(LOG_WARN, "Can't provide value for virtual option '%s'", c->key);
655
    return -2;
656
657
658
  default:
    tor_assert(0);
    break;
659
  }
660
  return 0;
661
662
}

663
664
665
666
667
668
669
670
671
672
/** restore the option named <b>key</b> in options to its default value. */
static void
config_reset_line(or_options_t *options, const char *key)
{
  config_var_t *var;

  var = config_find_option(key);
  if (!var)
    return; /* give error on next pass. */

673
  option_reset(options, var);
674
675
}

676
677
678
679
680
681
682
683
/** Return true iff key is a valid configuration option. */
int
config_option_is_recognized(const char *key)
{
  config_var_t *var = config_find_option(key);
  return (var != NULL);
}

684
685
686
687
688
689
690
691
692
/** Return a canonicalized list of the options assigned for key.
 */
struct config_line_t *
config_get_assigned_option(or_options_t *options, const char *key)
{
  config_var_t *var;
  const void *value;
  char buf[32];
  struct config_line_t *result;
693
  tor_assert(options && key);
694
695
696
697
698

  var = config_find_option(key);
  if (!var) {
    log_fn(LOG_WARN, "Unknown option '%s'.  Failing.", key);
    return NULL;
699
700
701
  } else if (var->type == CONFIG_TYPE_LINELIST_S) {
    log_fn(LOG_WARN, "Can't return context-sensitive '%s' on its own", key);
    return NULL;
702
703
704
  }
  value = ((char*)options) + var->var_offset;

705
706
  if (var->type == CONFIG_TYPE_LINELIST ||
      var->type == CONFIG_TYPE_LINELIST_V) {
707
    /* Linelist requires special handling: we just copy and return it. */
Roger Dingledine's avatar
Roger Dingledine committed
708
    const struct config_line_t *next_in = *(const struct config_line_t**)value;
709
710
711
712
713
714
715
716
717
718
719
720
721
722
    struct config_line_t **next_out = &result;
    while (next_in) {
      *next_out = tor_malloc(sizeof(struct config_line_t));
      (*next_out)->key = tor_strdup(next_in->key);
      (*next_out)->value = tor_strdup(next_in->value);
      next_in = next_in->next;
      next_out = &((*next_out)->next);
    }
    (*next_out) = NULL;
    return result;
  }

  result = tor_malloc_zero(sizeof(struct config_line_t));
  result->key = tor_strdup(var->name);
723
  switch (var->type)
724
725
    {
    case CONFIG_TYPE_STRING:
726
727
728
729
730
731
732
      if (*(char**)value) {
        result->value = tor_strdup(*(char**)value);
      } else {
        tor_free(result->key);
        tor_free(result);
        return NULL;
      }
733
      break;
734
    case CONFIG_TYPE_INTERVAL:
735
    case CONFIG_TYPE_UINT:
736
      /* This means every or_options_t uint or bool element
737
       * needs to be an int. Not, say, a uint16_t or char. */
738
739
740
      tor_snprintf(buf, sizeof(buf), "%d", *(int*)value);
      result->value = tor_strdup(buf);
      break;
741
742
743
744
745
    case CONFIG_TYPE_MEMUNIT:
      tor_snprintf(buf, sizeof(buf), U64_FORMAT,
                   U64_PRINTF_ARG(*(uint64_t*)value));
      result->value = tor_strdup(buf);
      break;
746
747
748
749
750
751
752
753
    case CONFIG_TYPE_DOUBLE:
      tor_snprintf(buf, sizeof(buf), "%f", *(double*)value);
      result->value = tor_strdup(buf);
      break;
    case CONFIG_TYPE_BOOL:
      result->value = tor_strdup(*(int*)value ? "1" : "0");
      break;
    case CONFIG_TYPE_CSV:
Roger Dingledine's avatar
Roger Dingledine committed
754
755
      if (*(smartlist_t**)value)
        result->value = smartlist_join_strings(*(smartlist_t**)value,",",0,NULL);
756
757
758
      else
        result->value = tor_strdup("");
      break;
759
760
761
762
763
    case CONFIG_TYPE_OBSOLETE:
      log_fn(LOG_WARN,"You asked me for the value of an obsolete config option %s.", key);
      tor_free(result->key);
      tor_free(result);
      return NULL;
764
765
766
    default:
      tor_free(result->key);
      tor_free(result);
767
      log_fn(LOG_WARN,"Bug: unknown type %d for known key %s", var->type, key);
768
769
770
771
772
773
      return NULL;
    }

  return result;
}

774
/** Iterate through the linked list of requested options <b>list</b>.
Nick Mathewson's avatar
Nick Mathewson committed
775
 * For each item, convert as appropriate and assign to <b>options</b>.
776
 * If an item is unrecognized, return -1 immediately,
777
778
779
780
 * else return 0 for success.
 *
 * If <b>reset</b>, then interpret empty lines as meaning "restore to
 * default value", and interpret LINELIST* options as replacing (not
781
782
 * extending) their previous values.  Return 0 on success, -1 on bad key,
 * -2 on bad value.
783
 */
784
static int
785
config_assign(or_options_t *options, struct config_line_t *list, int reset)
786
{
787
  struct config_line_t *p;
788
  tor_assert(options);
789
790
791
792
793
794
795

  /* pass 1: normalize keys */
  for (p = list; p; p = p->next) {
    const char *full = expand_abbrev(p->key, 0);
    if (strcmp(full,p->key)) {
      tor_free(p->key);
      p->key = tor_strdup(full);
796
    }
797
798
  }

799
  /* pass 2: if we're reading from a resetting source, clear all mentioned
800
801
802
803
804
   * linelists. */
  if (reset) {
    for (p = list; p; p = p->next)
      config_reset_line(options, p->key);
  }
805

806
807
  /* pass 3: assign. */
  while (list) {
808
809
810
    int r;
    if ((r=config_assign_line(options, list, reset)))
      return r;
811
    list = list->next;
Roger Dingledine's avatar
Roger Dingledine committed
812
  }
813
  return 0;
814
815
}

816
/** Try assigning <b>list</b> to the global options. You do this by duping
817
 * options, assigning list to the new one, then validating it. If it's
818
 * ok, then throw out the old one and stick with the new one. Else,
819
820
 * revert to old and return failure.  Return 0 on success, -1 on bad
 * keys, -2 on bad values, -3 on bad transition.
821
822
 */
int
823
config_trial_assign(struct config_line_t *list, int reset)
824
{
825
  int r;
826
  or_options_t *trial_options = options_dup(get_options());
827

828
  if ((r=config_assign(trial_options, list, reset)) < 0) {
829
    options_free(trial_options);
830
    return r;
831
832
833
834
  }

  if (options_validate(trial_options) < 0) {
    options_free(trial_options);
835
    return -2;
836
837
  }

838
  if (options_transition_allowed(get_options(), trial_options) < 0) {
839
    options_free(trial_options);
840
    return -3;
841
842
  }

843
  set_options(trial_options); /* we liked it. put it in place. */
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
  return 0;
}

/** Replace the option indexed by <b>var</b> in <b>options</b> with its
 * default value. */
static void
option_reset(or_options_t *options, config_var_t *var)
{
  struct config_line_t *c;
  void *lvalue;

  lvalue = ((char*)options) + var->var_offset;
  switch (var->type) {
    case CONFIG_TYPE_STRING:
      tor_free(*(char**)lvalue);
      break;
    case CONFIG_TYPE_DOUBLE:
      *(double*)lvalue = 0.0;
      break;
863
    case CONFIG_TYPE_INTERVAL:
864
865
866
867
    case CONFIG_TYPE_UINT:
    case CONFIG_TYPE_BOOL:
      *(int*)lvalue = 0;
      break;
868
869
870
    case CONFIG_TYPE_MEMUNIT:
      *(uint64_t*)lvalue = 0;
      break;
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
    case CONFIG_TYPE_CSV:
      if (*(smartlist_t**)lvalue) {
        SMARTLIST_FOREACH(*(smartlist_t **)lvalue, char *, cp, tor_free(cp));
        smartlist_free(*(smartlist_t **)lvalue);
        *(smartlist_t **)lvalue = NULL;
      }
      break;
    case CONFIG_TYPE_LINELIST:
    case CONFIG_TYPE_LINELIST_S:
      config_free_lines(*(struct config_line_t **)lvalue);
      *(struct config_line_t **)lvalue = NULL;
      break;
    case CONFIG_TYPE_LINELIST_V:
      /* handled by linelist_s. */
      break;
    case CONFIG_TYPE_OBSOLETE:
      break;
  }
  if (var->initvalue) {
890
    c = tor_malloc_zero(sizeof(struct config_line_t));
891
892
893
894
895
896
897
    c->key = tor_strdup(var->name);
    c->value = tor_strdup(var->initvalue);
    config_assign_line(options,c,0);
    config_free_lines(c);
  }
}

898
/** Set <b>options</b>-&gt;DirServers to contain the default directory
899
 * servers. */
900
static void
901
add_default_trusted_dirservers(or_options_t *options)
902
{
Nick Mathewson's avatar
Nick Mathewson committed
903
  /* moria1 */
904
  config_line_append(&options->DirServers, "DirServer",
905
       "18.244.0.188:9031 FFCB 46DB 1339 DA84 674C 70D7 CB58 6434 C437 0441");
Nick Mathewson's avatar
Nick Mathewson committed
906
  /* moria2 */
907
  config_line_append(&options->DirServers, "DirServer",
908
         "18.244.0.114:80 719B E45D E224 B607 C537 07D0 E214 3E2D 423E 74CF");
Nick Mathewson's avatar
Nick Mathewson committed
909
  /* tor26 */
910
  config_line_append(&options->DirServers, "DirServer",
911
     "62.116.124.106:9030 847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D");
912
//  "tor.noreply.org:9030 847B 1F85 0344 D787 6491 A548 92F9 0493 4E4E B85D");
913
914
}

Nick Mathewson's avatar
Nick Mathewson committed
915
/** Print a usage message for tor. */
916
917
918
static void
print_usage(void)
{
919
920
921
  printf(
"Copyright 2001-2004 Roger Dingledine, Nick Mathewson, Matej Pfajfar.\n\n"
"tor -f <torrc> [args]\n"
922
"See man page for options, or http://tor.eff.org/ for documentation.\n");
923
924
}

Nick Mathewson's avatar
Nick Mathewson committed
925
/**
926
927
 * Based on <b>address</b>, guess our public IP address and put it
 * in <b>addr</b>.
Nick Mathewson's avatar
Nick Mathewson committed
928
 */
929
930
931
int
resolve_my_address(const char *address, uint32_t *addr)
{
932
933
  struct in_addr in;
  struct hostent *rent;
934
  char hostname[256];
935
  int explicit_ip=1;
936
  char tmpbuf[INET_NTOA_BUF_LEN];
937
  static uint32_t old_addr=0;
938

939
940