1 /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
2 * Copyright (c) 2007-2021, The Tor Project, Inc. */
3 /* See LICENSE for licensing information */
6 * \file control_bootstrap.c
7 * \brief Provide bootstrap progress events for the control port.
9 #include "core/or/or.h"
11 #include "app/config/config.h"
12 #include "core/mainloop/connection.h"
13 #include "core/or/connection_or.h"
14 #include "core/or/connection_st.h"
15 #include "core/or/or_connection_st.h"
16 #include "core/or/reasons.h"
17 #include "feature/control/control_events.h"
18 #include "feature/hibernate/hibernate.h"
19 #include "lib/malloc/malloc.h"
21 /** A sufficiently large size to record the last bootstrap phase string. */
22 #define BOOTSTRAP_MSG_LEN 1024
24 /** What was the last bootstrap phase message we sent? We keep track
25 * of this so we can respond to getinfo status/bootstrap-phase queries. */
26 static char last_sent_bootstrap_message
[BOOTSTRAP_MSG_LEN
];
28 /** Table to convert bootstrap statuses to strings. */
30 bootstrap_status_t status
;
33 } boot_to_str_tab
[] = {
34 { BOOTSTRAP_STATUS_UNDEF
, "undef", "Undefined" },
35 { BOOTSTRAP_STATUS_STARTING
, "starting", "Starting" },
37 /* Initial connection to any relay */
39 { BOOTSTRAP_STATUS_CONN_PT
, "conn_pt", "Connecting to pluggable transport" },
40 { BOOTSTRAP_STATUS_CONN_DONE_PT
, "conn_done_pt",
41 "Connected to pluggable transport" },
42 { BOOTSTRAP_STATUS_CONN_PROXY
, "conn_proxy", "Connecting to proxy" },
43 { BOOTSTRAP_STATUS_CONN_DONE_PROXY
, "conn_done_proxy",
44 "Connected to proxy" },
45 { BOOTSTRAP_STATUS_CONN
, "conn", "Connecting to a relay" },
46 { BOOTSTRAP_STATUS_CONN_DONE
, "conn_done", "Connected to a relay" },
47 { BOOTSTRAP_STATUS_HANDSHAKE
, "handshake",
48 "Handshaking with a relay" },
49 { BOOTSTRAP_STATUS_HANDSHAKE_DONE
, "handshake_done",
50 "Handshake with a relay done" },
52 /* Loading directory info */
54 { BOOTSTRAP_STATUS_ONEHOP_CREATE
, "onehop_create",
55 "Establishing an encrypted directory connection" },
56 { BOOTSTRAP_STATUS_REQUESTING_STATUS
, "requesting_status",
57 "Asking for networkstatus consensus" },
58 { BOOTSTRAP_STATUS_LOADING_STATUS
, "loading_status",
59 "Loading networkstatus consensus" },
60 { BOOTSTRAP_STATUS_LOADING_KEYS
, "loading_keys",
61 "Loading authority key certs" },
62 { BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS
, "requesting_descriptors",
63 "Asking for relay descriptors" },
64 { BOOTSTRAP_STATUS_LOADING_DESCRIPTORS
, "loading_descriptors",
65 "Loading relay descriptors" },
66 { BOOTSTRAP_STATUS_ENOUGH_DIRINFO
, "enough_dirinfo",
67 "Loaded enough directory info to build circuits" },
69 /* Connecting to a relay for AP circuits */
71 { BOOTSTRAP_STATUS_AP_CONN_PT
, "ap_conn_pt",
72 "Connecting to pluggable transport to build circuits" },
73 { BOOTSTRAP_STATUS_AP_CONN_DONE_PT
, "ap_conn_done_pt",
74 "Connected to pluggable transport to build circuits" },
75 { BOOTSTRAP_STATUS_AP_CONN_PROXY
, "ap_conn_proxy",
76 "Connecting to proxy to build circuits" },
77 { BOOTSTRAP_STATUS_AP_CONN_DONE_PROXY
, "ap_conn_done_proxy",
78 "Connected to proxy to build circuits" },
79 { BOOTSTRAP_STATUS_AP_CONN
, "ap_conn",
80 "Connecting to a relay to build circuits" },
81 { BOOTSTRAP_STATUS_AP_CONN_DONE
, "ap_conn_done",
82 "Connected to a relay to build circuits" },
83 { BOOTSTRAP_STATUS_AP_HANDSHAKE
, "ap_handshake",
84 "Finishing handshake with a relay to build circuits" },
85 { BOOTSTRAP_STATUS_AP_HANDSHAKE_DONE
, "ap_handshake_done",
86 "Handshake finished with a relay to build circuits" },
88 /* Creating AP circuits */
90 { BOOTSTRAP_STATUS_CIRCUIT_CREATE
, "circuit_create",
91 "Establishing a Tor circuit" },
92 { BOOTSTRAP_STATUS_DONE
, "done", "Done" },
94 #define N_BOOT_TO_STR (sizeof(boot_to_str_tab)/sizeof(boot_to_str_tab[0]))
96 /** Convert the name of a bootstrapping phase <b>s</b> into strings
97 * <b>tag</b> and <b>summary</b> suitable for display by the controller. */
99 bootstrap_status_to_string(bootstrap_status_t s
, const char **tag
,
100 const char **summary
)
102 for (size_t i
= 0; i
< N_BOOT_TO_STR
; i
++) {
103 if (s
== boot_to_str_tab
[i
].status
) {
104 *tag
= boot_to_str_tab
[i
].tag
;
105 *summary
= boot_to_str_tab
[i
].summary
;
110 *tag
= *summary
= "unknown";
114 /** What percentage through the bootstrap process are we? We remember
115 * this so we can avoid sending redundant bootstrap status events, and
116 * so we can guess context for the bootstrap messages which are
117 * ambiguous. It starts at 'undef', but gets set to 'starting' while
118 * Tor initializes. */
119 static int bootstrap_percent
= BOOTSTRAP_STATUS_UNDEF
;
121 /** Like bootstrap_percent, but only takes on the enumerated values in
122 * bootstrap_status_t.
124 static int bootstrap_phase
= BOOTSTRAP_STATUS_UNDEF
;
126 /** As bootstrap_percent, but holds the bootstrapping level at which we last
127 * logged a NOTICE-level message. We use this, plus BOOTSTRAP_PCT_INCREMENT,
128 * to avoid flooding the log with a new message every time we get a few more
129 * microdescriptors */
130 static int notice_bootstrap_percent
= 0;
132 /** How many problems have we had getting to the next bootstrapping phase?
133 * These include failure to establish a connection to a Tor relay,
134 * failures to finish the TLS handshake, failures to validate the
135 * consensus document, etc. */
136 static int bootstrap_problems
= 0;
138 /** We only tell the controller once we've hit a threshold of problems
139 * for the current phase. */
140 #define BOOTSTRAP_PROBLEM_THRESHOLD 10
142 /** When our bootstrapping progress level changes, but our bootstrapping
143 * status has not advanced, we only log at NOTICE when we have made at least
144 * this much progress.
146 #define BOOTSTRAP_PCT_INCREMENT 5
148 /** Do the actual logging and notifications for
149 * control_event_bootstrap(). Doesn't change any state beyond that.
152 control_event_bootstrap_core(int loglevel
, bootstrap_status_t status
,
155 char buf
[BOOTSTRAP_MSG_LEN
];
156 const char *tag
, *summary
;
158 bootstrap_status_to_string(status
, &tag
, &summary
);
159 /* Locally reset status if there's incremental progress */
163 tor_log(loglevel
, LD_CONTROL
,
164 "Bootstrapped %d%% (%s): %s", status
, tag
, summary
);
165 tor_snprintf(buf
, sizeof(buf
),
166 "BOOTSTRAP PROGRESS=%d TAG=%s SUMMARY=\"%s\"",
167 status
, tag
, summary
);
168 tor_snprintf(last_sent_bootstrap_message
,
169 sizeof(last_sent_bootstrap_message
),
171 control_event_client_status(LOG_NOTICE
, "%s", buf
);
175 control_get_bootstrap_percent(void)
177 return bootstrap_percent
;
180 /** Called when Tor has made progress at bootstrapping its directory
181 * information and initial circuits.
183 * <b>status</b> is the new status, that is, what task we will be doing
184 * next. <b>progress</b> is zero if we just started this task, else it
185 * represents progress on the task.
188 control_event_bootstrap(bootstrap_status_t status
, int progress
)
190 int loglevel
= LOG_NOTICE
;
192 if (bootstrap_percent
== BOOTSTRAP_STATUS_DONE
)
193 return; /* already bootstrapped; nothing to be done here. */
195 if (status
<= bootstrap_percent
) {
196 /* If there's no new progress, return early. */
197 if (!progress
|| progress
<= bootstrap_percent
)
199 /* Log at INFO if not enough progress happened. */
200 if (progress
< notice_bootstrap_percent
+ BOOTSTRAP_PCT_INCREMENT
)
204 control_event_bootstrap_core(loglevel
, status
, progress
);
206 if (status
> bootstrap_percent
) {
207 bootstrap_phase
= status
; /* new milestone reached */
208 bootstrap_percent
= status
;
210 if (progress
> bootstrap_percent
) {
211 /* incremental progress within a milestone */
212 bootstrap_percent
= progress
;
213 bootstrap_problems
= 0; /* Progress! Reset our problem counter. */
215 if (loglevel
== LOG_NOTICE
&&
216 bootstrap_percent
> notice_bootstrap_percent
) {
217 /* Remember that we gave a notice at this level. */
218 notice_bootstrap_percent
= bootstrap_percent
;
222 /** Flag whether we've opened an OR_CONN yet */
223 static int bootstrap_first_orconn
= 0;
225 /** Like bootstrap_phase, but for (possibly deferred) directory progress */
226 static int bootstrap_dir_phase
= BOOTSTRAP_STATUS_UNDEF
;
228 /** Like bootstrap_problems, but for (possibly deferred) directory progress */
229 static int bootstrap_dir_progress
= BOOTSTRAP_STATUS_UNDEF
;
231 /** Defer directory info bootstrap events until we have successfully
232 * completed our first connection to a router. */
234 control_event_boot_dir(bootstrap_status_t status
, int progress
)
236 if (status
> bootstrap_dir_progress
) {
237 bootstrap_dir_progress
= status
;
238 bootstrap_dir_phase
= status
;
240 if (progress
&& progress
>= bootstrap_dir_progress
) {
241 bootstrap_dir_progress
= progress
;
244 /* Don't report unless we have successfully opened at least one OR_CONN */
245 if (!bootstrap_first_orconn
)
248 control_event_bootstrap(status
, progress
);
251 /** Set a flag to allow reporting of directory bootstrap progress.
252 * (Code that reports completion of an OR_CONN calls this.) Also,
253 * report directory progress so far. */
255 control_event_boot_first_orconn(void)
257 bootstrap_first_orconn
= 1;
258 control_event_bootstrap(bootstrap_dir_phase
, bootstrap_dir_progress
);
261 /** Called when Tor has failed to make bootstrapping progress in a way
262 * that indicates a problem. <b>warn</b> gives a human-readable hint
263 * as to why, and <b>reason</b> provides a controller-facing short
264 * tag. <b>conn</b> is the connection that caused this problem and
265 * can be NULL if a connection cannot be easily identified.
268 control_event_bootstrap_problem(const char *warn
, const char *reason
,
269 const connection_t
*conn
, int dowarn
)
271 int status
= bootstrap_percent
;
272 const char *tag
= "", *summary
= "";
273 char buf
[BOOTSTRAP_MSG_LEN
];
274 const char *recommendation
= "ignore";
276 char *or_id
= NULL
, *hostaddr
= NULL
;
277 const or_connection_t
*or_conn
= NULL
;
279 /* bootstrap_percent must not be in "undefined" state here. */
280 tor_assert(status
>= 0);
282 if (bootstrap_percent
== 100)
283 return; /* already bootstrapped; nothing to be done here. */
285 bootstrap_problems
++;
287 if (bootstrap_problems
>= BOOTSTRAP_PROBLEM_THRESHOLD
)
290 /* Don't warn about our bootstrapping status if we are hibernating or
292 if (we_are_hibernating())
295 tor_assert(bootstrap_status_to_string(bootstrap_phase
, &tag
, &summary
) == 0);
297 severity
= dowarn
? LOG_WARN
: LOG_INFO
;
300 recommendation
= "warn";
302 if (conn
&& conn
->type
== CONN_TYPE_OR
) {
303 /* XXX TO_OR_CONN can't deal with const */
304 or_conn
= CONST_TO_OR_CONN(conn
);
305 or_id
= tor_strdup(hex_str(or_conn
->identity_digest
, DIGEST_LEN
));
307 or_id
= tor_strdup("?");
311 tor_asprintf(&hostaddr
, "%s:%d", conn
->address
, (int)conn
->port
);
313 hostaddr
= tor_strdup("?");
316 LD_CONTROL
, "Problem bootstrapping. Stuck at %d%% (%s): %s. (%s; %s; "
317 "count %d; recommendation %s; host %s at %s)",
318 status
, tag
, summary
, warn
, reason
,
319 bootstrap_problems
, recommendation
,
322 connection_or_report_broken_states(severity
, LD_HANDSHAKE
);
324 tor_snprintf(buf
, sizeof(buf
),
325 "BOOTSTRAP PROGRESS=%d TAG=%s SUMMARY=\"%s\" WARNING=\"%s\" REASON=%s "
326 "COUNT=%d RECOMMENDATION=%s HOSTID=\"%s\" HOSTADDR=\"%s\"",
327 bootstrap_percent
, tag
, summary
, warn
, reason
, bootstrap_problems
,
331 tor_snprintf(last_sent_bootstrap_message
,
332 sizeof(last_sent_bootstrap_message
),
334 control_event_client_status(LOG_WARN
, "%s", buf
);
340 /** Called when Tor has failed to make bootstrapping progress in a way
341 * that indicates a problem. <b>warn</b> gives a hint as to why, and
342 * <b>reason</b> provides an "or_conn_end_reason" tag. <b>or_conn</b>
343 * is the connection that caused this problem.
346 control_event_bootstrap_prob_or
, (const char *warn
, int reason
,
347 or_connection_t
*or_conn
))
351 if (! or_conn
->potentially_used_for_bootstrapping
) {
352 /* We never decided that this channel was a good match for one of our
353 * origin_circuit_t objects. That means that we probably launched it
354 * for somebody else, most likely in response to an EXTEND cell.
356 * Since EXTEND cells can contain arbitrarily broken descriptions of
357 * relays, a failure on this connection here won't necessarily indicate a
358 * bootstrapping problem.
363 if (or_conn
->have_noted_bootstrap_problem
)
366 or_conn
->have_noted_bootstrap_problem
= 1;
368 if (reason
== END_OR_CONN_REASON_NO_ROUTE
)
371 /* If we are using bridges and all our OR connections are now
372 closed, it means that we totally failed to connect to our
373 bridges. Throw a warning. */
374 if (get_options()->UseBridges
&& !any_other_active_or_conns(or_conn
))
377 control_event_bootstrap_problem(warn
,
378 orconn_end_reason_to_control_string(reason
),
379 TO_CONN(or_conn
), dowarn
);
382 /** Return a copy of the last sent bootstrap message. */
384 control_event_boot_last_msg(void)
386 return tor_strdup(last_sent_bootstrap_message
);
389 /** Reset bootstrap tracking state. */
391 control_event_bootstrap_reset(void)
393 bootstrap_percent
= BOOTSTRAP_STATUS_UNDEF
;
394 bootstrap_phase
= BOOTSTRAP_STATUS_UNDEF
;
395 notice_bootstrap_percent
= 0;
396 bootstrap_problems
= 0;
397 bootstrap_first_orconn
= 0;
398 bootstrap_dir_progress
= BOOTSTRAP_STATUS_UNDEF
;
399 bootstrap_dir_phase
= BOOTSTRAP_STATUS_UNDEF
;
400 memset(last_sent_bootstrap_message
, 0, sizeof(last_sent_bootstrap_message
));