/src/tor/src/feature/dirauth/voteflags.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (c) 2001-2004, Roger Dingledine. |
2 | | * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. |
3 | | * Copyright (c) 2007-2021, The Tor Project, Inc. */ |
4 | | /* See LICENSE for licensing information */ |
5 | | |
6 | | /** |
7 | | * \file voteflags.c |
8 | | * \brief Authority code for deciding the performance thresholds for flags, |
9 | | * and assigning flags to routers. |
10 | | **/ |
11 | | |
12 | | #define VOTEFLAGS_PRIVATE |
13 | | #include "core/or/or.h" |
14 | | #include "feature/dirauth/voteflags.h" |
15 | | |
16 | | #include "app/config/config.h" |
17 | | #include "core/mainloop/mainloop.h" |
18 | | #include "core/or/policies.h" |
19 | | #include "feature/dirauth/bwauth.h" |
20 | | #include "feature/dirauth/reachability.h" |
21 | | #include "feature/dirauth/dirauth_sys.h" |
22 | | #include "feature/hibernate/hibernate.h" |
23 | | #include "feature/nodelist/dirlist.h" |
24 | | #include "feature/nodelist/networkstatus.h" |
25 | | #include "feature/nodelist/nodelist.h" |
26 | | #include "feature/nodelist/routerlist.h" |
27 | | #include "feature/nodelist/routerset.h" |
28 | | #include "feature/relay/router.h" |
29 | | #include "feature/stats/rephist.h" |
30 | | |
31 | | #include "feature/dirauth/dirauth_options_st.h" |
32 | | #include "feature/nodelist/node_st.h" |
33 | | #include "feature/nodelist/routerinfo_st.h" |
34 | | #include "feature/nodelist/routerlist_st.h" |
35 | | #include "feature/nodelist/vote_routerstatus_st.h" |
36 | | |
37 | | #include "lib/container/order.h" |
38 | | |
39 | | /* Thresholds for server performance: set by |
40 | | * dirserv_compute_performance_thresholds, and used by |
41 | | * generate_v2_networkstatus */ |
42 | | |
43 | | /** Any router with an uptime of at least this value is stable. */ |
44 | | static uint32_t stable_uptime = 0; /* start at a safe value */ |
45 | | /** Any router with an mtbf of at least this value is stable. */ |
46 | | static double stable_mtbf = 0.0; |
47 | | /** If true, we have measured enough mtbf info to look at stable_mtbf rather |
48 | | * than stable_uptime. */ |
49 | | static int enough_mtbf_info = 0; |
50 | | /** Any router with a weighted fractional uptime of at least this much might |
51 | | * be good as a guard. */ |
52 | | static double guard_wfu = 0.0; |
53 | | /** Don't call a router a guard unless we've known about it for at least this |
54 | | * many seconds. */ |
55 | | static long guard_tk = 0; |
56 | | /** Any router with a bandwidth at least this high is "Fast" */ |
57 | | static uint32_t fast_bandwidth_kb = 0; |
58 | | /** If exits can be guards, then all guards must have a bandwidth this |
59 | | * high. */ |
60 | | static uint32_t guard_bandwidth_including_exits_kb = 0; |
61 | | /** If exits can't be guards, then all guards must have a bandwidth this |
62 | | * high. */ |
63 | | static uint32_t guard_bandwidth_excluding_exits_kb = 0; |
64 | | |
65 | | /** Helper: estimate the uptime of a router given its stated uptime and the |
66 | | * amount of time since it last stated its stated uptime. */ |
67 | | static inline long |
68 | | real_uptime(const routerinfo_t *router, time_t now) |
69 | 0 | { |
70 | 0 | if (now < router->cache_info.published_on) |
71 | 0 | return router->uptime; |
72 | 0 | else |
73 | 0 | return router->uptime + (now - router->cache_info.published_on); |
74 | 0 | } |
75 | | |
76 | | /** Return 1 if <b>router</b> is not suitable for these parameters, else 0. |
77 | | * If <b>need_uptime</b> is non-zero, we require a minimum uptime. |
78 | | * If <b>need_capacity</b> is non-zero, we require a minimum advertised |
79 | | * bandwidth. |
80 | | */ |
81 | | static int |
82 | | dirserv_thinks_router_is_unreliable(time_t now, |
83 | | const routerinfo_t *router, |
84 | | int need_uptime, int need_capacity) |
85 | 0 | { |
86 | 0 | if (need_uptime) { |
87 | 0 | if (!enough_mtbf_info) { |
88 | | /* XXXX We should change the rule from |
89 | | * "use uptime if we don't have mtbf data" to "don't advertise Stable on |
90 | | * v3 if we don't have enough mtbf data." Or maybe not, since if we ever |
91 | | * hit a point where we need to reset a lot of authorities at once, |
92 | | * none of them would be in a position to declare Stable. |
93 | | */ |
94 | 0 | long uptime = real_uptime(router, now); |
95 | 0 | if ((unsigned)uptime < stable_uptime && |
96 | 0 | uptime < dirauth_get_options()->AuthDirVoteStableGuaranteeMinUptime) |
97 | 0 | return 1; |
98 | 0 | } else { |
99 | 0 | double mtbf = |
100 | 0 | rep_hist_get_stability(router->cache_info.identity_digest, now); |
101 | 0 | if (mtbf < stable_mtbf && |
102 | 0 | mtbf < dirauth_get_options()->AuthDirVoteStableGuaranteeMTBF) |
103 | 0 | return 1; |
104 | 0 | } |
105 | 0 | } |
106 | 0 | if (need_capacity) { |
107 | 0 | uint32_t bw_kb = dirserv_get_credible_bandwidth_kb(router); |
108 | 0 | if (bw_kb < fast_bandwidth_kb) |
109 | 0 | return 1; |
110 | 0 | } |
111 | 0 | return 0; |
112 | 0 | } |
113 | | |
114 | | /** Return 1 if <b>ri</b>'s descriptor is "active" -- running, valid, |
115 | | * not hibernating, and not too old. Else return 0. |
116 | | */ |
117 | | static int |
118 | | router_is_active(const routerinfo_t *ri, const node_t *node, time_t now) |
119 | 0 | { |
120 | 0 | time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH; |
121 | 0 | if (ri->cache_info.published_on < cutoff) { |
122 | 0 | return 0; |
123 | 0 | } |
124 | 0 | if (!node->is_running || !node->is_valid || ri->is_hibernating) { |
125 | 0 | return 0; |
126 | 0 | } |
127 | 0 | return 1; |
128 | 0 | } |
129 | | |
130 | | /** Return true iff <b>router</b> should be assigned the "HSDir" flag. |
131 | | * |
132 | | * Right now this means it advertises support for it, it has a high uptime, |
133 | | * it's a directory cache, it has the Stable and Fast flags, and it's currently |
134 | | * considered Running. |
135 | | * |
136 | | * This function needs to be called after router-\>is_running has |
137 | | * been set. |
138 | | */ |
139 | | static int |
140 | | dirserv_thinks_router_is_hs_dir(const routerinfo_t *router, |
141 | | const node_t *node, time_t now) |
142 | 0 | { |
143 | |
|
144 | 0 | long uptime; |
145 | | |
146 | | /* If we haven't been running for at least |
147 | | * MinUptimeHidServDirectoryV2 seconds, we can't |
148 | | * have accurate data telling us a relay has been up for at least |
149 | | * that long. We also want to allow a bit of slack: Reachability |
150 | | * tests aren't instant. If we haven't been running long enough, |
151 | | * trust the relay. */ |
152 | |
|
153 | 0 | if (get_uptime() > |
154 | 0 | dirauth_get_options()->MinUptimeHidServDirectoryV2 * 1.1) |
155 | 0 | uptime = MIN(rep_hist_get_uptime(router->cache_info.identity_digest, now), |
156 | 0 | real_uptime(router, now)); |
157 | 0 | else |
158 | 0 | uptime = real_uptime(router, now); |
159 | |
|
160 | 0 | return (router->wants_to_be_hs_dir && |
161 | 0 | router->supports_tunnelled_dir_requests && |
162 | 0 | node->is_stable && node->is_fast && |
163 | 0 | uptime >= dirauth_get_options()->MinUptimeHidServDirectoryV2 && |
164 | 0 | router_is_active(router, node, now)); |
165 | 0 | } |
166 | | |
167 | | /** Don't consider routers with less bandwidth than this when computing |
168 | | * thresholds. */ |
169 | 0 | #define ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER_KB 4 |
170 | | |
171 | | /** Helper for dirserv_compute_performance_thresholds(): Decide whether to |
172 | | * include a router in our calculations, and return true iff we should; the |
173 | | * require_mbw parameter is passed in by |
174 | | * dirserv_compute_performance_thresholds() and controls whether we ever |
175 | | * count routers with only advertised bandwidths */ |
176 | | static int |
177 | | router_counts_toward_thresholds(const node_t *node, time_t now, |
178 | | const digestmap_t *omit_as_sybil, |
179 | | int require_mbw) |
180 | 0 | { |
181 | | /* Have measured bw? */ |
182 | 0 | int have_mbw = |
183 | 0 | dirserv_has_measured_bw(node->identity); |
184 | 0 | uint64_t min_bw_kb = ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER_KB; |
185 | 0 | const or_options_t *options = get_options(); |
186 | 0 | const dirauth_options_t *dirauth_options = dirauth_get_options(); |
187 | |
|
188 | 0 | if (options->TestingTorNetwork) { |
189 | 0 | min_bw_kb = (int64_t)dirauth_options->TestingMinExitFlagThreshold / 1000; |
190 | 0 | } |
191 | |
|
192 | 0 | return node->ri && router_is_active(node->ri, node, now) && |
193 | 0 | !digestmap_get(omit_as_sybil, node->identity) && |
194 | 0 | (dirserv_get_credible_bandwidth_kb(node->ri) >= min_bw_kb) && |
195 | 0 | (have_mbw || !require_mbw); |
196 | 0 | } |
197 | | |
198 | | /** Look through the routerlist, the Mean Time Between Failure history, and |
199 | | * the Weighted Fractional Uptime history, and use them to set thresholds for |
200 | | * the Stable, Fast, and Guard flags. Update the fields stable_uptime, |
201 | | * stable_mtbf, enough_mtbf_info, guard_wfu, guard_tk, fast_bandwidth, |
202 | | * guard_bandwidth_including_exits, and guard_bandwidth_excluding_exits. |
203 | | * |
204 | | * Also, set the is_exit flag of each router appropriately. */ |
205 | | void |
206 | | dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil) |
207 | 0 | { |
208 | 0 | int n_active, n_active_nonexit, n_familiar; |
209 | 0 | uint32_t *uptimes, *bandwidths_kb, *bandwidths_excluding_exits_kb; |
210 | 0 | long *tks; |
211 | 0 | double *mtbfs, *wfus; |
212 | 0 | const smartlist_t *nodelist; |
213 | 0 | time_t now = time(NULL); |
214 | 0 | const or_options_t *options = get_options(); |
215 | 0 | const dirauth_options_t *dirauth_options = dirauth_get_options(); |
216 | | |
217 | | /* Require mbw? */ |
218 | 0 | int require_mbw = |
219 | 0 | (dirserv_get_last_n_measured_bws() > |
220 | 0 | dirauth_options->MinMeasuredBWsForAuthToIgnoreAdvertised) ? 1 : 0; |
221 | | |
222 | | /* initialize these all here, in case there are no routers */ |
223 | 0 | stable_uptime = 0; |
224 | 0 | stable_mtbf = 0; |
225 | 0 | fast_bandwidth_kb = 0; |
226 | 0 | guard_bandwidth_including_exits_kb = 0; |
227 | 0 | guard_bandwidth_excluding_exits_kb = 0; |
228 | 0 | guard_tk = 0; |
229 | 0 | guard_wfu = 0; |
230 | |
|
231 | 0 | nodelist_assert_ok(); |
232 | 0 | nodelist = nodelist_get_list(); |
233 | | |
234 | | /* Initialize arrays that will hold values for each router. We'll |
235 | | * sort them and use that to compute thresholds. */ |
236 | 0 | n_active = n_active_nonexit = 0; |
237 | | /* Uptime for every active router. */ |
238 | 0 | uptimes = tor_calloc(smartlist_len(nodelist), sizeof(uint32_t)); |
239 | | /* Bandwidth for every active router. */ |
240 | 0 | bandwidths_kb = tor_calloc(smartlist_len(nodelist), sizeof(uint32_t)); |
241 | | /* Bandwidth for every active non-exit router. */ |
242 | 0 | bandwidths_excluding_exits_kb = |
243 | 0 | tor_calloc(smartlist_len(nodelist), sizeof(uint32_t)); |
244 | | /* Weighted mean time between failure for each active router. */ |
245 | 0 | mtbfs = tor_calloc(smartlist_len(nodelist), sizeof(double)); |
246 | | /* Time-known for each active router. */ |
247 | 0 | tks = tor_calloc(smartlist_len(nodelist), sizeof(long)); |
248 | | /* Weighted fractional uptime for each active router. */ |
249 | 0 | wfus = tor_calloc(smartlist_len(nodelist), sizeof(double)); |
250 | | |
251 | | /* Now, fill in the arrays. */ |
252 | 0 | SMARTLIST_FOREACH_BEGIN(nodelist, node_t *, node) { |
253 | 0 | if (options->BridgeAuthoritativeDir && |
254 | 0 | node->ri && |
255 | 0 | node->ri->purpose != ROUTER_PURPOSE_BRIDGE) |
256 | 0 | continue; |
257 | | |
258 | 0 | routerinfo_t *ri = node->ri; |
259 | 0 | if (ri) { |
260 | 0 | node->is_exit = (!router_exit_policy_rejects_all(ri) && |
261 | 0 | exit_policy_is_general_exit(ri->exit_policy)); |
262 | 0 | } |
263 | |
|
264 | 0 | if (router_counts_toward_thresholds(node, now, omit_as_sybil, |
265 | 0 | require_mbw)) { |
266 | 0 | const char *id = node->identity; |
267 | 0 | uint32_t bw_kb; |
268 | | |
269 | | /* resolve spurious clang shallow analysis null pointer errors */ |
270 | 0 | tor_assert(ri); |
271 | | |
272 | 0 | uptimes[n_active] = (uint32_t)real_uptime(ri, now); |
273 | 0 | mtbfs[n_active] = rep_hist_get_stability(id, now); |
274 | 0 | tks [n_active] = rep_hist_get_weighted_time_known(id, now); |
275 | 0 | bandwidths_kb[n_active] = bw_kb = dirserv_get_credible_bandwidth_kb(ri); |
276 | 0 | if (!node->is_exit || node->is_bad_exit) { |
277 | 0 | bandwidths_excluding_exits_kb[n_active_nonexit] = bw_kb; |
278 | 0 | ++n_active_nonexit; |
279 | 0 | } |
280 | 0 | ++n_active; |
281 | 0 | } |
282 | 0 | } SMARTLIST_FOREACH_END(node); |
283 | | |
284 | | /* Now, compute thresholds. */ |
285 | 0 | if (n_active) { |
286 | | /* The median uptime is stable. */ |
287 | 0 | stable_uptime = median_uint32(uptimes, n_active); |
288 | | /* The median mtbf is stable, if we have enough mtbf info */ |
289 | 0 | stable_mtbf = median_double(mtbfs, n_active); |
290 | | /* The 12.5th percentile bandwidth is fast. */ |
291 | 0 | fast_bandwidth_kb = find_nth_uint32(bandwidths_kb, n_active, n_active/8); |
292 | | /* (Now bandwidths is sorted.) */ |
293 | 0 | if (fast_bandwidth_kb < RELAY_REQUIRED_MIN_BANDWIDTH/(2 * 1000)) |
294 | 0 | fast_bandwidth_kb = bandwidths_kb[n_active/4]; |
295 | 0 | int nth = (int)(n_active * |
296 | 0 | dirauth_options->AuthDirVoteGuardBwThresholdFraction); |
297 | 0 | guard_bandwidth_including_exits_kb = |
298 | 0 | find_nth_uint32(bandwidths_kb, n_active, nth); |
299 | 0 | guard_tk = find_nth_long(tks, n_active, n_active/8); |
300 | 0 | } |
301 | |
|
302 | 0 | if (guard_tk > dirauth_options->AuthDirVoteGuardGuaranteeTimeKnown) |
303 | 0 | guard_tk = dirauth_options->AuthDirVoteGuardGuaranteeTimeKnown; |
304 | |
|
305 | 0 | { |
306 | | /* We can vote on a parameter for the minimum and maximum. */ |
307 | 0 | #define ABSOLUTE_MIN_VALUE_FOR_FAST_FLAG 4 |
308 | 0 | int32_t min_fast_kb, max_fast_kb, min_fast, max_fast; |
309 | 0 | min_fast = networkstatus_get_param(NULL, "FastFlagMinThreshold", |
310 | 0 | ABSOLUTE_MIN_VALUE_FOR_FAST_FLAG, |
311 | 0 | ABSOLUTE_MIN_VALUE_FOR_FAST_FLAG, |
312 | 0 | INT32_MAX); |
313 | 0 | if (options->TestingTorNetwork) { |
314 | 0 | min_fast = (int32_t)dirauth_options->TestingMinFastFlagThreshold; |
315 | 0 | } |
316 | 0 | max_fast = networkstatus_get_param(NULL, "FastFlagMaxThreshold", |
317 | 0 | INT32_MAX, min_fast, INT32_MAX); |
318 | 0 | min_fast_kb = min_fast / 1000; |
319 | 0 | max_fast_kb = max_fast / 1000; |
320 | |
|
321 | 0 | if (fast_bandwidth_kb < (uint32_t)min_fast_kb) |
322 | 0 | fast_bandwidth_kb = min_fast_kb; |
323 | 0 | if (fast_bandwidth_kb > (uint32_t)max_fast_kb) |
324 | 0 | fast_bandwidth_kb = max_fast_kb; |
325 | 0 | } |
326 | | /* Protect sufficiently fast nodes from being pushed out of the set |
327 | | * of Fast nodes. */ |
328 | 0 | { |
329 | 0 | const uint64_t fast_opt = dirauth_get_options()->AuthDirFastGuarantee; |
330 | 0 | if (fast_opt && fast_bandwidth_kb > fast_opt / 1000) |
331 | 0 | fast_bandwidth_kb = (uint32_t)(fast_opt / 1000); |
332 | 0 | } |
333 | | |
334 | | /* Now that we have a time-known that 7/8 routers are known longer than, |
335 | | * fill wfus with the wfu of every such "familiar" router. */ |
336 | 0 | n_familiar = 0; |
337 | |
|
338 | 0 | SMARTLIST_FOREACH_BEGIN(nodelist, node_t *, node) { |
339 | 0 | if (router_counts_toward_thresholds(node, now, |
340 | 0 | omit_as_sybil, require_mbw)) { |
341 | 0 | routerinfo_t *ri = node->ri; |
342 | 0 | const char *id = ri->cache_info.identity_digest; |
343 | 0 | long tk = rep_hist_get_weighted_time_known(id, now); |
344 | 0 | if (tk < guard_tk) |
345 | 0 | continue; |
346 | 0 | wfus[n_familiar++] = rep_hist_get_weighted_fractional_uptime(id, now); |
347 | 0 | } |
348 | 0 | } SMARTLIST_FOREACH_END(node); |
349 | 0 | if (n_familiar) |
350 | 0 | guard_wfu = median_double(wfus, n_familiar); |
351 | 0 | if (guard_wfu > dirauth_options->AuthDirVoteGuardGuaranteeWFU) |
352 | 0 | guard_wfu = dirauth_options->AuthDirVoteGuardGuaranteeWFU; |
353 | |
|
354 | 0 | enough_mtbf_info = rep_hist_have_measured_enough_stability(); |
355 | |
|
356 | 0 | if (n_active_nonexit) { |
357 | 0 | int nth = (int)(n_active_nonexit * |
358 | 0 | dirauth_options->AuthDirVoteGuardBwThresholdFraction); |
359 | 0 | guard_bandwidth_excluding_exits_kb = |
360 | 0 | find_nth_uint32(bandwidths_excluding_exits_kb, n_active_nonexit, nth); |
361 | 0 | } |
362 | |
|
363 | 0 | log_info(LD_DIRSERV, |
364 | 0 | "Cutoffs: For Stable, %lu sec uptime, %lu sec MTBF. " |
365 | 0 | "For Fast: %lu kilobytes/sec. " |
366 | 0 | "For Guard: WFU %.03f%%, time-known %lu sec, " |
367 | 0 | "and bandwidth %lu or %lu kilobytes/sec. " |
368 | 0 | "We%s have enough stability data.", |
369 | 0 | (unsigned long)stable_uptime, |
370 | 0 | (unsigned long)stable_mtbf, |
371 | 0 | (unsigned long)fast_bandwidth_kb, |
372 | 0 | guard_wfu*100, |
373 | 0 | (unsigned long)guard_tk, |
374 | 0 | (unsigned long)guard_bandwidth_including_exits_kb, |
375 | 0 | (unsigned long)guard_bandwidth_excluding_exits_kb, |
376 | 0 | enough_mtbf_info ? "" : " don't"); |
377 | |
|
378 | 0 | tor_free(uptimes); |
379 | 0 | tor_free(mtbfs); |
380 | 0 | tor_free(bandwidths_kb); |
381 | 0 | tor_free(bandwidths_excluding_exits_kb); |
382 | 0 | tor_free(tks); |
383 | 0 | tor_free(wfus); |
384 | 0 | } |
385 | | |
386 | | /* Use dirserv_compute_performance_thresholds() to compute the thresholds |
387 | | * for the status flags, specifically for bridges. |
388 | | * |
389 | | * This is only called by a Bridge Authority from |
390 | | * networkstatus_getinfo_by_purpose(). |
391 | | */ |
392 | | void |
393 | | dirserv_compute_bridge_flag_thresholds(void) |
394 | 0 | { |
395 | 0 | digestmap_t *omit_as_sybil = digestmap_new(); |
396 | 0 | dirserv_compute_performance_thresholds(omit_as_sybil); |
397 | 0 | digestmap_free(omit_as_sybil, NULL); |
398 | 0 | } |
399 | | |
400 | | /** Give a statement of our current performance thresholds for inclusion |
401 | | * in a vote document. */ |
402 | | char * |
403 | | dirserv_get_flag_thresholds_line(void) |
404 | 0 | { |
405 | 0 | char *result=NULL; |
406 | 0 | const int measured_threshold = |
407 | 0 | dirauth_get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised; |
408 | 0 | const int enough_measured_bw = |
409 | 0 | dirserv_get_last_n_measured_bws() > measured_threshold; |
410 | |
|
411 | 0 | tor_asprintf(&result, |
412 | 0 | "stable-uptime=%lu stable-mtbf=%lu " |
413 | 0 | "fast-speed=%lu " |
414 | 0 | "guard-wfu=%.03f%% guard-tk=%lu " |
415 | 0 | "guard-bw-inc-exits=%lu guard-bw-exc-exits=%lu " |
416 | 0 | "enough-mtbf=%d ignoring-advertised-bws=%d", |
417 | 0 | (unsigned long)stable_uptime, |
418 | 0 | (unsigned long)stable_mtbf, |
419 | 0 | (unsigned long)fast_bandwidth_kb*1000, |
420 | 0 | guard_wfu*100, |
421 | 0 | (unsigned long)guard_tk, |
422 | 0 | (unsigned long)guard_bandwidth_including_exits_kb*1000, |
423 | 0 | (unsigned long)guard_bandwidth_excluding_exits_kb*1000, |
424 | 0 | enough_mtbf_info ? 1 : 0, |
425 | 0 | enough_measured_bw ? 1 : 0); |
426 | |
|
427 | 0 | return result; |
428 | 0 | } |
429 | | |
430 | | /** Directory authorities should avoid expressing an opinion on the |
431 | | * Running flag if their own uptime is too low for the opinion to be |
432 | | * accurate. They implement this step by not listing Running on the |
433 | | * "known-flags" line in their vote. |
434 | | * |
435 | | * The default threshold is 30 minutes, because authorities do a full |
436 | | * reachability sweep of the ID space every 10*128=1280 seconds |
437 | | * (see REACHABILITY_TEST_CYCLE_PERIOD). |
438 | | * |
439 | | * For v3 dir auths, as long as some authorities express an opinion about |
440 | | * Running, it's fine if a few authorities don't. There's an explicit |
441 | | * check, when making the consensus, to abort if *no* authorities list |
442 | | * Running as a known-flag. |
443 | | * |
444 | | * For the bridge authority, if it doesn't vote about Running, the |
445 | | * resulting networkstatus file simply won't list any bridges as Running. |
446 | | * That means the supporting tools, like bridgedb/rdsys and onionoo, need |
447 | | * to be able to handle getting a bridge networkstatus document with no |
448 | | * Running flags. For more details, see |
449 | | * https://bugs.torproject.org/tpo/anti-censorship/rdsys/102 */ |
450 | | int |
451 | | running_long_enough_to_decide_unreachable(void) |
452 | 0 | { |
453 | 0 | const dirauth_options_t *opts = dirauth_get_options(); |
454 | 0 | return time_of_process_start + |
455 | 0 | opts->TestingAuthDirTimeToLearnReachability < approx_time(); |
456 | 0 | } |
457 | | |
458 | | /** Each server needs to have passed a reachability test no more |
459 | | * than this number of seconds ago, or it is listed as down in |
460 | | * the directory. */ |
461 | 0 | #define REACHABLE_TIMEOUT (45*60) |
462 | | |
463 | | /** If we tested a router and found it reachable _at least this long_ after it |
464 | | * declared itself hibernating, it is probably done hibernating and we just |
465 | | * missed a descriptor from it. */ |
466 | 0 | #define HIBERNATION_PUBLICATION_SKEW (60*60) |
467 | | |
468 | | /** Treat a router as alive if |
469 | | * - It's me, and I'm not hibernating. |
470 | | * or - We've found it reachable recently. */ |
471 | | void |
472 | | dirserv_set_router_is_running(routerinfo_t *router, time_t now) |
473 | 0 | { |
474 | | /*XXXX This function is a mess. Separate out the part that calculates |
475 | | whether it's reachable and the part that tells rephist that the router was |
476 | | unreachable. |
477 | | */ |
478 | 0 | int answer; |
479 | 0 | const dirauth_options_t *dirauth_options = dirauth_get_options(); |
480 | 0 | node_t *node = node_get_mutable_by_id(router->cache_info.identity_digest); |
481 | 0 | tor_assert(node); |
482 | | |
483 | 0 | if (router_is_me(router)) { |
484 | | /* We always know if we are shutting down or hibernating ourselves. */ |
485 | 0 | answer = ! we_are_hibernating(); |
486 | 0 | } else if (router->is_hibernating && |
487 | 0 | (router->cache_info.published_on + |
488 | 0 | HIBERNATION_PUBLICATION_SKEW) > node->last_reachable) { |
489 | | /* A hibernating router is down unless we (somehow) had contact with it |
490 | | * since it declared itself to be hibernating. */ |
491 | 0 | answer = 0; |
492 | 0 | } else if (! dirauth_options->AuthDirTestReachability) { |
493 | | /* If we aren't testing reachability, then everybody is up unless they say |
494 | | * they are down. */ |
495 | 0 | answer = 1; |
496 | 0 | } else { |
497 | | /* Otherwise, a router counts as up if we found all announced OR |
498 | | ports reachable in the last REACHABLE_TIMEOUT seconds. |
499 | | |
500 | | XXX prop186 For now there's always one IPv4 and at most one |
501 | | IPv6 OR port. |
502 | | |
503 | | If we're not on IPv6, don't consider reachability of potential |
504 | | IPv6 OR port since that'd kill all dual stack relays until a |
505 | | majority of the dir auths have IPv6 connectivity. */ |
506 | 0 | answer = (now < node->last_reachable + REACHABLE_TIMEOUT && |
507 | 0 | (dirauth_options->AuthDirHasIPv6Connectivity != 1 || |
508 | 0 | tor_addr_is_null(&router->ipv6_addr) || |
509 | 0 | now < node->last_reachable6 + REACHABLE_TIMEOUT)); |
510 | 0 | } |
511 | |
|
512 | 0 | if (!answer && running_long_enough_to_decide_unreachable()) { |
513 | | /* Not considered reachable. tell rephist about that. |
514 | | |
515 | | Because we launch a reachability test for each router every |
516 | | REACHABILITY_TEST_CYCLE_PERIOD seconds, then the router has probably |
517 | | been down since at least that time after we last successfully reached |
518 | | it. |
519 | | |
520 | | XXX ipv6 |
521 | | */ |
522 | 0 | time_t when = now; |
523 | 0 | if (node->last_reachable && |
524 | 0 | node->last_reachable + REACHABILITY_TEST_CYCLE_PERIOD < now) |
525 | 0 | when = node->last_reachable + REACHABILITY_TEST_CYCLE_PERIOD; |
526 | 0 | rep_hist_note_router_unreachable(router->cache_info.identity_digest, when); |
527 | 0 | } |
528 | |
|
529 | 0 | node->is_running = answer; |
530 | 0 | } |
531 | | |
532 | | /* Check <b>node</b> and <b>ri</b> on whether or not we should publish a |
533 | | * relay's IPv6 addresses. */ |
534 | | static int |
535 | | should_publish_node_ipv6(const node_t *node, const routerinfo_t *ri, |
536 | | time_t now) |
537 | 0 | { |
538 | 0 | const dirauth_options_t *options = dirauth_get_options(); |
539 | |
|
540 | 0 | return options->AuthDirHasIPv6Connectivity == 1 && |
541 | 0 | !tor_addr_is_null(&ri->ipv6_addr) && |
542 | 0 | ((node->last_reachable6 >= now - REACHABLE_TIMEOUT) || |
543 | 0 | router_is_me(ri)); |
544 | 0 | } |
545 | | |
546 | | /** Set routerstatus flags based on the authority options. Same as the testing |
547 | | * function but for the main network. */ |
548 | | static void |
549 | | dirserv_set_routerstatus_flags(routerstatus_t *rs) |
550 | 0 | { |
551 | 0 | const dirauth_options_t *options = dirauth_get_options(); |
552 | |
|
553 | 0 | tor_assert(rs); |
554 | | |
555 | | /* Assign Guard flag to relays that can get it unconditionnaly. */ |
556 | 0 | if (routerset_contains_routerstatus(options->AuthDirVoteGuard, rs, 0)) { |
557 | 0 | rs->is_possible_guard = 1; |
558 | 0 | } |
559 | 0 | } |
560 | | |
561 | | /** |
562 | | * Extract status information from <b>ri</b> and from other authority |
563 | | * functions and store it in <b>rs</b>, as per |
564 | | * <b>set_routerstatus_from_routerinfo</b>. Additionally, sets information |
565 | | * in from the authority subsystem. |
566 | | */ |
567 | | void |
568 | | dirauth_set_routerstatus_from_routerinfo(routerstatus_t *rs, |
569 | | node_t *node, |
570 | | const routerinfo_t *ri, |
571 | | time_t now, |
572 | | int listbadexits, |
573 | | int listmiddleonly) |
574 | 0 | { |
575 | 0 | const or_options_t *options = get_options(); |
576 | 0 | uint32_t routerbw_kb = dirserv_get_credible_bandwidth_kb(ri); |
577 | | |
578 | | /* Set these flags so that set_routerstatus_from_routerinfo can copy them. |
579 | | */ |
580 | 0 | node->is_stable = !dirserv_thinks_router_is_unreliable(now, ri, 1, 0); |
581 | 0 | node->is_fast = !dirserv_thinks_router_is_unreliable(now, ri, 0, 1); |
582 | 0 | node->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, node, now); |
583 | |
|
584 | 0 | set_routerstatus_from_routerinfo(rs, node, ri); |
585 | | |
586 | | /* Override rs->is_possible_guard. */ |
587 | 0 | const uint64_t bw_opt = dirauth_get_options()->AuthDirGuardBWGuarantee; |
588 | 0 | if (node->is_fast && node->is_stable && |
589 | 0 | ri->supports_tunnelled_dir_requests && |
590 | 0 | ((bw_opt && routerbw_kb >= bw_opt / 1000) || |
591 | 0 | routerbw_kb >= MIN(guard_bandwidth_including_exits_kb, |
592 | 0 | guard_bandwidth_excluding_exits_kb))) { |
593 | 0 | long tk = rep_hist_get_weighted_time_known( |
594 | 0 | node->identity, now); |
595 | 0 | double wfu = rep_hist_get_weighted_fractional_uptime( |
596 | 0 | node->identity, now); |
597 | 0 | rs->is_possible_guard = (wfu >= guard_wfu && tk >= guard_tk) ? 1 : 0; |
598 | 0 | } else { |
599 | 0 | rs->is_possible_guard = 0; |
600 | 0 | } |
601 | | |
602 | | /* Override rs->is_bad_exit */ |
603 | 0 | rs->is_bad_exit = listbadexits && node->is_bad_exit; |
604 | | |
605 | | /* Override rs->is_middle_only and related flags. */ |
606 | 0 | rs->is_middle_only = listmiddleonly && node->is_middle_only; |
607 | 0 | if (rs->is_middle_only) { |
608 | 0 | if (listbadexits) |
609 | 0 | rs->is_bad_exit = 1; |
610 | 0 | rs->is_exit = rs->is_possible_guard = rs->is_hs_dir = rs->is_v2_dir = 0; |
611 | 0 | } |
612 | | |
613 | | /* Strip rs flags based on node flags. */ |
614 | 0 | if (node->strip_guard) { |
615 | 0 | rs->is_possible_guard = 0; |
616 | 0 | } |
617 | 0 | if (node->strip_hsdir) { |
618 | 0 | rs->is_hs_dir = 0; |
619 | 0 | } |
620 | 0 | if (node->strip_v2dir) { |
621 | 0 | rs->is_v2_dir = 0; |
622 | 0 | } |
623 | | |
624 | | /* Set rs->is_staledesc. */ |
625 | 0 | rs->is_staledesc = |
626 | 0 | (ri->cache_info.published_on + DESC_IS_STALE_INTERVAL) < now; |
627 | |
|
628 | 0 | if (! should_publish_node_ipv6(node, ri, now)) { |
629 | | /* We're not configured as having IPv6 connectivity or the node isn't: |
630 | | * zero its IPv6 information. */ |
631 | 0 | tor_addr_make_null(&rs->ipv6_addr, AF_INET6); |
632 | 0 | rs->ipv6_orport = 0; |
633 | 0 | } |
634 | |
|
635 | 0 | if (options->TestingTorNetwork) { |
636 | 0 | dirserv_set_routerstatus_testing(rs); |
637 | 0 | } else { |
638 | 0 | dirserv_set_routerstatus_flags(rs); |
639 | 0 | } |
640 | 0 | } |
641 | | |
642 | | /** Use TestingDirAuthVoteExit, TestingDirAuthVoteGuard, and |
643 | | * TestingDirAuthVoteHSDir to give out the Exit, Guard, and HSDir flags, |
644 | | * respectively. But don't set the corresponding node flags. |
645 | | * Should only be called if TestingTorNetwork is set. */ |
646 | | STATIC void |
647 | | dirserv_set_routerstatus_testing(routerstatus_t *rs) |
648 | 0 | { |
649 | 0 | const dirauth_options_t *options = dirauth_get_options(); |
650 | |
|
651 | 0 | tor_assert(get_options()->TestingTorNetwork); |
652 | | |
653 | 0 | if (routerset_contains_routerstatus(options->TestingDirAuthVoteExit, |
654 | 0 | rs, 0)) { |
655 | 0 | rs->is_exit = 1; |
656 | 0 | } else if (options->TestingDirAuthVoteExitIsStrict) { |
657 | 0 | rs->is_exit = 0; |
658 | 0 | } |
659 | |
|
660 | 0 | if (routerset_contains_routerstatus(options->TestingDirAuthVoteGuard, |
661 | 0 | rs, 0)) { |
662 | 0 | rs->is_possible_guard = 1; |
663 | 0 | } else if (options->TestingDirAuthVoteGuardIsStrict) { |
664 | 0 | rs->is_possible_guard = 0; |
665 | 0 | } |
666 | |
|
667 | 0 | if (routerset_contains_routerstatus(options->TestingDirAuthVoteHSDir, |
668 | 0 | rs, 0)) { |
669 | 0 | rs->is_hs_dir = 1; |
670 | 0 | } else if (options->TestingDirAuthVoteHSDirIsStrict) { |
671 | 0 | rs->is_hs_dir = 0; |
672 | 0 | } |
673 | 0 | } |
674 | | |
675 | | /** Use dirserv_set_router_is_running() to set bridges as running if they're |
676 | | * reachable. |
677 | | * |
678 | | * This function is called from set_bridge_running_callback() when running as |
679 | | * a bridge authority. |
680 | | */ |
681 | | void |
682 | | dirserv_set_bridges_running(time_t now) |
683 | 0 | { |
684 | 0 | routerlist_t *rl = router_get_routerlist(); |
685 | |
|
686 | 0 | SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, ri) { |
687 | 0 | if (ri->purpose == ROUTER_PURPOSE_BRIDGE) |
688 | 0 | dirserv_set_router_is_running(ri, now); |
689 | 0 | } SMARTLIST_FOREACH_END(ri); |
690 | 0 | } |