aboutsummaryrefslogtreecommitdiff
path: root/src/feature/dirauth/dirauth_periodic.c
blob: 19e51c5a05760e038410b7a66345fe8256447192 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/* Copyright (c) 2001 Matej Pfajfar.
 * Copyright (c) 2001-2004, Roger Dingledine.
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
 * Copyright (c) 2007-2020, The Tor Project, Inc. */
/* See LICENSE for licensing information */

/**
 * @file dirauth_periodic.c
 * @brief Peridoic events for directory authorities.
 **/

#include "core/or/or.h"

#include "app/config/or_options_st.h"
#include "core/mainloop/netstatus.h"
#include "feature/dirauth/reachability.h"
#include "feature/stats/rephist.h"

#include "feature/dirauth/bridgeauth.h"
#include "feature/dirauth/dirvote.h"
#include "feature/dirauth/dirauth_periodic.h"
#include "feature/dirauth/authmode.h"

#include "core/mainloop/periodic.h"

#ifndef COCCI
#define DECLARE_EVENT(name, roles, flags)         \
  static periodic_event_item_t name ## _event =   \
    PERIODIC_EVENT(name,                          \
                   PERIODIC_EVENT_ROLE_##roles,   \
                   flags)
#endif /* !defined(COCCI) */

#define FL(name) (PERIODIC_EVENT_FLAG_##name)

/**
 * Periodic callback: if we're an authority, check on our authority
 * certificate (the one that authenticates our authority signing key).
 */
static int
check_authority_cert_callback(time_t now, const or_options_t *options)
{
  (void)now;
  (void)options;
  /* 1e. Periodically, if we're a v3 authority, we check whether our cert is
   * close to expiring and warn the admin if it is. */
  v3_authority_check_key_expiry();
#define CHECK_V3_CERTIFICATE_INTERVAL (5*60)
  return CHECK_V3_CERTIFICATE_INTERVAL;
}

DECLARE_EVENT(check_authority_cert, DIRAUTH, 0);

/**
 * Scheduled callback: Run directory-authority voting functionality.
 *
 * The schedule is a bit complicated here, so dirvote_act() manages the
 * schedule itself.
 **/
static int
dirvote_callback(time_t now, const or_options_t *options)
{
  if (!authdir_mode_v3(options)) {
    tor_assert_nonfatal_unreached();
    return 3600;
  }

  time_t next = dirvote_act(options, now);
  if (BUG(next == TIME_MAX)) {
    /* This shouldn't be returned unless we called dirvote_act() without
     * being an authority.  If it happens, maybe our configuration will
     * fix itself in an hour or so? */
    return 3600;
  }
  return safe_timer_diff(now, next);
}

DECLARE_EVENT(dirvote, DIRAUTH, FL(NEED_NET));

/** Reschedule the directory-authority voting event.  Run this whenever the
 * schedule has changed. */
void
reschedule_dirvote(const or_options_t *options)
{
  if (authdir_mode_v3(options)) {
    periodic_event_reschedule(&dirvote_event);
  }
}

/**
 * Periodic callback: if we're an authority, record our measured stability
 * information from rephist in an mtbf file.
 */
static int
save_stability_callback(time_t now, const or_options_t *options)
{
  if (authdir_mode_tests_reachability(options)) {
    if (rep_hist_record_mtbf_data(now, 1)<0) {
      log_warn(LD_GENERAL, "Couldn't store mtbf data.");
    }
  }
#define SAVE_STABILITY_INTERVAL (30*60)
  return SAVE_STABILITY_INTERVAL;
}

DECLARE_EVENT(save_stability, AUTHORITIES, 0);

/**
 * Periodic callback: if we're an authority, make sure we test
 * the routers on the network for reachability.
 */
static int
launch_reachability_tests_callback(time_t now, const or_options_t *options)
{
  if (authdir_mode_tests_reachability(options) &&
      !net_is_disabled()) {
    /* try to determine reachability of the other Tor relays */
    dirserv_test_reachability(now);
  }
  return REACHABILITY_TEST_INTERVAL;
}

DECLARE_EVENT(launch_reachability_tests, AUTHORITIES, FL(NEED_NET));

/**
 * Periodic callback: if we're an authority, discount the stability
 * information (and other rephist information) that's older.
 */
static int
downrate_stability_callback(time_t now, const or_options_t *options)
{
  (void)options;
  /* 1d. Periodically, we discount older stability information so that new
   * stability info counts more, and save the stability information to disk as
   * appropriate. */
  time_t next = rep_hist_downrate_old_runs(now);
  return safe_timer_diff(now, next);
}

DECLARE_EVENT(downrate_stability, AUTHORITIES, 0);

/**
 * Periodic callback: if we're the bridge authority, write a networkstatus
 * file to disk.
 */
static int
write_bridge_ns_callback(time_t now, const or_options_t *options)
{
  if (options->BridgeAuthoritativeDir) {
    bridgeauth_dump_bridge_status_to_file(now);
#define BRIDGE_STATUSFILE_INTERVAL (30*60)
     return BRIDGE_STATUSFILE_INTERVAL;
  }
  return PERIODIC_EVENT_NO_UPDATE;
}

DECLARE_EVENT(write_bridge_ns, BRIDGEAUTH, 0);

void
dirauth_register_periodic_events(void)
{
  periodic_events_register(&downrate_stability_event);
  periodic_events_register(&launch_reachability_tests_event);
  periodic_events_register(&save_stability_event);
  periodic_events_register(&check_authority_cert_event);
  periodic_events_register(&dirvote_event);
  periodic_events_register(&write_bridge_ns_event);
}