tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

statefile.c (24914B)


      1 /* Copyright (c) 2001 Matej Pfajfar.
      2 * Copyright (c) 2001-2004, Roger Dingledine.
      3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      5 /* See LICENSE for licensing information */
      6 
      7 /**
      8 * \file statefile.c
      9 *
     10 * \brief Handles parsing and encoding the persistent 'state' file that carries
     11 *  miscellaneous persistent state between Tor invocations.
     12 *
     13 * This 'state' file is a typed key-value store that allows multiple
     14 * entries for the same key.  It follows the same metaformat as described
     15 * in confmgt.c, and uses the same code to read and write itself.
     16 *
     17 * The state file is most suitable for small values that don't change too
     18 * frequently.  For values that become very large, we typically use a separate
     19 * file -- for example, see how we handle microdescriptors, by storing them in
     20 * a separate file with a journal.
     21 *
     22 * The current state is accessed via get_or_state(), which returns a singleton
     23 * or_state_t object.  Functions that change it should call
     24 * or_state_mark_dirty() to ensure that it will get written to disk.
     25 *
     26 * The or_state_save() function additionally calls various functioens
     27 * throughout Tor that might want to flush more state to the the disk,
     28 * including some in rephist.c, entrynodes.c, circuitstats.c, hibernate.c.
     29 */
     30 
     31 #define STATEFILE_PRIVATE
     32 #include "core/or/or.h"
     33 #include "core/or/circuitstats.h"
     34 #include "app/config/config.h"
     35 #include "feature/relay/transport_config.h"
     36 #include "lib/confmgt/confmgt.h"
     37 #include "core/mainloop/mainloop.h"
     38 #include "core/mainloop/netstatus.h"
     39 #include "core/mainloop/connection.h"
     40 #include "feature/control/control_events.h"
     41 #include "feature/client/entrynodes.h"
     42 #include "feature/hibernate/hibernate.h"
     43 #include "feature/stats/bwhist.h"
     44 #include "feature/relay/router.h"
     45 #include "feature/relay/routermode.h"
     46 #include "lib/sandbox/sandbox.h"
     47 #include "app/config/statefile.h"
     48 #include "app/main/subsysmgr.h"
     49 #include "lib/encoding/confline.h"
     50 #include "lib/net/resolve.h"
     51 #include "lib/version/torversion.h"
     52 
     53 #include "app/config/or_state_st.h"
     54 
     55 #ifdef HAVE_UNISTD_H
     56 #include <unistd.h>
     57 #endif
     58 
     59 /** A list of state-file "abbreviations," for compatibility. */
     60 static config_abbrev_t state_abbrevs_[] = {
     61  { NULL, NULL, 0, 0},
     62 };
     63 
     64 /** A list of obsolete keys that we do not and should not preserve.
     65 *
     66 * We could just let these live in ExtraLines indefinitely, but they're
     67 * never going to be used again, and every version that used them
     68 * has been obsolete for a long time.
     69 * */
     70 static const char *obsolete_state_keys[] = {
     71  /* These were renamed in 0.1.1.11-alpha */
     72  "AccountingBytesReadInterval",
     73  "HelperNode",
     74  "HelperNodeDownSince",
     75  "HelperNodeUnlistedSince",
     76  "EntryNode",
     77  "HelperNodeDownSince",
     78  "EntryNodeUnlistedSince",
     79  /* These were replaced by "Guard" in 0.3.0.1-alpha. */
     80  "EntryGuard",
     81  "EntryGuardDownSince",
     82  "EntryGuardUnlistedSince",
     83  "EntryGuardAddedBy",
     84  "EntryGuardPathBias",
     85  "EntryGuardPathUseBias",
     86  /* This was replaced by OPE-based revision numbers in 0.3.5.1-alpha,
     87   * and was never actually used in a released version. */
     88  "HidServRevCounter",
     89 
     90  NULL,
     91 };
     92 
     93 /** dummy instance of or_state_t, used for type-checking its
     94 * members with CONF_CHECK_VAR_TYPE. */
     95 DUMMY_TYPECHECK_INSTANCE(or_state_t);
     96 
     97 #define VAR(varname,conftype,member,initvalue)                          \
     98  CONFIG_VAR_ETYPE(or_state_t, varname, conftype, member, 0, initvalue)
     99 #define V(member,conftype,initvalue)            \
    100  VAR(#member, conftype, member, initvalue)
    101 
    102 /** Array of "state" variables saved to the ~/.tor/state file. */
    103 // clang-format off
    104 static const config_var_t state_vars_[] = {
    105  /* Remember to document these in state-contents.txt ! */
    106 
    107  V(AccountingBytesReadInInterval,    MEMUNIT,  NULL),
    108  V(AccountingBytesWrittenInInterval, MEMUNIT,  NULL),
    109  V(AccountingExpectedUsage,          MEMUNIT,  NULL),
    110  V(AccountingIntervalStart,          ISOTIME,  NULL),
    111  V(AccountingSecondsActive,          INTERVAL, NULL),
    112  V(AccountingSecondsToReachSoftLimit,INTERVAL, NULL),
    113  V(AccountingSoftLimitHitAt,         ISOTIME,  NULL),
    114  V(AccountingBytesAtSoftLimit,       MEMUNIT,  NULL),
    115 
    116  VAR("TransportProxy",               LINELIST_S, TransportProxies, NULL),
    117  V(TransportProxies,                 LINELIST_V, NULL),
    118 
    119  V(BWHistoryReadEnds,                ISOTIME,  NULL),
    120  V(BWHistoryReadInterval,            POSINT,     "900"),
    121  V(BWHistoryReadValues,              CSV,      ""),
    122  V(BWHistoryReadMaxima,              CSV,      ""),
    123  V(BWHistoryWriteEnds,               ISOTIME,  NULL),
    124  V(BWHistoryWriteInterval,           POSINT,     "900"),
    125  V(BWHistoryWriteValues,             CSV,      ""),
    126  V(BWHistoryWriteMaxima,             CSV,      ""),
    127  V(BWHistoryIPv6ReadEnds,                ISOTIME,  NULL),
    128  V(BWHistoryIPv6ReadInterval,            POSINT,     "900"),
    129  V(BWHistoryIPv6ReadValues,              CSV,      ""),
    130  V(BWHistoryIPv6ReadMaxima,              CSV,      ""),
    131  V(BWHistoryIPv6WriteEnds,               ISOTIME,  NULL),
    132  V(BWHistoryIPv6WriteInterval,           POSINT,     "900"),
    133  V(BWHistoryIPv6WriteValues,             CSV,      ""),
    134  V(BWHistoryIPv6WriteMaxima,             CSV,      ""),
    135  V(BWHistoryDirReadEnds,             ISOTIME,  NULL),
    136  V(BWHistoryDirReadInterval,         POSINT,     "900"),
    137  V(BWHistoryDirReadValues,           CSV,      ""),
    138  V(BWHistoryDirReadMaxima,           CSV,      ""),
    139  V(BWHistoryDirWriteEnds,            ISOTIME,  NULL),
    140  V(BWHistoryDirWriteInterval,        POSINT,     "900"),
    141  V(BWHistoryDirWriteValues,          CSV,      ""),
    142  V(BWHistoryDirWriteMaxima,          CSV,      ""),
    143 
    144  V(Guard,                            LINELIST, NULL),
    145 
    146  V(TorVersion,                       STRING,   NULL),
    147 
    148  V(LastRotatedOnionKey,              ISOTIME,  NULL),
    149  V(LastWritten,                      ISOTIME,  NULL),
    150 
    151  V(TotalBuildTimes,                  POSINT,     NULL),
    152  V(CircuitBuildAbandonedCount,       POSINT,     "0"),
    153  VAR("CircuitBuildTimeBin",          LINELIST_S, BuildtimeHistogram, NULL),
    154  VAR("BuildtimeHistogram",           LINELIST_V, BuildtimeHistogram, NULL),
    155 
    156  END_OF_CONFIG_VARS
    157 };
    158 // clang-format on
    159 
    160 #undef VAR
    161 #undef V
    162 
    163 static int or_state_validate(or_state_t *state, char **msg);
    164 
    165 static int or_state_validate_cb(const void *old_options,
    166                                void *options, char **msg);
    167 
    168 /** Magic value for or_state_t. */
    169 #define OR_STATE_MAGIC 0x57A73f57
    170 
    171 /** "Extra" variable in the state that receives lines we can't parse. This
    172 * lets us preserve options from versions of Tor newer than us. */
    173 static struct_member_t state_extra_var = {
    174  .name = "__extra",
    175  .type = CONFIG_TYPE_LINELIST,
    176  .offset = offsetof(or_state_t, ExtraLines),
    177 };
    178 
    179 /** Configuration format for or_state_t. */
    180 static const config_format_t state_format = {
    181  .size = sizeof(or_state_t),
    182  .magic = {
    183   "or_state_t",
    184   OR_STATE_MAGIC,
    185   offsetof(or_state_t, magic_),
    186  },
    187  .abbrevs = state_abbrevs_,
    188  .vars = state_vars_,
    189  .legacy_validate_fn = or_state_validate_cb,
    190  .extra = &state_extra_var,
    191  .has_config_suite = true,
    192  .config_suite_offset = offsetof(or_state_t, substates_),
    193 };
    194 
    195 /* A global configuration manager for state-file objects */
    196 static config_mgr_t *state_mgr = NULL;
    197 
    198 /** Return the configuration manager for state-file objects. */
    199 STATIC const config_mgr_t *
    200 get_state_mgr(void)
    201 {
    202  if (PREDICT_UNLIKELY(state_mgr == NULL)) {
    203    state_mgr = config_mgr_new(&state_format);
    204    int rv = subsystems_register_state_formats(state_mgr);
    205    tor_assert(rv == 0);
    206    config_mgr_freeze(state_mgr);
    207  }
    208  return state_mgr;
    209 }
    210 
    211 #define CHECK_STATE_MAGIC(s) STMT_BEGIN                        \
    212    config_check_toplevel_magic(get_state_mgr(), (s));         \
    213  STMT_END
    214 
    215 /** Persistent serialized state. */
    216 static or_state_t *global_state = NULL;
    217 
    218 /** Return the persistent state struct for this Tor. */
    219 MOCK_IMPL(or_state_t *,
    220 get_or_state, (void))
    221 {
    222  tor_assert(global_state);
    223  return global_state;
    224 }
    225 
    226 /** Return true iff we have loaded the global state for this Tor */
    227 int
    228 or_state_loaded(void)
    229 {
    230  return global_state != NULL;
    231 }
    232 
    233 /** Return true if <b>line</b> is a valid state TransportProxy line.
    234 *  Return false otherwise. */
    235 static int
    236 state_transport_line_is_valid(const char *line)
    237 {
    238  smartlist_t *items = NULL;
    239  char *addrport=NULL;
    240  tor_addr_t addr;
    241  uint16_t port = 0;
    242  int r;
    243 
    244  items = smartlist_new();
    245  smartlist_split_string(items, line, NULL,
    246                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
    247 
    248  if (smartlist_len(items) != 2) {
    249    log_warn(LD_CONFIG, "state: Not enough arguments in TransportProxy line.");
    250    goto err;
    251  }
    252 
    253  addrport = smartlist_get(items, 1);
    254  if (tor_addr_port_lookup(addrport, &addr, &port) < 0) {
    255    log_warn(LD_CONFIG, "state: Could not parse addrport.");
    256    goto err;
    257  }
    258 
    259  if (!port) {
    260    log_warn(LD_CONFIG, "state: Transport line did not contain port.");
    261    goto err;
    262  }
    263 
    264  r = 1;
    265  goto done;
    266 
    267 err:
    268  r = 0;
    269 
    270 done:
    271  SMARTLIST_FOREACH(items, char*, s, tor_free(s));
    272  smartlist_free(items);
    273  return r;
    274 }
    275 
    276 /** Return 0 if all TransportProxy lines in <b>state</b> are well
    277 *  formed. Otherwise, return -1. */
    278 static int
    279 validate_transports_in_state(or_state_t *state)
    280 {
    281  int broken = 0;
    282  config_line_t *line;
    283 
    284  for (line = state->TransportProxies ; line ; line = line->next) {
    285    tor_assert(!strcmp(line->key, "TransportProxy"));
    286    if (!state_transport_line_is_valid(line->value))
    287      broken = 1;
    288  }
    289 
    290  if (broken)
    291    log_warn(LD_CONFIG, "state: State file seems to be broken.");
    292 
    293  return 0;
    294 }
    295 
    296 /** Return 0 if every setting in <b>state</b> is reasonable, and a
    297 * permissible transition from <b>old_state</b>.  Else warn and return -1.
    298 * Should have no side effects, except for normalizing the contents of
    299 * <b>state</b>.
    300 */
    301 static int
    302 or_state_validate(or_state_t *state, char **msg)
    303 {
    304  return config_validate(get_state_mgr(), NULL, state, msg);
    305 }
    306 
    307 /**
    308 * Legacy validation/normalization callback for or_state_t.  See
    309 * legacy_validate_fn_t for more information.
    310 */
    311 static int
    312 or_state_validate_cb(const void *old_state, void *state_, char **msg)
    313 {
    314  /* There is not a meaningful concept of a state-to-state transition,
    315   * since we do not reload the state after we start. */
    316  (void) old_state;
    317  CHECK_STATE_MAGIC(state_);
    318 
    319  or_state_t *state = state_;
    320 
    321  if (entry_guards_parse_state(state, 0, msg)<0)
    322    return -1;
    323 
    324  if (validate_transports_in_state(state)<0)
    325    return -1;
    326 
    327  return 0;
    328 }
    329 
    330 /** Replace the current persistent state with <b>new_state</b> */
    331 static int
    332 or_state_set(or_state_t *new_state)
    333 {
    334  char *err = NULL;
    335  int ret = 0;
    336  tor_assert(new_state);
    337  config_free(get_state_mgr(), global_state);
    338  global_state = new_state;
    339  if (subsystems_set_state(get_state_mgr(), global_state) < 0) {
    340    ret = -1;
    341  }
    342  if (entry_guards_parse_state(global_state, 1, &err)<0) {
    343    log_warn(LD_GENERAL,"%s",err);
    344    tor_free(err);
    345    ret = -1;
    346  }
    347  if (bwhist_load_state(global_state, &err)<0) {
    348    log_warn(LD_GENERAL,"Unparseable bandwidth history state: %s",err);
    349    tor_free(err);
    350    ret = -1;
    351  }
    352  if (circuit_build_times_parse_state(
    353      get_circuit_build_times_mutable(),global_state) < 0) {
    354    ret = -1;
    355  }
    356 
    357  return ret;
    358 }
    359 
    360 /**
    361 * Save a broken state file to a backup location.
    362 */
    363 static void
    364 or_state_save_broken(char *fname)
    365 {
    366  int i, res;
    367  file_status_t status;
    368  char *fname2 = NULL;
    369  for (i = 0; i < 100; ++i) {
    370    tor_asprintf(&fname2, "%s.%d", fname, i);
    371    status = file_status(fname2);
    372    if (status == FN_NOENT)
    373      break;
    374    tor_free(fname2);
    375  }
    376  if (i == 100) {
    377    log_warn(LD_BUG, "Unable to parse state in \"%s\"; too many saved bad "
    378             "state files to move aside. Discarding the old state file.",
    379             fname);
    380    res = unlink(fname);
    381    if (res != 0) {
    382      log_warn(LD_FS,
    383               "Also couldn't discard old state file \"%s\" because "
    384               "unlink() failed: %s",
    385               fname, strerror(errno));
    386    }
    387  } else {
    388    log_warn(LD_BUG, "Unable to parse state in \"%s\". Moving it aside "
    389             "to \"%s\".  This could be a bug in Tor; please tell "
    390             "the developers.", fname, fname2);
    391    if (tor_rename(fname, fname2) < 0) {//XXXX sandbox prohibits
    392      log_warn(LD_BUG, "Weirdly, I couldn't even move the state aside. The "
    393               "OS gave an error of %s", strerror(errno));
    394    }
    395  }
    396  tor_free(fname2);
    397 }
    398 
    399 STATIC or_state_t *
    400 or_state_new(void)
    401 {
    402  or_state_t *new_state = config_new(get_state_mgr());
    403  config_init(get_state_mgr(), new_state);
    404 
    405  return new_state;
    406 }
    407 
    408 /** Reload the persistent state from disk, generating a new state as needed.
    409 * Return 0 on success, less than 0 on failure.
    410 */
    411 int
    412 or_state_load(void)
    413 {
    414  or_state_t *new_state = NULL;
    415  char *contents = NULL, *fname;
    416  char *errmsg = NULL;
    417  int r = -1, badstate = 0;
    418 
    419  fname = get_datadir_fname("state");
    420  switch (file_status(fname)) {
    421    case FN_FILE:
    422      if (!(contents = read_file_to_str(fname, 0, NULL))) {
    423        log_warn(LD_FS, "Unable to read state file \"%s\"", fname);
    424        goto done;
    425      }
    426      break;
    427    /* treat empty state files as if the file doesn't exist, and generate
    428     * a new state file, overwriting the empty file in or_state_save() */
    429    case FN_NOENT:
    430    case FN_EMPTY:
    431      break;
    432    case FN_ERROR:
    433    case FN_DIR:
    434    default:
    435      log_warn(LD_GENERAL,"State file \"%s\" is not a file? Failing.", fname);
    436      goto done;
    437  }
    438  new_state = or_state_new();
    439  if (contents) {
    440    config_line_t *lines=NULL;
    441    int assign_retval;
    442    if (config_get_lines(contents, &lines, 0)<0)
    443      goto done;
    444    assign_retval = config_assign(get_state_mgr(), new_state,
    445                                  lines, 0, &errmsg);
    446    config_free_lines(lines);
    447    if (assign_retval<0)
    448      badstate = 1;
    449    if (errmsg) {
    450      log_warn(LD_GENERAL, "%s", errmsg);
    451      tor_free(errmsg);
    452    }
    453  }
    454 
    455  if (!badstate && or_state_validate(new_state, &errmsg) < 0)
    456    badstate = 1;
    457 
    458  if (errmsg) {
    459    log_warn(LD_GENERAL, "%s", errmsg);
    460    tor_free(errmsg);
    461  }
    462 
    463  if (badstate && !contents) {
    464    log_warn(LD_BUG, "Uh oh.  We couldn't even validate our own default state."
    465             " This is a bug in Tor.");
    466    goto done;
    467  } else if (badstate && contents) {
    468    or_state_save_broken(fname);
    469 
    470    tor_free(contents);
    471    config_free(get_state_mgr(), new_state);
    472 
    473    new_state = or_state_new();
    474  } else if (contents) {
    475    log_info(LD_GENERAL, "Loaded state from \"%s\"", fname);
    476    /* Warn the user if their clock has been set backwards,
    477     * they could be tricked into using old consensuses */
    478    time_t apparent_skew = time(NULL) - new_state->LastWritten;
    479    if (apparent_skew < 0) {
    480      /* Initialize bootstrap event reporting because we might call
    481       * clock_skew_warning() before the bootstrap state is
    482       * initialized, causing an assertion failure. */
    483      control_event_bootstrap(BOOTSTRAP_STATUS_STARTING, 0);
    484      clock_skew_warning(NULL, (long)apparent_skew, 1, LD_GENERAL,
    485                         "local state file", fname);
    486    }
    487  } else {
    488    log_info(LD_GENERAL, "Initialized state");
    489  }
    490  or_state_remove_obsolete_lines(&new_state->ExtraLines);
    491  if (or_state_set(new_state) == -1) {
    492    or_state_save_broken(fname);
    493  }
    494  new_state = NULL;
    495  if (!contents) {
    496    global_state->next_write = 0;
    497    or_state_save(time(NULL));
    498  }
    499  r = 0;
    500 
    501 done:
    502  tor_free(fname);
    503  tor_free(contents);
    504  if (new_state)
    505    config_free(get_state_mgr(), new_state);
    506 
    507  return r;
    508 }
    509 
    510 /** Remove from `extra_lines` every element whose key appears in
    511 * `obsolete_state_keys`. */
    512 STATIC void
    513 or_state_remove_obsolete_lines(config_line_t **extra_lines)
    514 {
    515  /* make a strmap for the obsolete state names, so we can have O(1)
    516     lookup. */
    517  strmap_t *bad_keys = strmap_new();
    518  for (unsigned i = 0; obsolete_state_keys[i] != NULL; ++i) {
    519    strmap_set_lc(bad_keys, obsolete_state_keys[i], (void*)"rmv");
    520  }
    521 
    522  config_line_t **line = extra_lines;
    523  while (*line) {
    524    if (strmap_get_lc(bad_keys, (*line)->key) != NULL) {
    525      /* This key is obsolete; remove it. */
    526      config_line_t *victim = *line;
    527      *line = (*line)->next;
    528 
    529      victim->next = NULL; // prevent double-free.
    530      config_free_lines(victim);
    531    } else {
    532      /* This is just an unrecognized key; keep it. */
    533      line = &(*line)->next;
    534    }
    535  }
    536 
    537  strmap_free(bad_keys, NULL);
    538 }
    539 
    540 /** Did the last time we tried to write the state file fail? If so, we
    541 * should consider disabling such features as preemptive circuit generation
    542 * to compute circuit-build-time. */
    543 static int last_state_file_write_failed = 0;
    544 
    545 /** Return whether the state file failed to write last time we tried. */
    546 int
    547 did_last_state_file_write_fail(void)
    548 {
    549  return last_state_file_write_failed;
    550 }
    551 
    552 /** If writing the state to disk fails, try again after this many seconds. */
    553 #define STATE_WRITE_RETRY_INTERVAL 3600
    554 
    555 /** If we're a relay, how often should we checkpoint our state file even
    556 * if nothing else dirties it? This will checkpoint ongoing stats like
    557 * bandwidth used, per-country user stats, etc. */
    558 #define STATE_RELAY_CHECKPOINT_INTERVAL (12*60*60)
    559 
    560 /** Write the persistent state to disk. Return 0 for success, <0 on failure. */
    561 int
    562 or_state_save(time_t now)
    563 {
    564  char *state, *contents;
    565  char tbuf[ISO_TIME_LEN+1];
    566  char *fname;
    567 
    568  tor_assert(global_state);
    569 
    570  if (global_state->next_write > now)
    571    return 0;
    572 
    573  /* Call everything else that might dirty the state even more, in order
    574   * to avoid redundant writes. */
    575  (void) subsystems_flush_state(get_state_mgr(), global_state);
    576  entry_guards_update_state(global_state);
    577  bwhist_update_state(global_state);
    578  circuit_build_times_update_state(get_circuit_build_times(), global_state);
    579 
    580  if (accounting_is_enabled(get_options()))
    581    accounting_run_housekeeping(now);
    582 
    583  global_state->LastWritten = now;
    584 
    585  tor_free(global_state->TorVersion);
    586  tor_asprintf(&global_state->TorVersion, "Tor %s", get_version());
    587 
    588  state = config_dump(get_state_mgr(), NULL, global_state, 1, 0);
    589  format_local_iso_time(tbuf, now);
    590  tor_asprintf(&contents,
    591               "# Tor state file last generated on %s local time\n"
    592               "# Other times below are in UTC\n"
    593               "# You *do not* need to edit this file.\n\n%s",
    594               tbuf, state);
    595  tor_free(state);
    596  fname = get_datadir_fname("state");
    597  if (write_str_to_file(fname, contents, 0)<0) {
    598    log_warn(LD_FS, "Unable to write state to file \"%s\"; "
    599             "will try again later", fname);
    600    last_state_file_write_failed = 1;
    601    tor_free(fname);
    602    tor_free(contents);
    603    /* Try again after STATE_WRITE_RETRY_INTERVAL (or sooner, if the state
    604     * changes sooner). */
    605    global_state->next_write = now + STATE_WRITE_RETRY_INTERVAL;
    606    return -1;
    607  }
    608 
    609  last_state_file_write_failed = 0;
    610  log_info(LD_GENERAL, "Saved state to \"%s\"", fname);
    611  tor_free(fname);
    612  tor_free(contents);
    613 
    614  if (server_mode(get_options()))
    615    global_state->next_write = now + STATE_RELAY_CHECKPOINT_INTERVAL;
    616  else
    617    global_state->next_write = TIME_MAX;
    618 
    619  return 0;
    620 }
    621 
    622 /** Return the config line for transport <b>transport</b> in the current state.
    623 *  Return NULL if there is no config line for <b>transport</b>. */
    624 STATIC config_line_t *
    625 get_transport_in_state_by_name(const char *transport)
    626 {
    627  or_state_t *or_state = get_or_state();
    628  config_line_t *line;
    629  config_line_t *ret = NULL;
    630  smartlist_t *items = NULL;
    631 
    632  for (line = or_state->TransportProxies ; line ; line = line->next) {
    633    tor_assert(!strcmp(line->key, "TransportProxy"));
    634 
    635    items = smartlist_new();
    636    smartlist_split_string(items, line->value, NULL,
    637                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
    638    if (smartlist_len(items) != 2) /* broken state */
    639      goto done;
    640 
    641    if (!strcmp(smartlist_get(items, 0), transport)) {
    642      ret = line;
    643      goto done;
    644    }
    645 
    646    SMARTLIST_FOREACH(items, char*, s, tor_free(s));
    647    smartlist_free(items);
    648    items = NULL;
    649  }
    650 
    651 done:
    652  if (items) {
    653    SMARTLIST_FOREACH(items, char*, s, tor_free(s));
    654    smartlist_free(items);
    655  }
    656  return ret;
    657 }
    658 
    659 /** Return string containing the address:port part of the
    660 *  TransportProxy <b>line</b> for transport <b>transport</b>.
    661 *  If the line is corrupted, return NULL. */
    662 static const char *
    663 get_transport_bindaddr(const char *line, const char *transport)
    664 {
    665  char *line_tmp = NULL;
    666 
    667  if (strlen(line) < strlen(transport) + 2) {
    668    goto broken_state;
    669  } else {
    670    /* line should start with the name of the transport and a space.
    671       (for example, "obfs2 127.0.0.1:47245") */
    672    tor_asprintf(&line_tmp, "%s ", transport);
    673    if (strcmpstart(line, line_tmp))
    674      goto broken_state;
    675 
    676    tor_free(line_tmp);
    677    return (line+strlen(transport)+1);
    678  }
    679 
    680 broken_state:
    681  tor_free(line_tmp);
    682  return NULL;
    683 }
    684 
    685 /** Return a string containing the address:port that a proxy transport
    686 *  should bind on. The string is stored on the heap and must be freed
    687 *  by the caller of this function. */
    688 char *
    689 get_stored_bindaddr_for_server_transport(const char *transport)
    690 {
    691  char *default_addrport = NULL;
    692  const char *stored_bindaddr = NULL;
    693  config_line_t *line = NULL;
    694 
    695  {
    696    /* See if the user explicitly asked for a specific listening
    697       address for this transport. */
    698    char *conf_bindaddr = pt_get_bindaddr_from_config(transport);
    699    if (conf_bindaddr)
    700      return conf_bindaddr;
    701  }
    702 
    703  line = get_transport_in_state_by_name(transport);
    704  if (!line) /* Found no references in state for this transport. */
    705    goto no_bindaddr_found;
    706 
    707  stored_bindaddr = get_transport_bindaddr(line->value, transport);
    708  if (stored_bindaddr) /* found stored bindaddr in state file. */
    709    return tor_strdup(stored_bindaddr);
    710 
    711 no_bindaddr_found:
    712  /** If we didn't find references for this pluggable transport in the
    713      state file, we should instruct the pluggable transport proxy to
    714      listen on INADDR_ANY on a random ephemeral port. */
    715  tor_asprintf(&default_addrport, "%s:%s", fmt_addr32(INADDR_ANY), "0");
    716  return default_addrport;
    717 }
    718 
    719 /** Save <b>transport</b> listening on <b>addr</b>:<b>port</b> to
    720    state */
    721 void
    722 save_transport_to_state(const char *transport,
    723                        const tor_addr_t *addr, uint16_t port)
    724 {
    725  or_state_t *state = get_or_state();
    726 
    727  char *transport_addrport=NULL;
    728 
    729  /** find where to write on the state */
    730  config_line_t **next, *line;
    731 
    732  /* see if this transport is already stored in state */
    733  config_line_t *transport_line =
    734    get_transport_in_state_by_name(transport);
    735 
    736  if (transport_line) { /* if transport already exists in state... */
    737    const char *prev_bindaddr = /* get its addrport... */
    738      get_transport_bindaddr(transport_line->value, transport);
    739    transport_addrport = tor_strdup(fmt_addrport(addr, port));
    740 
    741    /* if transport in state has the same address as this one, life is good */
    742    if (!strcmp(prev_bindaddr, transport_addrport)) {
    743      log_info(LD_CONFIG, "Transport seems to have spawned on its usual "
    744               "address:port.");
    745      goto done;
    746    } else { /* if addrport in state is different than the one we got */
    747      log_info(LD_CONFIG, "Transport seems to have spawned on different "
    748               "address:port. Let's update the state file with the new "
    749               "address:port");
    750      tor_free(transport_line->value); /* free the old line */
    751      /* replace old addrport line with new line */
    752      tor_asprintf(&transport_line->value, "%s %s", transport,
    753                   fmt_addrport(addr, port));
    754    }
    755  } else { /* never seen this one before; save it in state for next time */
    756    log_info(LD_CONFIG, "It's the first time we see this transport. "
    757             "Let's save its address:port");
    758    next = &state->TransportProxies;
    759    /* find the last TransportProxy line in the state and point 'next'
    760       right after it  */
    761    line = state->TransportProxies;
    762    while (line) {
    763      next = &(line->next);
    764      line = line->next;
    765    }
    766 
    767    /* allocate space for the new line and fill it in */
    768    *next = line = tor_malloc_zero(sizeof(config_line_t));
    769    line->key = tor_strdup("TransportProxy");
    770    tor_asprintf(&line->value, "%s %s", transport, fmt_addrport(addr, port));
    771  }
    772 
    773  if (!get_options()->AvoidDiskWrites)
    774    or_state_mark_dirty(state, 0);
    775 
    776 done:
    777  tor_free(transport_addrport);
    778 }
    779 
    780 /** Change the next_write time of <b>state</b> to <b>when</b>, unless the
    781 * state is already scheduled to be written to disk earlier than <b>when</b>.
    782 */
    783 void
    784 or_state_mark_dirty(or_state_t *state, time_t when)
    785 {
    786  if (state->next_write > when) {
    787    state->next_write = when;
    788    reschedule_or_state_save();
    789  }
    790 }
    791 
    792 STATIC void
    793 or_state_free_(or_state_t *state)
    794 {
    795  if (!state)
    796    return;
    797 
    798  config_free(get_state_mgr(), state);
    799 }
    800 
    801 void
    802 or_state_free_all(void)
    803 {
    804  or_state_free(global_state);
    805  global_state = NULL;
    806  config_mgr_free(state_mgr);
    807 }