Tor 0.4.9.0-alpha-dev
statefile.c
Go to the documentation of this file.
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"
34#include "app/config/config.h"
36#include "lib/confmgt/confmgt.h"
46#include "lib/sandbox/sandbox.h"
48#include "app/main/subsysmgr.h"
50#include "lib/net/resolve.h"
52
54
55#ifdef HAVE_UNISTD_H
56#include <unistd.h>
57#endif
58
59/** A list of state-file "abbreviations," for compatibility. */
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 * */
70static 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. */
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
104static 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
157};
158// clang-format on
159
160#undef VAR
161#undef V
162
163static int or_state_validate(or_state_t *state, char **msg);
164
165static 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. */
174 .name = "__extra",
175 .type = CONFIG_TYPE_LINELIST,
176 .offset = offsetof(or_state_t, ExtraLines),
177};
178
179/** Configuration format for or_state_t. */
181 .size = sizeof(or_state_t),
182 .magic = {
183 "or_state_t",
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 */
196static config_mgr_t *state_mgr = NULL;
197
198/** Return the configuration manager for state-file objects. */
199STATIC const config_mgr_t *
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. */
217
218/** Return the persistent state struct for this Tor. */
221{
223 return global_state;
224}
225
226/** Return true iff we have loaded the global state for this Tor */
227int
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. */
235static int
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. */
278static int
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 */
301static int
302or_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 */
311static int
312or_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> */
331static int
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;
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 }
354 ret = -1;
355 }
356
357 return ret;
358}
359
360/**
361 * Save a broken state file to a backup location.
362 */
363static void
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
400or_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 */
411int
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) {
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 }
491 if (or_state_set(new_state) == -1) {
493 }
494 new_state = NULL;
495 if (!contents) {
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`. */
512STATIC void
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. */
544
545/** Return whether the state file failed to write last time we tried. */
546int
548{
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. */
561int
562or_state_save(time_t now)
563{
564 char *state, *contents;
565 char tbuf[ISO_TIME_LEN+1];
566 char *fname;
567
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. */
579
582
584
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);
601 tor_free(fname);
602 tor_free(contents);
603 /* Try again after STATE_WRITE_RETRY_INTERVAL (or sooner, if the state
604 * changes sooner). */
606 return -1;
607 }
608
610 log_info(LD_GENERAL, "Saved state to \"%s\"", fname);
611 tor_free(fname);
612 tor_free(contents);
613
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>. */
625get_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. */
662static const char *
663get_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. */
688char *
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 */
721void
722save_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 =
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 */
783void
784or_state_mark_dirty(or_state_t *state, time_t when)
785{
786 if (state->next_write > when) {
787 state->next_write = when;
789 }
790}
791
792STATIC void
793or_state_free_(or_state_t *state)
794{
795 if (!state)
796 return;
797
798 config_free(get_state_mgr(), state);
799}
800
801void
802or_state_free_all(void)
803{
804 or_state_free(global_state);
805 global_state = NULL;
806 config_mgr_free(state_mgr);
807}
const char * fmt_addrport(const tor_addr_t *addr, uint16_t port)
Definition: address.c:1199
const char * fmt_addr32(uint32_t addr)
Definition: address.c:1210
void bwhist_update_state(or_state_t *state)
Definition: bwhist.c:411
int bwhist_load_state(or_state_t *state, char **err)
Definition: bwhist.c:513
Header for feature/stats/bwhist.c.
circuit_build_times_t * get_circuit_build_times_mutable(void)
Definition: circuitstats.c:85
int circuit_build_times_parse_state(circuit_build_times_t *cbt, or_state_t *state)
const circuit_build_times_t * get_circuit_build_times(void)
Definition: circuitstats.c:78
void circuit_build_times_update_state(const circuit_build_times_t *cbt, or_state_t *state)
Definition: circuitstats.c:917
Header file for circuitstats.c.
const or_options_t * get_options(void)
Definition: config.c:944
#define VAR(varname, conftype, member, initvalue)
Definition: config.c:263
Header file for config.c.
int config_get_lines(const char *string, config_line_t **result, int extended)
Definition: confline.c:200
Header for confline.c.
#define END_OF_CONFIG_VARS
Definition: confmacros.h:22
void config_init(const config_mgr_t *mgr, void *options)
Definition: confmgt.c:1158
void config_mgr_freeze(config_mgr_t *mgr)
Definition: confmgt.c:285
validation_status_t config_validate(const config_mgr_t *mgr, const void *old_options, void *options, char **msg_out)
Definition: confmgt.c:1272
int config_assign(const config_mgr_t *mgr, void *options, config_line_t *list, unsigned config_assign_flags, char **msg)
Definition: confmgt.c:937
char * config_dump(const config_mgr_t *mgr, const void *default_options, const void *options, int minimal, int comment_defaults)
Definition: confmgt.c:1314
config_mgr_t * config_mgr_new(const config_format_t *toplevel_fmt)
Definition: confmgt.c:145
void * config_new(const config_mgr_t *mgr)
Definition: confmgt.c:387
Header for confmgt.c.
@ CONFIG_TYPE_LINELIST
Definition: conftypes.h:61
void clock_skew_warning(const connection_t *conn, long apparent_skew, int trusted, log_domain_mask_t domain, const char *received, const char *source)
Definition: connection.c:5963
Header file for connection.c.
void control_event_bootstrap(bootstrap_status_t status, int progress)
Header file for control_events.c.
void entry_guards_update_state(or_state_t *state)
Definition: entrynodes.c:3683
int entry_guards_parse_state(or_state_t *state, int set, char **msg)
Definition: entrynodes.c:3616
Header file for circuitbuild.c.
int write_str_to_file(const char *fname, const char *str, int bin)
Definition: files.c:275
file_status_t file_status(const char *filename)
Definition: files.c:213
file_status_t
Definition: files.h:55
int tor_rename(const char *path_old, const char *path_new)
Definition: files.c:104
int accounting_is_enabled(const or_options_t *options)
Definition: hibernate.c:305
void accounting_run_housekeeping(time_t now)
Definition: hibernate.c:585
Header file for hibernate.c.
#define LD_FS
Definition: log.h:70
#define LD_BUG
Definition: log.h:86
#define LD_GENERAL
Definition: log.h:62
#define LD_CONFIG
Definition: log.h:68
void reschedule_or_state_save(void)
Definition: mainloop.c:1936
Header file for mainloop.c.
#define tor_free(p)
Definition: malloc.h:56
void * strmap_get_lc(const strmap_t *map, const char *key)
Definition: map.c:360
void * strmap_set_lc(strmap_t *map, const char *key, void *val)
Definition: map.c:346
Header for netstatus.c.
Master header file for Tor-specific functionality.
The or_state_t structure, which represents Tor's state file.
int tor_asprintf(char **strp, const char *fmt,...)
Definition: printf.c:75
int tor_addr_port_lookup(const char *s, tor_addr_t *addr_out, uint16_t *port_out)
Definition: resolve.c:252
Header for resolve.c.
Header file for router.c.
int server_mode(const or_options_t *options)
Definition: routermode.c:34
Header file for routermode.c.
Header file for sandbox.c.
smartlist_t * smartlist_new(void)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, int flags, int max)
#define STATE_WRITE_RETRY_INTERVAL
Definition: statefile.c:553
static const char * get_transport_bindaddr(const char *line, const char *transport)
Definition: statefile.c:663
int or_state_loaded(void)
Definition: statefile.c:228
char * get_stored_bindaddr_for_server_transport(const char *transport)
Definition: statefile.c:689
static const config_format_t state_format
Definition: statefile.c:180
void save_transport_to_state(const char *transport, const tor_addr_t *addr, uint16_t port)
Definition: statefile.c:722
int or_state_load(void)
Definition: statefile.c:412
void or_state_mark_dirty(or_state_t *state, time_t when)
Definition: statefile.c:784
STATIC void or_state_remove_obsolete_lines(config_line_t **extra_lines)
Definition: statefile.c:513
static const char * obsolete_state_keys[]
Definition: statefile.c:70
static int last_state_file_write_failed
Definition: statefile.c:543
static const config_var_t state_vars_[]
Definition: statefile.c:104
#define OR_STATE_MAGIC
Definition: statefile.c:169
int did_last_state_file_write_fail(void)
Definition: statefile.c:547
static struct_member_t state_extra_var
Definition: statefile.c:173
STATIC config_line_t * get_transport_in_state_by_name(const char *transport)
Definition: statefile.c:625
static config_abbrev_t state_abbrevs_[]
Definition: statefile.c:60
static void or_state_save_broken(char *fname)
Definition: statefile.c:364
or_state_t * get_or_state(void)
Definition: statefile.c:220
#define STATE_RELAY_CHECKPOINT_INTERVAL
Definition: statefile.c:558
static int validate_transports_in_state(or_state_t *state)
Definition: statefile.c:279
int or_state_save(time_t now)
Definition: statefile.c:562
static int state_transport_line_is_valid(const char *line)
Definition: statefile.c:236
STATIC const config_mgr_t * get_state_mgr(void)
Definition: statefile.c:200
static int or_state_set(or_state_t *new_state)
Definition: statefile.c:332
DUMMY_TYPECHECK_INSTANCE(or_state_t)
static int or_state_validate_cb(const void *old_options, void *options, char **msg)
Definition: statefile.c:312
static or_state_t * global_state
Definition: statefile.c:216
static int or_state_validate(or_state_t *state, char **msg)
Definition: statefile.c:302
Header for statefile.c.
time_t next_write
Definition: or_state_st.h:26
char * TorVersion
Definition: or_state_st.h:85
time_t LastWritten
Definition: or_state_st.h:29
struct config_line_t * ExtraLines
Definition: or_state_st.h:89
const char * name
Definition: conftypes.h:98
int subsystems_register_state_formats(config_mgr_t *mgr)
Definition: subsysmgr.c:339
int subsystems_set_state(const config_mgr_t *mgr, struct or_state_t *state)
Definition: subsysmgr.c:437
int subsystems_flush_state(const config_mgr_t *mgr, struct or_state_t *state)
Definition: subsysmgr.c:461
Header for subsysmgr.c.
#define STATIC
Definition: testsupport.h:32
#define MOCK_IMPL(rv, funcname, arglist)
Definition: testsupport.h:133
void format_local_iso_time(char *buf, time_t t)
Definition: time_fmt.c:316
Header for version.c.
const char * get_version(void)
Definition: version.c:38
char * pt_get_bindaddr_from_config(const char *transport)
Header for feature/relay/transport_config.c.
#define tor_assert(expr)
Definition: util_bug.h:103
int strcmpstart(const char *s1, const char *s2)
Definition: util_string.c:217