Line data Source code
1 : /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
2 : * Copyright (c) 2007-2021, The Tor Project, Inc. */
3 : /* See LICENSE for licensing information */
4 :
5 : /**
6 : * \file control_events.c
7 : * \brief Implement the event-reporting part of the controller API.
8 : **/
9 :
10 : #define CONTROL_MODULE_PRIVATE
11 : #define CONTROL_EVENTS_PRIVATE
12 : #define OCIRC_EVENT_PRIVATE
13 :
14 : #include "core/or/or.h"
15 : #include "app/config/config.h"
16 : #include "core/mainloop/connection.h"
17 : #include "core/mainloop/mainloop.h"
18 : #include "core/or/channeltls.h"
19 : #include "core/or/circuitlist.h"
20 : #include "core/or/circuitstats.h"
21 : #include "core/or/command.h"
22 : #include "core/or/connection_edge.h"
23 : #include "core/or/connection_or.h"
24 : #include "core/or/reasons.h"
25 : #include "feature/control/control.h"
26 : #include "feature/control/control_events.h"
27 : #include "feature/control/control_fmt.h"
28 : #include "feature/control/control_proto.h"
29 : #include "feature/dircommon/directory.h"
30 : #include "feature/nodelist/describe.h"
31 : #include "feature/nodelist/networkstatus.h"
32 : #include "feature/nodelist/nodelist.h"
33 :
34 : #include "feature/control/control_connection_st.h"
35 : #include "core/or/entry_connection_st.h"
36 : #include "feature/nodelist/networkstatus_st.h"
37 : #include "core/or/or_connection_st.h"
38 : #include "core/or/or_circuit_st.h"
39 : #include "core/or/origin_circuit_st.h"
40 :
41 : #include "lib/evloop/compat_libevent.h"
42 : #include "lib/encoding/confline.h"
43 :
44 : static void flush_queued_events_cb(mainloop_event_t *event, void *arg);
45 : static void control_get_bytes_rw_last_sec(uint64_t *r, uint64_t *w);
46 :
47 : /** Yield true iff <b>s</b> is the state of a control_connection_t that has
48 : * finished authentication and is accepting commands. */
49 : #define STATE_IS_OPEN(s) ((s) == CONTROL_CONN_STATE_OPEN)
50 :
51 : /** An event mask of all the events that any controller is interested in
52 : * receiving. */
53 : static event_mask_t global_event_mask = 0;
54 :
55 : /** True iff we have disabled log messages from being sent to the controller */
56 : static int disable_log_messages = 0;
57 :
58 : /** Macro: true if any control connection is interested in events of type
59 : * <b>e</b>. */
60 : #define EVENT_IS_INTERESTING(e) \
61 : (!! (global_event_mask & EVENT_MASK_(e)))
62 :
63 : /** Macro: true if any event from the bitfield 'e' is interesting. */
64 : #define ANY_EVENT_IS_INTERESTING(e) \
65 : (!! (global_event_mask & (e)))
66 :
67 : static void send_control_event_impl(uint16_t event,
68 : const char *format, va_list ap)
69 : CHECK_PRINTF(2,0);
70 : static int control_event_status(int type, int severity, const char *format,
71 : va_list args)
72 : CHECK_PRINTF(3,0);
73 :
74 : static void send_control_event(uint16_t event,
75 : const char *format, ...)
76 : CHECK_PRINTF(2,3);
77 :
78 : /** Table mapping event values to their names. Used to implement SETEVENTS
79 : * and GETINFO events/names, and to keep they in sync. */
80 : const struct control_event_t control_event_table[] = {
81 : { EVENT_CIRCUIT_STATUS, "CIRC" },
82 : { EVENT_CIRCUIT_STATUS_MINOR, "CIRC_MINOR" },
83 : { EVENT_STREAM_STATUS, "STREAM" },
84 : { EVENT_OR_CONN_STATUS, "ORCONN" },
85 : { EVENT_BANDWIDTH_USED, "BW" },
86 : { EVENT_DEBUG_MSG, "DEBUG" },
87 : { EVENT_INFO_MSG, "INFO" },
88 : { EVENT_NOTICE_MSG, "NOTICE" },
89 : { EVENT_WARN_MSG, "WARN" },
90 : { EVENT_ERR_MSG, "ERR" },
91 : { EVENT_NEW_DESC, "NEWDESC" },
92 : { EVENT_ADDRMAP, "ADDRMAP" },
93 : { EVENT_DESCCHANGED, "DESCCHANGED" },
94 : { EVENT_NS, "NS" },
95 : { EVENT_STATUS_GENERAL, "STATUS_GENERAL" },
96 : { EVENT_STATUS_CLIENT, "STATUS_CLIENT" },
97 : { EVENT_STATUS_SERVER, "STATUS_SERVER" },
98 : { EVENT_GUARD, "GUARD" },
99 : { EVENT_STREAM_BANDWIDTH_USED, "STREAM_BW" },
100 : { EVENT_CLIENTS_SEEN, "CLIENTS_SEEN" },
101 : { EVENT_NEWCONSENSUS, "NEWCONSENSUS" },
102 : { EVENT_BUILDTIMEOUT_SET, "BUILDTIMEOUT_SET" },
103 : { EVENT_GOT_SIGNAL, "SIGNAL" },
104 : { EVENT_CONF_CHANGED, "CONF_CHANGED"},
105 : { EVENT_CONN_BW, "CONN_BW" },
106 : { EVENT_CELL_STATS, "CELL_STATS" },
107 : { EVENT_CIRC_BANDWIDTH_USED, "CIRC_BW" },
108 : { EVENT_TRANSPORT_LAUNCHED, "TRANSPORT_LAUNCHED" },
109 : { EVENT_HS_DESC, "HS_DESC" },
110 : { EVENT_HS_DESC_CONTENT, "HS_DESC_CONTENT" },
111 : { EVENT_NETWORK_LIVENESS, "NETWORK_LIVENESS" },
112 : { 0, NULL },
113 : };
114 :
115 : /** Given a log severity, return the corresponding control event code. */
116 : static inline int
117 8 : log_severity_to_event(int severity)
118 : {
119 8 : switch (severity) {
120 : case LOG_DEBUG: return EVENT_DEBUG_MSG;
121 : case LOG_INFO: return EVENT_INFO_MSG;
122 : case LOG_NOTICE: return EVENT_NOTICE_MSG;
123 : case LOG_WARN: return EVENT_WARN_MSG;
124 : case LOG_ERR: return EVENT_ERR_MSG;
125 : default: return -1;
126 : }
127 : }
128 :
129 : /** Helper: clear bandwidth counters of all origin circuits. */
130 : static void
131 0 : clear_circ_bw_fields(void)
132 : {
133 0 : origin_circuit_t *ocirc;
134 0 : SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
135 0 : if (!CIRCUIT_IS_ORIGIN(circ))
136 0 : continue;
137 0 : ocirc = TO_ORIGIN_CIRCUIT(circ);
138 0 : ocirc->n_written_circ_bw = ocirc->n_read_circ_bw = 0;
139 0 : ocirc->n_overhead_written_circ_bw = ocirc->n_overhead_read_circ_bw = 0;
140 0 : ocirc->n_delivered_written_circ_bw = ocirc->n_delivered_read_circ_bw = 0;
141 : }
142 0 : SMARTLIST_FOREACH_END(circ);
143 0 : }
144 :
145 : /* Helper to emit the BUILDTIMEOUT_SET circuit build time event */
146 : void
147 113 : cbt_control_event_buildtimeout_set(const circuit_build_times_t *cbt,
148 : buildtimeout_set_event_t type)
149 : {
150 113 : char *args = NULL;
151 113 : double qnt;
152 113 : double timeout_rate = 0.0;
153 113 : double close_rate = 0.0;
154 :
155 113 : switch (type) {
156 : case BUILDTIMEOUT_SET_EVENT_RESET:
157 : case BUILDTIMEOUT_SET_EVENT_SUSPENDED:
158 : case BUILDTIMEOUT_SET_EVENT_DISCARD:
159 : qnt = 1.0;
160 : break;
161 3 : case BUILDTIMEOUT_SET_EVENT_COMPUTED:
162 : case BUILDTIMEOUT_SET_EVENT_RESUME:
163 : default:
164 3 : qnt = circuit_build_times_quantile_cutoff();
165 3 : break;
166 : }
167 :
168 : /* The timeout rate is the ratio of the timeout count over
169 : * the total number of circuits attempted. The total number of
170 : * circuits is (timeouts+succeeded), since every circuit
171 : * either succeeds, or times out. "Closed" circuits are
172 : * MEASURE_TIMEOUT circuits whose measurement period expired.
173 : * All MEASURE_TIMEOUT circuits are counted in the timeouts stat
174 : * before transitioning to MEASURE_TIMEOUT (in
175 : * circuit_build_times_mark_circ_as_measurement_only()).
176 : * MEASURE_TIMEOUT circuits that succeed are *not* counted as
177 : * "succeeded". See circuit_build_times_handle_completed_hop().
178 : *
179 : * We cast the denominator
180 : * to promote it to double before the addition, to avoid int32
181 : * overflow. */
182 113 : const double total_circuits =
183 113 : ((double)cbt->num_circ_timeouts) + cbt->num_circ_succeeded;
184 113 : if (total_circuits >= 1.0) {
185 0 : timeout_rate = cbt->num_circ_timeouts / total_circuits;
186 0 : close_rate = cbt->num_circ_closed / total_circuits;
187 : }
188 :
189 113 : tor_asprintf(&args, "TOTAL_TIMES=%lu "
190 : "TIMEOUT_MS=%lu XM=%lu ALPHA=%f CUTOFF_QUANTILE=%f "
191 : "TIMEOUT_RATE=%f CLOSE_MS=%lu CLOSE_RATE=%f",
192 113 : (unsigned long)cbt->total_build_times,
193 113 : (unsigned long)cbt->timeout_ms,
194 113 : (unsigned long)cbt->Xm, cbt->alpha, qnt,
195 : timeout_rate,
196 113 : (unsigned long)cbt->close_ms,
197 : close_rate);
198 :
199 113 : control_event_buildtimeout_set(type, args);
200 :
201 113 : tor_free(args);
202 113 : }
203 : /** Set <b>global_event_mask*</b> to the bitwise OR of each live control
204 : * connection's event_mask field. */
205 : void
206 235 : control_update_global_event_mask(void)
207 : {
208 235 : smartlist_t *conns = get_connection_array();
209 235 : event_mask_t old_mask, new_mask;
210 235 : old_mask = global_event_mask;
211 235 : int any_old_per_sec_events = control_any_per_second_event_enabled();
212 :
213 235 : global_event_mask = 0;
214 235 : SMARTLIST_FOREACH(conns, connection_t *, _conn,
215 : {
216 : if (_conn->type == CONN_TYPE_CONTROL &&
217 : STATE_IS_OPEN(_conn->state)) {
218 : control_connection_t *conn = TO_CONTROL_CONN(_conn);
219 : global_event_mask |= conn->event_mask;
220 : }
221 : });
222 :
223 235 : new_mask = global_event_mask;
224 :
225 : /* Handle the aftermath. Set up the log callback to tell us only what
226 : * we want to hear...*/
227 235 : control_adjust_event_log_severity();
228 :
229 : /* Macro: true if ev was false before and is true now. */
230 : #define NEWLY_ENABLED(ev) \
231 : (! (old_mask & (ev)) && (new_mask & (ev)))
232 :
233 : /* ...then, if we've started logging stream or circ bw, clear the
234 : * appropriate fields. */
235 235 : if (NEWLY_ENABLED(EVENT_STREAM_BANDWIDTH_USED)) {
236 0 : SMARTLIST_FOREACH(conns, connection_t *, conn,
237 : {
238 : if (conn->type == CONN_TYPE_AP) {
239 : edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
240 : edge_conn->n_written = edge_conn->n_read = 0;
241 : }
242 : });
243 : }
244 235 : if (NEWLY_ENABLED(EVENT_CIRC_BANDWIDTH_USED)) {
245 0 : clear_circ_bw_fields();
246 : }
247 235 : if (NEWLY_ENABLED(EVENT_BANDWIDTH_USED)) {
248 0 : uint64_t r, w;
249 0 : control_get_bytes_rw_last_sec(&r, &w);
250 : }
251 235 : if (any_old_per_sec_events != control_any_per_second_event_enabled()) {
252 0 : rescan_periodic_events(get_options());
253 : }
254 :
255 : #undef NEWLY_ENABLED
256 235 : }
257 :
258 : /** Given a control event code for a message event, return the corresponding
259 : * log severity. */
260 : static inline int
261 0 : event_to_log_severity(int event)
262 : {
263 0 : switch (event) {
264 : case EVENT_DEBUG_MSG: return LOG_DEBUG;
265 : case EVENT_INFO_MSG: return LOG_INFO;
266 : case EVENT_NOTICE_MSG: return LOG_NOTICE;
267 : case EVENT_WARN_MSG: return LOG_WARN;
268 : case EVENT_ERR_MSG: return LOG_ERR;
269 : default: return -1;
270 : }
271 : }
272 :
273 : /** Adjust the log severities that result in control_event_logmsg being called
274 : * to match the severity of log messages that any controllers are interested
275 : * in. */
276 : void
277 244 : control_adjust_event_log_severity(void)
278 : {
279 244 : int i;
280 244 : int min_log_event=EVENT_ERR_MSG, max_log_event=EVENT_DEBUG_MSG;
281 :
282 1464 : for (i = EVENT_DEBUG_MSG; i <= EVENT_ERR_MSG; ++i) {
283 1220 : if (EVENT_IS_INTERESTING(i)) {
284 : min_log_event = i;
285 : break;
286 : }
287 : }
288 1464 : for (i = EVENT_ERR_MSG; i >= EVENT_DEBUG_MSG; --i) {
289 1220 : if (EVENT_IS_INTERESTING(i)) {
290 : max_log_event = i;
291 : break;
292 : }
293 : }
294 244 : if (EVENT_IS_INTERESTING(EVENT_STATUS_GENERAL)) {
295 0 : if (min_log_event > EVENT_NOTICE_MSG)
296 : min_log_event = EVENT_NOTICE_MSG;
297 : if (max_log_event < EVENT_ERR_MSG)
298 : max_log_event = EVENT_ERR_MSG;
299 : }
300 244 : if (min_log_event <= max_log_event)
301 0 : change_callback_log_severity(event_to_log_severity(min_log_event),
302 : event_to_log_severity(max_log_event),
303 : control_event_logmsg);
304 : else
305 244 : change_callback_log_severity(LOG_ERR, LOG_ERR,
306 : control_event_logmsg);
307 244 : }
308 :
309 : /** Return true iff the event with code <b>c</b> is being sent to any current
310 : * control connection. This is useful if the amount of work needed to prepare
311 : * to call the appropriate control_event_...() function is high.
312 : */
313 : int
314 4991 : control_event_is_interesting(int event)
315 : {
316 4991 : return EVENT_IS_INTERESTING(event);
317 : }
318 :
319 : /** Return true if any event that needs to fire once a second is enabled. */
320 : int
321 778 : control_any_per_second_event_enabled(void)
322 : {
323 778 : return ANY_EVENT_IS_INTERESTING(
324 : EVENT_MASK_(EVENT_BANDWIDTH_USED) |
325 : EVENT_MASK_(EVENT_CELL_STATS) |
326 : EVENT_MASK_(EVENT_CIRC_BANDWIDTH_USED) |
327 : EVENT_MASK_(EVENT_CONN_BW) |
328 : EVENT_MASK_(EVENT_STREAM_BANDWIDTH_USED)
329 : );
330 : }
331 :
332 : /* The value of 'get_bytes_read()' the previous time that
333 : * control_get_bytes_rw_last_sec() as called. */
334 : static uint64_t stats_prev_n_read = 0;
335 : /* The value of 'get_bytes_written()' the previous time that
336 : * control_get_bytes_rw_last_sec() as called. */
337 : static uint64_t stats_prev_n_written = 0;
338 :
339 : /**
340 : * Set <b>n_read</b> and <b>n_written</b> to the total number of bytes read
341 : * and written by Tor since the last call to this function.
342 : *
343 : * Call this only from the main thread.
344 : */
345 : static void
346 0 : control_get_bytes_rw_last_sec(uint64_t *n_read,
347 : uint64_t *n_written)
348 : {
349 0 : const uint64_t stats_n_bytes_read = get_bytes_read();
350 0 : const uint64_t stats_n_bytes_written = get_bytes_written();
351 :
352 0 : *n_read = stats_n_bytes_read - stats_prev_n_read;
353 0 : *n_written = stats_n_bytes_written - stats_prev_n_written;
354 0 : stats_prev_n_read = stats_n_bytes_read;
355 0 : stats_prev_n_written = stats_n_bytes_written;
356 0 : }
357 :
358 : /**
359 : * Run all the controller events (if any) that are scheduled to trigger once
360 : * per second.
361 : */
362 : void
363 0 : control_per_second_events(void)
364 : {
365 0 : if (!control_any_per_second_event_enabled())
366 0 : return;
367 :
368 0 : uint64_t bytes_read, bytes_written;
369 0 : control_get_bytes_rw_last_sec(&bytes_read, &bytes_written);
370 0 : control_event_bandwidth_used((uint32_t)bytes_read,(uint32_t)bytes_written);
371 :
372 0 : control_event_stream_bandwidth_used();
373 0 : control_event_conn_bandwidth_used();
374 0 : control_event_circ_bandwidth_used();
375 0 : control_event_circuit_cell_stats();
376 : }
377 :
378 : /** Represents an event that's queued to be sent to one or more
379 : * controllers. */
380 : typedef struct queued_event_t {
381 : uint16_t event;
382 : char *msg;
383 : } queued_event_t;
384 :
385 : /** Pointer to int. If this is greater than 0, we don't allow new events to be
386 : * queued. */
387 : static tor_threadlocal_t block_event_queue_flag;
388 :
389 : /** Holds a smartlist of queued_event_t objects that may need to be sent
390 : * to one or more controllers */
391 : static smartlist_t *queued_control_events = NULL;
392 :
393 : /** True if the flush_queued_events_event is pending. */
394 : static int flush_queued_event_pending = 0;
395 :
396 : /** Lock to protect the above fields. */
397 : static tor_mutex_t *queued_control_events_lock = NULL;
398 :
399 : /** An event that should fire in order to flush the contents of
400 : * queued_control_events. */
401 : static mainloop_event_t *flush_queued_events_event = NULL;
402 :
403 : void
404 13 : control_initialize_event_queue(void)
405 : {
406 13 : if (queued_control_events == NULL) {
407 13 : queued_control_events = smartlist_new();
408 : }
409 :
410 13 : if (flush_queued_events_event == NULL) {
411 13 : struct event_base *b = tor_libevent_get_base();
412 13 : if (b) {
413 26 : flush_queued_events_event =
414 13 : mainloop_event_new(flush_queued_events_cb, NULL);
415 13 : tor_assert(flush_queued_events_event);
416 : }
417 : }
418 :
419 13 : if (queued_control_events_lock == NULL) {
420 13 : queued_control_events_lock = tor_mutex_new();
421 13 : tor_threadlocal_init(&block_event_queue_flag);
422 : }
423 13 : }
424 :
425 : static int *
426 0 : get_block_event_queue(void)
427 : {
428 0 : int *val = tor_threadlocal_get(&block_event_queue_flag);
429 0 : if (PREDICT_UNLIKELY(val == NULL)) {
430 0 : val = tor_malloc_zero(sizeof(int));
431 0 : tor_threadlocal_set(&block_event_queue_flag, val);
432 : }
433 0 : return val;
434 : }
435 :
436 : /** Helper: inserts an event on the list of events queued to be sent to
437 : * one or more controllers, and schedules the events to be flushed if needed.
438 : *
439 : * This function takes ownership of <b>msg</b>, and may free it.
440 : *
441 : * We queue these events rather than send them immediately in order to break
442 : * the dependency in our callgraph from code that generates events for the
443 : * controller, and the network layer at large. Otherwise, nearly every
444 : * interesting part of Tor would potentially call every other interesting part
445 : * of Tor.
446 : */
447 229 : MOCK_IMPL(STATIC void,
448 : queue_control_event_string,(uint16_t event, char *msg))
449 : {
450 : /* This is redundant with checks done elsewhere, but it's a last-ditch
451 : * attempt to avoid queueing something we shouldn't have to queue. */
452 229 : if (PREDICT_UNLIKELY( ! EVENT_IS_INTERESTING(event) )) {
453 229 : tor_free(msg);
454 229 : return;
455 : }
456 :
457 0 : int *block_event_queue = get_block_event_queue();
458 0 : if (*block_event_queue) {
459 0 : tor_free(msg);
460 0 : return;
461 : }
462 :
463 0 : queued_event_t *ev = tor_malloc(sizeof(*ev));
464 0 : ev->event = event;
465 0 : ev->msg = msg;
466 :
467 : /* No queueing an event while queueing an event */
468 0 : ++*block_event_queue;
469 :
470 0 : tor_mutex_acquire(queued_control_events_lock);
471 0 : tor_assert(queued_control_events);
472 0 : smartlist_add(queued_control_events, ev);
473 :
474 0 : int activate_event = 0;
475 0 : if (! flush_queued_event_pending && in_main_thread()) {
476 0 : activate_event = 1;
477 0 : flush_queued_event_pending = 1;
478 : }
479 :
480 0 : tor_mutex_release(queued_control_events_lock);
481 :
482 0 : --*block_event_queue;
483 :
484 : /* We just put an event on the queue; mark the queue to be
485 : * flushed. We only do this from the main thread for now; otherwise,
486 : * we'd need to incur locking overhead in Libevent or use a socket.
487 : */
488 0 : if (activate_event) {
489 0 : tor_assert(flush_queued_events_event);
490 0 : mainloop_event_activate(flush_queued_events_event);
491 : }
492 : }
493 :
494 : #define queued_event_free(ev) \
495 : FREE_AND_NULL(queued_event_t, queued_event_free_, (ev))
496 :
497 : /** Release all storage held by <b>ev</b>. */
498 : static void
499 0 : queued_event_free_(queued_event_t *ev)
500 : {
501 0 : if (ev == NULL)
502 : return;
503 :
504 0 : tor_free(ev->msg);
505 0 : tor_free(ev);
506 : }
507 :
508 : /** Send every queued event to every controller that's interested in it,
509 : * and remove the events from the queue. If <b>force</b> is true,
510 : * then make all controllers send their data out immediately, since we
511 : * may be about to shut down. */
512 : static void
513 0 : queued_events_flush_all(int force)
514 : {
515 : /* Make sure that we get all the pending log events, if there are any. */
516 0 : flush_pending_log_callbacks();
517 :
518 0 : if (PREDICT_UNLIKELY(queued_control_events == NULL)) {
519 0 : return;
520 : }
521 0 : smartlist_t *all_conns = get_connection_array();
522 0 : smartlist_t *controllers = smartlist_new();
523 0 : smartlist_t *queued_events;
524 :
525 0 : int *block_event_queue = get_block_event_queue();
526 0 : ++*block_event_queue;
527 :
528 0 : tor_mutex_acquire(queued_control_events_lock);
529 : /* No queueing an event while flushing events. */
530 0 : flush_queued_event_pending = 0;
531 0 : queued_events = queued_control_events;
532 0 : queued_control_events = smartlist_new();
533 0 : tor_mutex_release(queued_control_events_lock);
534 :
535 : /* Gather all the controllers that will care... */
536 0 : SMARTLIST_FOREACH_BEGIN(all_conns, connection_t *, conn) {
537 0 : if (conn->type == CONN_TYPE_CONTROL &&
538 0 : !conn->marked_for_close &&
539 0 : conn->state == CONTROL_CONN_STATE_OPEN) {
540 0 : control_connection_t *control_conn = TO_CONTROL_CONN(conn);
541 :
542 0 : smartlist_add(controllers, control_conn);
543 : }
544 0 : } SMARTLIST_FOREACH_END(conn);
545 :
546 0 : SMARTLIST_FOREACH_BEGIN(queued_events, queued_event_t *, ev) {
547 0 : const event_mask_t bit = ((event_mask_t)1) << ev->event;
548 0 : const size_t msg_len = strlen(ev->msg);
549 0 : SMARTLIST_FOREACH_BEGIN(controllers, control_connection_t *,
550 : control_conn) {
551 0 : if (control_conn->event_mask & bit) {
552 0 : connection_buf_add(ev->msg, msg_len, TO_CONN(control_conn));
553 : }
554 0 : } SMARTLIST_FOREACH_END(control_conn);
555 :
556 0 : queued_event_free(ev);
557 0 : } SMARTLIST_FOREACH_END(ev);
558 :
559 0 : if (force) {
560 0 : SMARTLIST_FOREACH_BEGIN(controllers, control_connection_t *,
561 : control_conn) {
562 0 : connection_flush(TO_CONN(control_conn));
563 0 : } SMARTLIST_FOREACH_END(control_conn);
564 : }
565 :
566 0 : smartlist_free(queued_events);
567 0 : smartlist_free(controllers);
568 :
569 0 : --*block_event_queue;
570 : }
571 :
572 : /** Libevent callback: Flushes pending events to controllers that are
573 : * interested in them. */
574 : static void
575 0 : flush_queued_events_cb(mainloop_event_t *event, void *arg)
576 : {
577 0 : (void) event;
578 0 : (void) arg;
579 0 : queued_events_flush_all(0);
580 0 : }
581 :
582 : /** Send an event to all v1 controllers that are listening for code
583 : * <b>event</b>. The event's body is given by <b>msg</b>.
584 : *
585 : * The EXTENDED_FORMAT and NONEXTENDED_FORMAT flags behave similarly with
586 : * respect to the EXTENDED_EVENTS feature. */
587 107 : MOCK_IMPL(STATIC void,
588 : send_control_event_string,(uint16_t event,
589 : const char *msg))
590 : {
591 107 : tor_assert(event >= EVENT_MIN_ && event <= EVENT_MAX_);
592 107 : queue_control_event_string(event, tor_strdup(msg));
593 107 : }
594 :
595 : /** Helper for send_control_event and control_event_status:
596 : * Send an event to all v1 controllers that are listening for code
597 : * <b>event</b>. The event's body is created by the printf-style format in
598 : * <b>format</b>, and other arguments as provided. */
599 : static void
600 173 : send_control_event_impl(uint16_t event,
601 : const char *format, va_list ap)
602 : {
603 173 : char *buf = NULL;
604 173 : int len;
605 :
606 173 : len = tor_vasprintf(&buf, format, ap);
607 173 : if (len < 0) {
608 0 : log_warn(LD_BUG, "Unable to format event for controller.");
609 0 : return;
610 : }
611 :
612 173 : queue_control_event_string(event, buf);
613 : }
614 :
615 : /** Send an event to all v1 controllers that are listening for code
616 : * <b>event</b>. The event's body is created by the printf-style format in
617 : * <b>format</b>, and other arguments as provided. */
618 : static void
619 173 : send_control_event(uint16_t event,
620 : const char *format, ...)
621 : {
622 173 : va_list ap;
623 173 : va_start(ap, format);
624 173 : send_control_event_impl(event, format, ap);
625 173 : va_end(ap);
626 173 : }
627 :
628 : /** Something major has happened to circuit <b>circ</b>: tell any
629 : * interested control connections. */
630 : int
631 1 : control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp,
632 : int reason_code)
633 : {
634 1 : const char *status;
635 1 : char reasons[64] = "";
636 :
637 1 : if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS))
638 : return 0;
639 0 : tor_assert(circ);
640 :
641 0 : switch (tp)
642 : {
643 : case CIRC_EVENT_LAUNCHED: status = "LAUNCHED"; break;
644 0 : case CIRC_EVENT_BUILT: status = "BUILT"; break;
645 0 : case CIRC_EVENT_EXTENDED: status = "EXTENDED"; break;
646 0 : case CIRC_EVENT_FAILED: status = "FAILED"; break;
647 0 : case CIRC_EVENT_CLOSED: status = "CLOSED"; break;
648 0 : default:
649 0 : log_warn(LD_BUG, "Unrecognized status code %d", (int)tp);
650 0 : tor_fragile_assert();
651 : return 0;
652 : }
653 :
654 0 : if (tp == CIRC_EVENT_FAILED || tp == CIRC_EVENT_CLOSED) {
655 0 : const char *reason_str = circuit_end_reason_to_control_string(reason_code);
656 0 : char unk_reason_buf[16];
657 0 : if (!reason_str) {
658 0 : tor_snprintf(unk_reason_buf, 16, "UNKNOWN_%d", reason_code);
659 0 : reason_str = unk_reason_buf;
660 : }
661 0 : if (reason_code > 0 && reason_code & END_CIRC_REASON_FLAG_REMOTE) {
662 0 : tor_snprintf(reasons, sizeof(reasons),
663 : " REASON=DESTROYED REMOTE_REASON=%s", reason_str);
664 : } else {
665 0 : tor_snprintf(reasons, sizeof(reasons),
666 : " REASON=%s", reason_str);
667 : }
668 : }
669 :
670 : {
671 0 : char *circdesc = circuit_describe_status_for_controller(circ);
672 0 : const char *sp = strlen(circdesc) ? " " : "";
673 0 : send_control_event(EVENT_CIRCUIT_STATUS,
674 : "650 CIRC %lu %s%s%s%s\r\n",
675 0 : (unsigned long)circ->global_identifier,
676 : status, sp,
677 : circdesc,
678 : reasons);
679 0 : tor_free(circdesc);
680 : }
681 :
682 0 : return 0;
683 : }
684 :
685 : /** Something minor has happened to circuit <b>circ</b>: tell any
686 : * interested control connections. */
687 : static int
688 10 : control_event_circuit_status_minor(origin_circuit_t *circ,
689 : circuit_status_minor_event_t e,
690 : int purpose, const struct timeval *tv)
691 : {
692 10 : const char *event_desc;
693 10 : char event_tail[160] = "";
694 10 : if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS_MINOR))
695 : return 0;
696 0 : tor_assert(circ);
697 :
698 0 : switch (e)
699 : {
700 0 : case CIRC_MINOR_EVENT_PURPOSE_CHANGED:
701 0 : event_desc = "PURPOSE_CHANGED";
702 :
703 : {
704 : /* event_tail can currently be up to 68 chars long */
705 0 : const char *hs_state_str =
706 0 : circuit_purpose_to_controller_hs_state_string(purpose);
707 0 : tor_snprintf(event_tail, sizeof(event_tail),
708 : " OLD_PURPOSE=%s%s%s",
709 : circuit_purpose_to_controller_string(purpose),
710 : (hs_state_str != NULL) ? " OLD_HS_STATE=" : "",
711 : (hs_state_str != NULL) ? hs_state_str : "");
712 : }
713 :
714 0 : break;
715 0 : case CIRC_MINOR_EVENT_CANNIBALIZED:
716 0 : event_desc = "CANNIBALIZED";
717 :
718 : {
719 : /* event_tail can currently be up to 130 chars long */
720 0 : const char *hs_state_str =
721 0 : circuit_purpose_to_controller_hs_state_string(purpose);
722 0 : const struct timeval *old_timestamp_began = tv;
723 0 : char tbuf[ISO_TIME_USEC_LEN+1];
724 0 : format_iso_time_nospace_usec(tbuf, old_timestamp_began);
725 :
726 0 : tor_snprintf(event_tail, sizeof(event_tail),
727 : " OLD_PURPOSE=%s%s%s OLD_TIME_CREATED=%s",
728 : circuit_purpose_to_controller_string(purpose),
729 : (hs_state_str != NULL) ? " OLD_HS_STATE=" : "",
730 : (hs_state_str != NULL) ? hs_state_str : "",
731 : tbuf);
732 : }
733 :
734 0 : break;
735 0 : default:
736 0 : log_warn(LD_BUG, "Unrecognized status code %d", (int)e);
737 0 : tor_fragile_assert();
738 : return 0;
739 : }
740 :
741 : {
742 0 : char *circdesc = circuit_describe_status_for_controller(circ);
743 0 : const char *sp = strlen(circdesc) ? " " : "";
744 0 : send_control_event(EVENT_CIRCUIT_STATUS_MINOR,
745 : "650 CIRC_MINOR %lu %s%s%s%s\r\n",
746 0 : (unsigned long)circ->global_identifier,
747 : event_desc, sp,
748 : circdesc,
749 : event_tail);
750 0 : tor_free(circdesc);
751 : }
752 :
753 0 : return 0;
754 : }
755 :
756 : /**
757 : * <b>circ</b> has changed its purpose from <b>old_purpose</b>: tell any
758 : * interested controllers.
759 : */
760 : int
761 10 : control_event_circuit_purpose_changed(origin_circuit_t *circ,
762 : int old_purpose)
763 : {
764 10 : return control_event_circuit_status_minor(circ,
765 : CIRC_MINOR_EVENT_PURPOSE_CHANGED,
766 : old_purpose,
767 : NULL);
768 : }
769 :
770 : /**
771 : * <b>circ</b> has changed its purpose from <b>old_purpose</b>, and its
772 : * created-time from <b>old_tv_created</b>: tell any interested controllers.
773 : */
774 : int
775 0 : control_event_circuit_cannibalized(origin_circuit_t *circ,
776 : int old_purpose,
777 : const struct timeval *old_tv_created)
778 : {
779 0 : return control_event_circuit_status_minor(circ,
780 : CIRC_MINOR_EVENT_CANNIBALIZED,
781 : old_purpose,
782 : old_tv_created);
783 : }
784 :
785 : /** Something has happened to the stream associated with AP connection
786 : * <b>conn</b>: tell any interested control connections. */
787 : int
788 27 : control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp,
789 : int reason_code)
790 : {
791 27 : char reason_buf[64];
792 27 : char addrport_buf[64];
793 27 : const char *status;
794 27 : circuit_t *circ;
795 27 : origin_circuit_t *origin_circ = NULL;
796 27 : char buf[256];
797 27 : const char *purpose = "";
798 27 : tor_assert(conn->socks_request);
799 :
800 27 : if (!EVENT_IS_INTERESTING(EVENT_STREAM_STATUS))
801 : return 0;
802 :
803 0 : if (tp == STREAM_EVENT_CLOSED &&
804 0 : (reason_code & END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED))
805 : return 0;
806 :
807 0 : write_stream_target_to_buf(conn, buf, sizeof(buf));
808 :
809 0 : reason_buf[0] = '\0';
810 0 : switch (tp)
811 : {
812 : case STREAM_EVENT_SENT_CONNECT: status = "SENTCONNECT"; break;
813 0 : case STREAM_EVENT_SENT_RESOLVE: status = "SENTRESOLVE"; break;
814 0 : case STREAM_EVENT_SUCCEEDED: status = "SUCCEEDED"; break;
815 0 : case STREAM_EVENT_FAILED: status = "FAILED"; break;
816 0 : case STREAM_EVENT_CLOSED: status = "CLOSED"; break;
817 0 : case STREAM_EVENT_NEW: status = "NEW"; break;
818 0 : case STREAM_EVENT_NEW_RESOLVE: status = "NEWRESOLVE"; break;
819 0 : case STREAM_EVENT_FAILED_RETRIABLE: status = "DETACHED"; break;
820 0 : case STREAM_EVENT_REMAP: status = "REMAP"; break;
821 0 : case STREAM_EVENT_CONTROLLER_WAIT: status = "CONTROLLER_WAIT"; break;
822 0 : default:
823 0 : log_warn(LD_BUG, "Unrecognized status code %d", (int)tp);
824 0 : return 0;
825 : }
826 0 : if (reason_code && (tp == STREAM_EVENT_FAILED ||
827 0 : tp == STREAM_EVENT_CLOSED ||
828 0 : tp == STREAM_EVENT_FAILED_RETRIABLE)) {
829 0 : const char *reason_str = stream_end_reason_to_control_string(reason_code);
830 0 : char *r = NULL;
831 0 : if (!reason_str) {
832 0 : tor_asprintf(&r, " UNKNOWN_%d", reason_code);
833 0 : reason_str = r;
834 : }
835 0 : if (reason_code & END_STREAM_REASON_FLAG_REMOTE)
836 0 : tor_snprintf(reason_buf, sizeof(reason_buf),
837 : " REASON=END REMOTE_REASON=%s", reason_str);
838 : else
839 0 : tor_snprintf(reason_buf, sizeof(reason_buf),
840 : " REASON=%s", reason_str);
841 0 : tor_free(r);
842 0 : } else if (reason_code && tp == STREAM_EVENT_REMAP) {
843 0 : switch (reason_code) {
844 0 : case REMAP_STREAM_SOURCE_CACHE:
845 0 : strlcpy(reason_buf, " SOURCE=CACHE", sizeof(reason_buf));
846 0 : break;
847 0 : case REMAP_STREAM_SOURCE_EXIT:
848 0 : strlcpy(reason_buf, " SOURCE=EXIT", sizeof(reason_buf));
849 0 : break;
850 0 : default:
851 0 : tor_snprintf(reason_buf, sizeof(reason_buf), " REASON=UNKNOWN_%d",
852 : reason_code);
853 : /* XXX do we want SOURCE=UNKNOWN_%d above instead? -RD */
854 0 : break;
855 : }
856 : }
857 :
858 0 : if (tp == STREAM_EVENT_NEW || tp == STREAM_EVENT_NEW_RESOLVE) {
859 : /*
860 : * When the control conn is an AF_UNIX socket and we have no address,
861 : * it gets set to "(Tor_internal)"; see dnsserv_launch_request() in
862 : * dnsserv.c.
863 : */
864 0 : if (strcmp(ENTRY_TO_CONN(conn)->address, "(Tor_internal)") != 0) {
865 0 : tor_snprintf(addrport_buf,sizeof(addrport_buf), " SOURCE_ADDR=%s:%d",
866 0 : ENTRY_TO_CONN(conn)->address, ENTRY_TO_CONN(conn)->port);
867 : } else {
868 : /*
869 : * else leave it blank so control on AF_UNIX doesn't need to make
870 : * something up.
871 : */
872 0 : addrport_buf[0] = '\0';
873 : }
874 : } else {
875 0 : addrport_buf[0] = '\0';
876 : }
877 :
878 0 : if (tp == STREAM_EVENT_NEW_RESOLVE) {
879 : purpose = " PURPOSE=DNS_REQUEST";
880 0 : } else if (tp == STREAM_EVENT_NEW) {
881 0 : if (conn->use_begindir) {
882 0 : connection_t *linked = ENTRY_TO_CONN(conn)->linked_conn;
883 0 : int linked_dir_purpose = -1;
884 0 : if (linked && linked->type == CONN_TYPE_DIR)
885 0 : linked_dir_purpose = linked->purpose;
886 0 : if (DIR_PURPOSE_IS_UPLOAD(linked_dir_purpose))
887 : purpose = " PURPOSE=DIR_UPLOAD";
888 : else
889 0 : purpose = " PURPOSE=DIR_FETCH";
890 : } else
891 : purpose = " PURPOSE=USER";
892 : }
893 :
894 0 : circ = circuit_get_by_edge_conn(ENTRY_TO_EDGE_CONN(conn));
895 0 : if (circ && CIRCUIT_IS_ORIGIN(circ))
896 0 : origin_circ = TO_ORIGIN_CIRCUIT(circ);
897 :
898 : {
899 0 : char *conndesc = entry_connection_describe_status_for_controller(conn);
900 0 : const char *sp = strlen(conndesc) ? " " : "";
901 0 : send_control_event(EVENT_STREAM_STATUS,
902 : "650 STREAM %"PRIu64" %s %lu %s%s%s%s%s%s\r\n",
903 : (ENTRY_TO_CONN(conn)->global_identifier),
904 : status,
905 : origin_circ?
906 0 : (unsigned long)origin_circ->global_identifier : 0ul,
907 : buf, reason_buf, addrport_buf, purpose, sp, conndesc);
908 0 : tor_free(conndesc);
909 : }
910 :
911 : /* XXX need to specify its intended exit, etc? */
912 :
913 0 : return 0;
914 : }
915 :
916 : /** Called when the status of an OR connection <b>conn</b> changes: tell any
917 : * interested control connections. <b>tp</b> is the new status for the
918 : * connection. If <b>conn</b> has just closed or failed, then <b>reason</b>
919 : * may be the reason why.
920 : */
921 : int
922 5 : control_event_or_conn_status(or_connection_t *conn, or_conn_status_event_t tp,
923 : int reason)
924 : {
925 5 : int ncircs = 0;
926 5 : const char *status;
927 5 : char name[128];
928 5 : char ncircs_buf[32] = {0}; /* > 8 + log10(2^32)=10 + 2 */
929 :
930 5 : if (!EVENT_IS_INTERESTING(EVENT_OR_CONN_STATUS))
931 : return 0;
932 :
933 0 : switch (tp)
934 : {
935 : case OR_CONN_EVENT_LAUNCHED: status = "LAUNCHED"; break;
936 0 : case OR_CONN_EVENT_CONNECTED: status = "CONNECTED"; break;
937 0 : case OR_CONN_EVENT_FAILED: status = "FAILED"; break;
938 0 : case OR_CONN_EVENT_CLOSED: status = "CLOSED"; break;
939 0 : case OR_CONN_EVENT_NEW: status = "NEW"; break;
940 0 : default:
941 0 : log_warn(LD_BUG, "Unrecognized status code %d", (int)tp);
942 0 : return 0;
943 : }
944 0 : if (conn->chan) {
945 0 : ncircs = circuit_count_pending_on_channel(TLS_CHAN_TO_BASE(conn->chan));
946 : } else {
947 : ncircs = 0;
948 : }
949 0 : ncircs += connection_or_get_num_circuits(conn);
950 0 : if (ncircs && (tp == OR_CONN_EVENT_FAILED || tp == OR_CONN_EVENT_CLOSED)) {
951 0 : tor_snprintf(ncircs_buf, sizeof(ncircs_buf), " NCIRCS=%d", ncircs);
952 : }
953 :
954 0 : orconn_target_get_name(name, sizeof(name), conn);
955 0 : send_control_event(EVENT_OR_CONN_STATUS,
956 : "650 ORCONN %s %s%s%s%s ID=%"PRIu64"\r\n",
957 : name, status,
958 : reason ? " REASON=" : "",
959 : orconn_end_reason_to_control_string(reason),
960 : ncircs_buf,
961 : (conn->base_.global_identifier));
962 :
963 0 : return 0;
964 : }
965 :
966 : /**
967 : * Print out STREAM_BW event for a single conn
968 : */
969 : int
970 6 : control_event_stream_bandwidth(edge_connection_t *edge_conn)
971 : {
972 6 : struct timeval now;
973 6 : char tbuf[ISO_TIME_USEC_LEN+1];
974 6 : if (EVENT_IS_INTERESTING(EVENT_STREAM_BANDWIDTH_USED)) {
975 0 : if (!edge_conn->n_read && !edge_conn->n_written)
976 : return 0;
977 :
978 0 : tor_gettimeofday(&now);
979 0 : format_iso_time_nospace_usec(tbuf, &now);
980 0 : send_control_event(EVENT_STREAM_BANDWIDTH_USED,
981 : "650 STREAM_BW %"PRIu64" %lu %lu %s\r\n",
982 : (edge_conn->base_.global_identifier),
983 0 : (unsigned long)edge_conn->n_read,
984 0 : (unsigned long)edge_conn->n_written,
985 : tbuf);
986 :
987 0 : edge_conn->n_written = edge_conn->n_read = 0;
988 : }
989 :
990 : return 0;
991 : }
992 :
993 : /** A second or more has elapsed: tell any interested control
994 : * connections how much bandwidth streams have used. */
995 : int
996 0 : control_event_stream_bandwidth_used(void)
997 : {
998 0 : if (EVENT_IS_INTERESTING(EVENT_STREAM_BANDWIDTH_USED)) {
999 0 : smartlist_t *conns = get_connection_array();
1000 0 : edge_connection_t *edge_conn;
1001 0 : struct timeval now;
1002 0 : char tbuf[ISO_TIME_USEC_LEN+1];
1003 :
1004 0 : SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn)
1005 : {
1006 0 : if (conn->type != CONN_TYPE_AP)
1007 0 : continue;
1008 0 : edge_conn = TO_EDGE_CONN(conn);
1009 0 : if (!edge_conn->n_read && !edge_conn->n_written)
1010 0 : continue;
1011 :
1012 0 : tor_gettimeofday(&now);
1013 0 : format_iso_time_nospace_usec(tbuf, &now);
1014 0 : send_control_event(EVENT_STREAM_BANDWIDTH_USED,
1015 : "650 STREAM_BW %"PRIu64" %lu %lu %s\r\n",
1016 : (edge_conn->base_.global_identifier),
1017 0 : (unsigned long)edge_conn->n_read,
1018 0 : (unsigned long)edge_conn->n_written,
1019 : tbuf);
1020 :
1021 0 : edge_conn->n_written = edge_conn->n_read = 0;
1022 : }
1023 0 : SMARTLIST_FOREACH_END(conn);
1024 : }
1025 :
1026 0 : return 0;
1027 : }
1028 :
1029 : /** A second or more has elapsed: tell any interested control connections
1030 : * how much bandwidth origin circuits have used. */
1031 : int
1032 0 : control_event_circ_bandwidth_used(void)
1033 : {
1034 0 : if (!EVENT_IS_INTERESTING(EVENT_CIRC_BANDWIDTH_USED))
1035 : return 0;
1036 :
1037 0 : SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
1038 0 : if (!CIRCUIT_IS_ORIGIN(circ))
1039 0 : continue;
1040 :
1041 0 : control_event_circ_bandwidth_used_for_circ(TO_ORIGIN_CIRCUIT(circ));
1042 : }
1043 0 : SMARTLIST_FOREACH_END(circ);
1044 :
1045 : return 0;
1046 : }
1047 :
1048 : /**
1049 : * Emit a CIRC_BW event line for a specific circuit.
1050 : *
1051 : * This function sets the values it emits to 0, and does not emit
1052 : * an event if there is no new data to report since the last call.
1053 : *
1054 : * Therefore, it may be called at any frequency.
1055 : */
1056 : int
1057 0 : control_event_circ_bandwidth_used_for_circ(origin_circuit_t *ocirc)
1058 : {
1059 0 : struct timeval now;
1060 0 : char tbuf[ISO_TIME_USEC_LEN+1];
1061 :
1062 0 : tor_assert(ocirc);
1063 :
1064 0 : if (!EVENT_IS_INTERESTING(EVENT_CIRC_BANDWIDTH_USED))
1065 : return 0;
1066 :
1067 : /* n_read_circ_bw and n_written_circ_bw are always updated
1068 : * when there is any new cell on a circuit, and set to 0 after
1069 : * the event, below.
1070 : *
1071 : * Therefore, checking them is sufficient to determine if there
1072 : * is new data to report. */
1073 0 : if (!ocirc->n_read_circ_bw && !ocirc->n_written_circ_bw)
1074 : return 0;
1075 :
1076 0 : tor_gettimeofday(&now);
1077 0 : format_iso_time_nospace_usec(tbuf, &now);
1078 0 : send_control_event(EVENT_CIRC_BANDWIDTH_USED,
1079 : "650 CIRC_BW ID=%d READ=%lu WRITTEN=%lu TIME=%s "
1080 : "DELIVERED_READ=%lu OVERHEAD_READ=%lu "
1081 : "DELIVERED_WRITTEN=%lu OVERHEAD_WRITTEN=%lu\r\n",
1082 : ocirc->global_identifier,
1083 0 : (unsigned long)ocirc->n_read_circ_bw,
1084 0 : (unsigned long)ocirc->n_written_circ_bw,
1085 : tbuf,
1086 0 : (unsigned long)ocirc->n_delivered_read_circ_bw,
1087 0 : (unsigned long)ocirc->n_overhead_read_circ_bw,
1088 0 : (unsigned long)ocirc->n_delivered_written_circ_bw,
1089 0 : (unsigned long)ocirc->n_overhead_written_circ_bw);
1090 0 : ocirc->n_written_circ_bw = ocirc->n_read_circ_bw = 0;
1091 0 : ocirc->n_overhead_written_circ_bw = ocirc->n_overhead_read_circ_bw = 0;
1092 0 : ocirc->n_delivered_written_circ_bw = ocirc->n_delivered_read_circ_bw = 0;
1093 :
1094 0 : return 0;
1095 : }
1096 :
1097 : /** Print out CONN_BW event for a single OR/DIR/EXIT <b>conn</b> and reset
1098 : * bandwidth counters. */
1099 : int
1100 14 : control_event_conn_bandwidth(connection_t *conn)
1101 : {
1102 14 : const char *conn_type_str;
1103 14 : if (!get_options()->TestingEnableConnBwEvent ||
1104 0 : !EVENT_IS_INTERESTING(EVENT_CONN_BW))
1105 : return 0;
1106 0 : if (!conn->n_read_conn_bw && !conn->n_written_conn_bw)
1107 : return 0;
1108 0 : switch (conn->type) {
1109 : case CONN_TYPE_OR:
1110 : conn_type_str = "OR";
1111 : break;
1112 0 : case CONN_TYPE_DIR:
1113 0 : conn_type_str = "DIR";
1114 0 : break;
1115 0 : case CONN_TYPE_EXIT:
1116 0 : conn_type_str = "EXIT";
1117 0 : break;
1118 : default:
1119 : return 0;
1120 : }
1121 0 : send_control_event(EVENT_CONN_BW,
1122 : "650 CONN_BW ID=%"PRIu64" TYPE=%s "
1123 : "READ=%lu WRITTEN=%lu\r\n",
1124 : (conn->global_identifier),
1125 : conn_type_str,
1126 0 : (unsigned long)conn->n_read_conn_bw,
1127 0 : (unsigned long)conn->n_written_conn_bw);
1128 0 : conn->n_written_conn_bw = conn->n_read_conn_bw = 0;
1129 0 : return 0;
1130 : }
1131 :
1132 : /** A second or more has elapsed: tell any interested control
1133 : * connections how much bandwidth connections have used. */
1134 : int
1135 0 : control_event_conn_bandwidth_used(void)
1136 : {
1137 0 : if (get_options()->TestingEnableConnBwEvent &&
1138 0 : EVENT_IS_INTERESTING(EVENT_CONN_BW)) {
1139 0 : SMARTLIST_FOREACH(get_connection_array(), connection_t *, conn,
1140 : control_event_conn_bandwidth(conn));
1141 : }
1142 0 : return 0;
1143 : }
1144 :
1145 : /** Helper: iterate over cell statistics of <b>circ</b> and sum up added
1146 : * cells, removed cells, and waiting times by cell command and direction.
1147 : * Store results in <b>cell_stats</b>. Free cell statistics of the
1148 : * circuit afterwards. */
1149 : void
1150 4 : sum_up_cell_stats_by_command(circuit_t *circ, cell_stats_t *cell_stats)
1151 : {
1152 4 : memset(cell_stats, 0, sizeof(cell_stats_t));
1153 8 : SMARTLIST_FOREACH_BEGIN(circ->testing_cell_stats,
1154 : const testing_cell_stats_entry_t *, ent) {
1155 4 : tor_assert(ent->command <= CELL_COMMAND_MAX_);
1156 4 : if (!ent->removed && !ent->exitward) {
1157 1 : cell_stats->added_cells_appward[ent->command] += 1;
1158 3 : } else if (!ent->removed && ent->exitward) {
1159 1 : cell_stats->added_cells_exitward[ent->command] += 1;
1160 2 : } else if (!ent->exitward) {
1161 1 : cell_stats->removed_cells_appward[ent->command] += 1;
1162 1 : cell_stats->total_time_appward[ent->command] += ent->waiting_time * 10;
1163 : } else {
1164 1 : cell_stats->removed_cells_exitward[ent->command] += 1;
1165 1 : cell_stats->total_time_exitward[ent->command] += ent->waiting_time * 10;
1166 : }
1167 4 : } SMARTLIST_FOREACH_END(ent);
1168 4 : circuit_clear_testing_cell_stats(circ);
1169 4 : }
1170 :
1171 : /** Helper: append a cell statistics string to <code>event_parts</code>,
1172 : * prefixed with <code>key</code>=. Statistics consist of comma-separated
1173 : * key:value pairs with lower-case command strings as keys and cell
1174 : * numbers or total waiting times as values. A key:value pair is included
1175 : * if the entry in <code>include_if_non_zero</code> is not zero, but with
1176 : * the (possibly zero) entry from <code>number_to_include</code>. Both
1177 : * arrays are expected to have a length of CELL_COMMAND_MAX_ + 1. If no
1178 : * entry in <code>include_if_non_zero</code> is positive, no string will
1179 : * be added to <code>event_parts</code>. */
1180 : void
1181 34 : append_cell_stats_by_command(smartlist_t *event_parts, const char *key,
1182 : const uint64_t *include_if_non_zero,
1183 : const uint64_t *number_to_include)
1184 : {
1185 34 : smartlist_t *key_value_strings = smartlist_new();
1186 34 : int i;
1187 4590 : for (i = 0; i <= CELL_COMMAND_MAX_; i++) {
1188 4522 : if (include_if_non_zero[i] > 0) {
1189 14 : smartlist_add_asprintf(key_value_strings, "%s:%"PRIu64,
1190 : cell_command_to_string(i),
1191 14 : (number_to_include[i]));
1192 : }
1193 : }
1194 34 : if (smartlist_len(key_value_strings) > 0) {
1195 11 : char *joined = smartlist_join_strings(key_value_strings, ",", 0, NULL);
1196 11 : smartlist_add_asprintf(event_parts, "%s=%s", key, joined);
1197 25 : SMARTLIST_FOREACH(key_value_strings, char *, cp, tor_free(cp));
1198 11 : tor_free(joined);
1199 : }
1200 34 : smartlist_free(key_value_strings);
1201 34 : }
1202 :
1203 : /** Helper: format <b>cell_stats</b> for <b>circ</b> for inclusion in a
1204 : * CELL_STATS event and write result string to <b>event_string</b>. */
1205 : void
1206 7 : format_cell_stats(char **event_string, circuit_t *circ,
1207 : cell_stats_t *cell_stats)
1208 : {
1209 7 : smartlist_t *event_parts = smartlist_new();
1210 7 : if (CIRCUIT_IS_ORIGIN(circ)) {
1211 4 : origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
1212 4 : smartlist_add_asprintf(event_parts, "ID=%lu",
1213 4 : (unsigned long)ocirc->global_identifier);
1214 3 : } else if (TO_OR_CIRCUIT(circ)->p_chan) {
1215 3 : or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
1216 3 : smartlist_add_asprintf(event_parts, "InboundQueue=%lu",
1217 3 : (unsigned long)or_circ->p_circ_id);
1218 3 : smartlist_add_asprintf(event_parts, "InboundConn=%"PRIu64,
1219 3 : (or_circ->p_chan->global_identifier));
1220 3 : append_cell_stats_by_command(event_parts, "InboundAdded",
1221 : cell_stats->added_cells_appward,
1222 3 : cell_stats->added_cells_appward);
1223 3 : append_cell_stats_by_command(event_parts, "InboundRemoved",
1224 : cell_stats->removed_cells_appward,
1225 3 : cell_stats->removed_cells_appward);
1226 3 : append_cell_stats_by_command(event_parts, "InboundTime",
1227 : cell_stats->removed_cells_appward,
1228 3 : cell_stats->total_time_appward);
1229 : }
1230 7 : if (circ->n_chan) {
1231 7 : smartlist_add_asprintf(event_parts, "OutboundQueue=%lu",
1232 7 : (unsigned long)circ->n_circ_id);
1233 7 : smartlist_add_asprintf(event_parts, "OutboundConn=%"PRIu64,
1234 7 : (circ->n_chan->global_identifier));
1235 7 : append_cell_stats_by_command(event_parts, "OutboundAdded",
1236 : cell_stats->added_cells_exitward,
1237 7 : cell_stats->added_cells_exitward);
1238 7 : append_cell_stats_by_command(event_parts, "OutboundRemoved",
1239 : cell_stats->removed_cells_exitward,
1240 7 : cell_stats->removed_cells_exitward);
1241 7 : append_cell_stats_by_command(event_parts, "OutboundTime",
1242 : cell_stats->removed_cells_exitward,
1243 7 : cell_stats->total_time_exitward);
1244 : }
1245 7 : *event_string = smartlist_join_strings(event_parts, " ", 0, NULL);
1246 40 : SMARTLIST_FOREACH(event_parts, char *, cp, tor_free(cp));
1247 7 : smartlist_free(event_parts);
1248 7 : }
1249 :
1250 : /** A second or more has elapsed: tell any interested control connection
1251 : * how many cells have been processed for a given circuit. */
1252 : int
1253 0 : control_event_circuit_cell_stats(void)
1254 : {
1255 0 : cell_stats_t *cell_stats;
1256 0 : char *event_string;
1257 0 : if (!get_options()->TestingEnableCellStatsEvent ||
1258 0 : !EVENT_IS_INTERESTING(EVENT_CELL_STATS))
1259 : return 0;
1260 0 : cell_stats = tor_malloc(sizeof(cell_stats_t));
1261 0 : SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
1262 0 : if (!circ->testing_cell_stats)
1263 0 : continue;
1264 0 : sum_up_cell_stats_by_command(circ, cell_stats);
1265 0 : format_cell_stats(&event_string, circ, cell_stats);
1266 0 : send_control_event(EVENT_CELL_STATS,
1267 : "650 CELL_STATS %s\r\n", event_string);
1268 0 : tor_free(event_string);
1269 : }
1270 0 : SMARTLIST_FOREACH_END(circ);
1271 0 : tor_free(cell_stats);
1272 0 : return 0;
1273 : }
1274 :
1275 : /* about 5 minutes worth. */
1276 : #define N_BW_EVENTS_TO_CACHE 300
1277 : /* Index into cached_bw_events to next write. */
1278 : static int next_measurement_idx = 0;
1279 : /* number of entries set in n_measurements */
1280 : static int n_measurements = 0;
1281 : static struct cached_bw_event_t {
1282 : uint32_t n_read;
1283 : uint32_t n_written;
1284 : } cached_bw_events[N_BW_EVENTS_TO_CACHE];
1285 :
1286 : /** A second or more has elapsed: tell any interested control
1287 : * connections how much bandwidth we used. */
1288 : int
1289 0 : control_event_bandwidth_used(uint32_t n_read, uint32_t n_written)
1290 : {
1291 0 : cached_bw_events[next_measurement_idx].n_read = n_read;
1292 0 : cached_bw_events[next_measurement_idx].n_written = n_written;
1293 0 : if (++next_measurement_idx == N_BW_EVENTS_TO_CACHE)
1294 0 : next_measurement_idx = 0;
1295 0 : if (n_measurements < N_BW_EVENTS_TO_CACHE)
1296 0 : ++n_measurements;
1297 :
1298 0 : if (EVENT_IS_INTERESTING(EVENT_BANDWIDTH_USED)) {
1299 0 : send_control_event(EVENT_BANDWIDTH_USED,
1300 : "650 BW %lu %lu\r\n",
1301 : (unsigned long)n_read,
1302 : (unsigned long)n_written);
1303 : }
1304 :
1305 0 : return 0;
1306 : }
1307 :
1308 : char *
1309 0 : get_bw_samples(void)
1310 : {
1311 0 : int i;
1312 0 : int idx = (next_measurement_idx + N_BW_EVENTS_TO_CACHE - n_measurements)
1313 : % N_BW_EVENTS_TO_CACHE;
1314 0 : tor_assert(0 <= idx && idx < N_BW_EVENTS_TO_CACHE);
1315 :
1316 0 : smartlist_t *elements = smartlist_new();
1317 :
1318 0 : for (i = 0; i < n_measurements; ++i) {
1319 0 : tor_assert(0 <= idx && idx < N_BW_EVENTS_TO_CACHE);
1320 0 : const struct cached_bw_event_t *bwe = &cached_bw_events[idx];
1321 :
1322 0 : smartlist_add_asprintf(elements, "%u,%u",
1323 0 : (unsigned)bwe->n_read,
1324 0 : (unsigned)bwe->n_written);
1325 :
1326 0 : idx = (idx + 1) % N_BW_EVENTS_TO_CACHE;
1327 : }
1328 :
1329 0 : char *result = smartlist_join_strings(elements, " ", 0, NULL);
1330 :
1331 0 : SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
1332 0 : smartlist_free(elements);
1333 :
1334 0 : return result;
1335 : }
1336 :
1337 : /** Called when we are sending a log message to the controllers: suspend
1338 : * sending further log messages to the controllers until we're done. Used by
1339 : * CONN_LOG_PROTECT. */
1340 : void
1341 0 : disable_control_logging(void)
1342 : {
1343 0 : ++disable_log_messages;
1344 0 : }
1345 :
1346 : /** We're done sending a log message to the controllers: re-enable controller
1347 : * logging. Used by CONN_LOG_PROTECT. */
1348 : void
1349 0 : enable_control_logging(void)
1350 : {
1351 0 : if (--disable_log_messages < 0)
1352 0 : tor_assert(0);
1353 0 : }
1354 :
1355 : /** Remove newline and carriage-return characters from @a msg, replacing them
1356 : * with spaces, and discarding any that appear at the end of the message */
1357 : void
1358 8 : control_logmsg_strip_newlines(char *msg)
1359 : {
1360 8 : char *cp;
1361 86 : for (cp = msg; *cp; ++cp) {
1362 78 : if (*cp == '\r' || *cp == '\n') {
1363 7 : *cp = ' ';
1364 : }
1365 : }
1366 8 : if (cp == msg)
1367 : return;
1368 : /* Remove trailing spaces */
1369 24 : for (--cp; *cp == ' '; --cp) {
1370 19 : *cp = '\0';
1371 19 : if (cp == msg)
1372 : break;
1373 : }
1374 : }
1375 :
1376 : /** We got a log message: tell any interested control connections. */
1377 : void
1378 8 : control_event_logmsg(int severity, log_domain_mask_t domain, const char *msg)
1379 : {
1380 8 : int event;
1381 :
1382 : /* Don't even think of trying to add stuff to a buffer from a cpuworker
1383 : * thread. (See #25987 for plan to fix.) */
1384 8 : if (! in_main_thread())
1385 : return;
1386 :
1387 8 : if (disable_log_messages)
1388 : return;
1389 :
1390 8 : if (domain == LD_BUG && EVENT_IS_INTERESTING(EVENT_STATUS_GENERAL) &&
1391 : severity <= LOG_NOTICE) {
1392 0 : char *esc = esc_for_log(msg);
1393 0 : ++disable_log_messages;
1394 0 : control_event_general_status(severity, "BUG REASON=%s", esc);
1395 0 : --disable_log_messages;
1396 0 : tor_free(esc);
1397 : }
1398 :
1399 8 : event = log_severity_to_event(severity);
1400 8 : if (event >= 0 && EVENT_IS_INTERESTING(event)) {
1401 0 : char *b = NULL;
1402 0 : const char *s;
1403 0 : if (strchr(msg, '\n')) {
1404 0 : b = tor_strdup(msg);
1405 0 : control_logmsg_strip_newlines(b);
1406 : }
1407 0 : switch (severity) {
1408 : case LOG_DEBUG: s = "DEBUG"; break;
1409 0 : case LOG_INFO: s = "INFO"; break;
1410 0 : case LOG_NOTICE: s = "NOTICE"; break;
1411 0 : case LOG_WARN: s = "WARN"; break;
1412 0 : case LOG_ERR: s = "ERR"; break;
1413 0 : default: s = "UnknownLogSeverity"; break;
1414 : }
1415 0 : ++disable_log_messages;
1416 0 : send_control_event(event, "650 %s %s\r\n", s, b?b:msg);
1417 0 : if (severity == LOG_ERR) {
1418 : /* Force a flush, since we may be about to die horribly */
1419 0 : queued_events_flush_all(1);
1420 : }
1421 0 : --disable_log_messages;
1422 0 : tor_free(b);
1423 : }
1424 : }
1425 :
1426 : /**
1427 : * Logging callback: called when there is a queued pending log callback.
1428 : */
1429 : void
1430 0 : control_event_logmsg_pending(void)
1431 : {
1432 0 : if (! in_main_thread()) {
1433 : /* We can't handle this case yet, since we're using a
1434 : * mainloop_event_t to invoke queued_events_flush_all. We ought to
1435 : * use a different mechanism instead: see #25987.
1436 : **/
1437 : return;
1438 : }
1439 0 : tor_assert(flush_queued_events_event);
1440 0 : mainloop_event_activate(flush_queued_events_event);
1441 : }
1442 :
1443 : /** Called whenever we receive new router descriptors: tell any
1444 : * interested control connections. <b>routers</b> is a list of
1445 : * routerinfo_t's.
1446 : */
1447 : int
1448 25 : control_event_descriptors_changed(smartlist_t *routers)
1449 : {
1450 25 : char *msg;
1451 :
1452 25 : if (!EVENT_IS_INTERESTING(EVENT_NEW_DESC))
1453 : return 0;
1454 :
1455 : {
1456 0 : smartlist_t *names = smartlist_new();
1457 0 : char *ids;
1458 0 : SMARTLIST_FOREACH(routers, routerinfo_t *, ri, {
1459 : char *b = tor_malloc(MAX_VERBOSE_NICKNAME_LEN+1);
1460 : router_get_verbose_nickname(b, ri);
1461 : smartlist_add(names, b);
1462 : });
1463 0 : ids = smartlist_join_strings(names, " ", 0, NULL);
1464 0 : tor_asprintf(&msg, "650 NEWDESC %s\r\n", ids);
1465 0 : send_control_event_string(EVENT_NEW_DESC, msg);
1466 0 : tor_free(ids);
1467 0 : tor_free(msg);
1468 0 : SMARTLIST_FOREACH(names, char *, cp, tor_free(cp));
1469 0 : smartlist_free(names);
1470 : }
1471 0 : return 0;
1472 : }
1473 :
1474 : /** Called when an address mapping on <b>from</b> from changes to <b>to</b>.
1475 : * <b>expires</b> values less than 3 are special; see connection_edge.c. If
1476 : * <b>error</b> is non-NULL, it is an error code describing the failure
1477 : * mode of the mapping.
1478 : */
1479 : int
1480 41 : control_event_address_mapped(const char *from, const char *to,
1481 : time_t expires, const char *error,
1482 : const int cached, uint64_t stream_id)
1483 : {
1484 41 : char *stream_id_str = NULL;
1485 41 : if (!EVENT_IS_INTERESTING(EVENT_ADDRMAP))
1486 : return 0;
1487 :
1488 0 : if (stream_id) {
1489 0 : tor_asprintf(&stream_id_str, " STREAMID=%"PRIu64"", stream_id);
1490 : }
1491 :
1492 0 : if (expires < 3 || expires == TIME_MAX)
1493 0 : send_control_event(EVENT_ADDRMAP,
1494 : "650 ADDRMAP %s %s NEVER %s%s"
1495 : "CACHED=\"%s\"%s\r\n",
1496 : from, to, error ? error : "", error ? " " : "",
1497 : cached ? "YES" : "NO",
1498 : stream_id ? stream_id_str : "");
1499 : else {
1500 0 : char buf[ISO_TIME_LEN+1];
1501 0 : char buf2[ISO_TIME_LEN+1];
1502 0 : format_local_iso_time(buf,expires);
1503 0 : format_iso_time(buf2,expires);
1504 0 : send_control_event(EVENT_ADDRMAP,
1505 : "650 ADDRMAP %s %s \"%s\" %s%sEXPIRES=\"%s\" "
1506 : "CACHED=\"%s\"%s\r\n",
1507 : from, to, buf, error ? error : "",
1508 : error ? " " : "", buf2, cached ? "YES" : "NO",
1509 : stream_id ? stream_id_str: "");
1510 : }
1511 :
1512 0 : tor_free(stream_id_str);
1513 :
1514 0 : return 0;
1515 : }
1516 : /** The network liveness has changed; this is called from circuitstats.c
1517 : * whenever we receive a cell, or when timeout expires and we assume the
1518 : * network is down. */
1519 : int
1520 221 : control_event_network_liveness_update(int liveness)
1521 : {
1522 221 : if (liveness > 0) {
1523 121 : if (get_cached_network_liveness() <= 0) {
1524 : /* Update cached liveness */
1525 58 : set_cached_network_liveness(1);
1526 58 : log_debug(LD_CONTROL, "Sending NETWORK_LIVENESS UP");
1527 58 : send_control_event_string(EVENT_NETWORK_LIVENESS,
1528 : "650 NETWORK_LIVENESS UP\r\n");
1529 : }
1530 : /* else was already live, no-op */
1531 : } else {
1532 100 : if (get_cached_network_liveness() > 0) {
1533 : /* Update cached liveness */
1534 49 : set_cached_network_liveness(0);
1535 49 : log_debug(LD_CONTROL, "Sending NETWORK_LIVENESS DOWN");
1536 49 : send_control_event_string(EVENT_NETWORK_LIVENESS,
1537 : "650 NETWORK_LIVENESS DOWN\r\n");
1538 : }
1539 : /* else was already dead, no-op */
1540 : }
1541 :
1542 221 : return 0;
1543 : }
1544 :
1545 : /** Helper function for NS-style events. Constructs and sends an event
1546 : * of type <b>event</b> with string <b>event_string</b> out of the set of
1547 : * networkstatuses <b>statuses</b>. Currently it is used for NS events
1548 : * and NEWCONSENSUS events. */
1549 : static int
1550 0 : control_event_networkstatus_changed_helper(smartlist_t *statuses,
1551 : uint16_t event,
1552 : const char *event_string)
1553 : {
1554 0 : smartlist_t *strs;
1555 0 : char *s, *esc = NULL;
1556 0 : if (!EVENT_IS_INTERESTING(event) || !smartlist_len(statuses))
1557 : return 0;
1558 :
1559 0 : strs = smartlist_new();
1560 0 : smartlist_add_strdup(strs, "650+");
1561 0 : smartlist_add_strdup(strs, event_string);
1562 0 : smartlist_add_strdup(strs, "\r\n");
1563 0 : SMARTLIST_FOREACH(statuses, const routerstatus_t *, rs,
1564 : {
1565 : s = networkstatus_getinfo_helper_single(rs);
1566 : if (!s) continue;
1567 : smartlist_add(strs, s);
1568 : });
1569 :
1570 0 : s = smartlist_join_strings(strs, "", 0, NULL);
1571 0 : write_escaped_data(s, strlen(s), &esc);
1572 0 : SMARTLIST_FOREACH(strs, char *, cp, tor_free(cp));
1573 0 : smartlist_free(strs);
1574 0 : tor_free(s);
1575 0 : send_control_event_string(event, esc);
1576 0 : send_control_event_string(event,
1577 : "650 OK\r\n");
1578 :
1579 0 : tor_free(esc);
1580 0 : return 0;
1581 : }
1582 :
1583 : /** Called when the routerstatus_ts <b>statuses</b> have changed: sends
1584 : * an NS event to any controller that cares. */
1585 : int
1586 0 : control_event_networkstatus_changed(smartlist_t *statuses)
1587 : {
1588 0 : return control_event_networkstatus_changed_helper(statuses, EVENT_NS, "NS");
1589 : }
1590 :
1591 : /** Called when we get a new consensus networkstatus. Sends a NEWCONSENSUS
1592 : * event consisting of an NS-style line for each relay in the consensus. */
1593 : int
1594 5 : control_event_newconsensus(const networkstatus_t *consensus)
1595 : {
1596 5 : if (!control_event_is_interesting(EVENT_NEWCONSENSUS))
1597 : return 0;
1598 0 : return control_event_networkstatus_changed_helper(
1599 0 : consensus->routerstatus_list, EVENT_NEWCONSENSUS, "NEWCONSENSUS");
1600 : }
1601 :
1602 : /** Called when we compute a new circuitbuildtimeout */
1603 : int
1604 113 : control_event_buildtimeout_set(buildtimeout_set_event_t type,
1605 : const char *args)
1606 : {
1607 113 : const char *type_string = NULL;
1608 :
1609 113 : if (!control_event_is_interesting(EVENT_BUILDTIMEOUT_SET))
1610 : return 0;
1611 :
1612 0 : switch (type) {
1613 : case BUILDTIMEOUT_SET_EVENT_COMPUTED:
1614 : type_string = "COMPUTED";
1615 : break;
1616 0 : case BUILDTIMEOUT_SET_EVENT_RESET:
1617 0 : type_string = "RESET";
1618 0 : break;
1619 0 : case BUILDTIMEOUT_SET_EVENT_SUSPENDED:
1620 0 : type_string = "SUSPENDED";
1621 0 : break;
1622 0 : case BUILDTIMEOUT_SET_EVENT_DISCARD:
1623 0 : type_string = "DISCARD";
1624 0 : break;
1625 0 : case BUILDTIMEOUT_SET_EVENT_RESUME:
1626 0 : type_string = "RESUME";
1627 0 : break;
1628 0 : default:
1629 0 : type_string = "UNKNOWN";
1630 0 : break;
1631 : }
1632 :
1633 0 : send_control_event(EVENT_BUILDTIMEOUT_SET,
1634 : "650 BUILDTIMEOUT_SET %s %s\r\n",
1635 : type_string, args);
1636 :
1637 0 : return 0;
1638 : }
1639 :
1640 : /** Called when a signal has been processed from signal_callback */
1641 : int
1642 4 : control_event_signal(uintptr_t signal_num)
1643 : {
1644 4 : const char *signal_string = NULL;
1645 :
1646 4 : if (!control_event_is_interesting(EVENT_GOT_SIGNAL))
1647 : return 0;
1648 :
1649 31 : for (unsigned i = 0; signal_table[i].signal_name != NULL; ++i) {
1650 30 : if ((int)signal_num == signal_table[i].sig) {
1651 : signal_string = signal_table[i].signal_name;
1652 : break;
1653 : }
1654 : }
1655 :
1656 3 : if (signal_string == NULL) {
1657 1 : log_warn(LD_BUG, "Unrecognized signal %lu in control_event_signal",
1658 : (unsigned long)signal_num);
1659 1 : return -1;
1660 : }
1661 :
1662 2 : send_control_event(EVENT_GOT_SIGNAL, "650 SIGNAL %s\r\n",
1663 : signal_string);
1664 2 : return 0;
1665 : }
1666 :
1667 : /** Called when a single local_routerstatus_t has changed: Sends an NS event
1668 : * to any controller that cares. */
1669 : int
1670 0 : control_event_networkstatus_changed_single(const routerstatus_t *rs)
1671 : {
1672 0 : smartlist_t *statuses;
1673 0 : int r;
1674 :
1675 0 : if (!EVENT_IS_INTERESTING(EVENT_NS))
1676 : return 0;
1677 :
1678 0 : statuses = smartlist_new();
1679 0 : smartlist_add(statuses, (void*)rs);
1680 0 : r = control_event_networkstatus_changed(statuses);
1681 0 : smartlist_free(statuses);
1682 0 : return r;
1683 : }
1684 :
1685 : /** Our own router descriptor has changed; tell any controllers that care.
1686 : */
1687 : int
1688 0 : control_event_my_descriptor_changed(void)
1689 : {
1690 0 : send_control_event(EVENT_DESCCHANGED, "650 DESCCHANGED\r\n");
1691 0 : return 0;
1692 : }
1693 :
1694 : /** Helper: sends a status event where <b>type</b> is one of
1695 : * EVENT_STATUS_{GENERAL,CLIENT,SERVER}, where <b>severity</b> is one of
1696 : * LOG_{NOTICE,WARN,ERR}, and where <b>format</b> is a printf-style format
1697 : * string corresponding to <b>args</b>. */
1698 : static int
1699 30 : control_event_status(int type, int severity, const char *format, va_list args)
1700 : {
1701 30 : char *user_buf = NULL;
1702 30 : char format_buf[160];
1703 30 : const char *status, *sev;
1704 :
1705 30 : switch (type) {
1706 : case EVENT_STATUS_GENERAL:
1707 : status = "STATUS_GENERAL";
1708 : break;
1709 30 : case EVENT_STATUS_CLIENT:
1710 30 : status = "STATUS_CLIENT";
1711 30 : break;
1712 0 : case EVENT_STATUS_SERVER:
1713 0 : status = "STATUS_SERVER";
1714 0 : break;
1715 0 : default:
1716 0 : log_warn(LD_BUG, "Unrecognized status type %d", type);
1717 0 : return -1;
1718 : }
1719 30 : switch (severity) {
1720 : case LOG_NOTICE:
1721 : sev = "NOTICE";
1722 : break;
1723 0 : case LOG_WARN:
1724 0 : sev = "WARN";
1725 0 : break;
1726 0 : case LOG_ERR:
1727 0 : sev = "ERR";
1728 0 : break;
1729 0 : default:
1730 0 : log_warn(LD_BUG, "Unrecognized status severity %d", severity);
1731 0 : return -1;
1732 : }
1733 30 : if (tor_snprintf(format_buf, sizeof(format_buf), "650 %s %s",
1734 : status, sev)<0) {
1735 0 : log_warn(LD_BUG, "Format string too long.");
1736 0 : return -1;
1737 : }
1738 30 : if (tor_vasprintf(&user_buf, format, args)<0) {
1739 0 : log_warn(LD_BUG, "Failed to create user buffer.");
1740 0 : return -1;
1741 : }
1742 :
1743 30 : send_control_event(type, "%s %s\r\n", format_buf, user_buf);
1744 30 : tor_free(user_buf);
1745 30 : return 0;
1746 : }
1747 :
1748 : #ifndef COCCI
1749 : #define CONTROL_EVENT_STATUS_BODY(event, sev) \
1750 : int r; \
1751 : do { \
1752 : va_list ap; \
1753 : if (!EVENT_IS_INTERESTING(event)) \
1754 : return 0; \
1755 : \
1756 : va_start(ap, format); \
1757 : r = control_event_status((event), (sev), format, ap); \
1758 : va_end(ap); \
1759 : } while (0)
1760 : #endif /* !defined(COCCI) */
1761 :
1762 : /** Format and send an EVENT_STATUS_GENERAL event whose main text is obtained
1763 : * by formatting the arguments using the printf-style <b>format</b>. */
1764 : int
1765 3 : control_event_general_status(int severity, const char *format, ...)
1766 : {
1767 3 : CONTROL_EVENT_STATUS_BODY(EVENT_STATUS_GENERAL, severity);
1768 0 : return r;
1769 : }
1770 :
1771 : /** Format and send an EVENT_STATUS_GENERAL LOG_ERR event, and flush it to the
1772 : * controller(s) immediately. */
1773 : int
1774 0 : control_event_general_error(const char *format, ...)
1775 : {
1776 0 : CONTROL_EVENT_STATUS_BODY(EVENT_STATUS_GENERAL, LOG_ERR);
1777 : /* Force a flush, since we may be about to die horribly */
1778 0 : queued_events_flush_all(1);
1779 0 : return r;
1780 : }
1781 :
1782 : /** Format and send an EVENT_STATUS_CLIENT event whose main text is obtained
1783 : * by formatting the arguments using the printf-style <b>format</b>. */
1784 : int
1785 50 : control_event_client_status(int severity, const char *format, ...)
1786 : {
1787 50 : CONTROL_EVENT_STATUS_BODY(EVENT_STATUS_CLIENT, severity);
1788 30 : return r;
1789 : }
1790 :
1791 : /** Format and send an EVENT_STATUS_CLIENT LOG_ERR event, and flush it to the
1792 : * controller(s) immediately. */
1793 : int
1794 0 : control_event_client_error(const char *format, ...)
1795 : {
1796 0 : CONTROL_EVENT_STATUS_BODY(EVENT_STATUS_CLIENT, LOG_ERR);
1797 : /* Force a flush, since we may be about to die horribly */
1798 0 : queued_events_flush_all(1);
1799 0 : return r;
1800 : }
1801 :
1802 : /** Format and send an EVENT_STATUS_SERVER event whose main text is obtained
1803 : * by formatting the arguments using the printf-style <b>format</b>. */
1804 : int
1805 51 : control_event_server_status(int severity, const char *format, ...)
1806 : {
1807 51 : CONTROL_EVENT_STATUS_BODY(EVENT_STATUS_SERVER, severity);
1808 0 : return r;
1809 : }
1810 :
1811 : /** Format and send an EVENT_STATUS_SERVER LOG_ERR event, and flush it to the
1812 : * controller(s) immediately. */
1813 : int
1814 0 : control_event_server_error(const char *format, ...)
1815 : {
1816 0 : CONTROL_EVENT_STATUS_BODY(EVENT_STATUS_SERVER, LOG_ERR);
1817 : /* Force a flush, since we may be about to die horribly */
1818 0 : queued_events_flush_all(1);
1819 0 : return r;
1820 : }
1821 :
1822 : /** Called when the status of an entry guard with the given <b>nickname</b>
1823 : * and identity <b>digest</b> has changed to <b>status</b>: tells any
1824 : * controllers that care. */
1825 : int
1826 2105 : control_event_guard(const char *nickname, const char *digest,
1827 : const char *status)
1828 : {
1829 2105 : char hbuf[HEX_DIGEST_LEN+1];
1830 2105 : base16_encode(hbuf, sizeof(hbuf), digest, DIGEST_LEN);
1831 2105 : if (!EVENT_IS_INTERESTING(EVENT_GUARD))
1832 : return 0;
1833 :
1834 : {
1835 0 : char buf[MAX_VERBOSE_NICKNAME_LEN+1];
1836 0 : const node_t *node = node_get_by_id(digest);
1837 0 : if (node) {
1838 0 : node_get_verbose_nickname(node, buf);
1839 : } else {
1840 0 : tor_snprintf(buf, sizeof(buf), "$%s~%s", hbuf, nickname);
1841 : }
1842 0 : send_control_event(EVENT_GUARD,
1843 : "650 GUARD ENTRY %s %s\r\n", buf, status);
1844 : }
1845 0 : return 0;
1846 : }
1847 :
1848 : /** Called when a configuration option changes. This is generally triggered
1849 : * by SETCONF requests and RELOAD/SIGHUP signals. The <b>changes</b> are
1850 : * a linked list of configuration key-values.
1851 : * <b>changes</b> can be NULL, meaning "no changes".
1852 : */
1853 : void
1854 5 : control_event_conf_changed(const config_line_t *changes)
1855 : {
1856 5 : char *result;
1857 5 : smartlist_t *lines;
1858 5 : if (!EVENT_IS_INTERESTING(EVENT_CONF_CHANGED) || !changes) {
1859 5 : return;
1860 : }
1861 0 : lines = smartlist_new();
1862 0 : for (const config_line_t *line = changes; line; line = line->next) {
1863 0 : if (line->value == NULL) {
1864 0 : smartlist_add_asprintf(lines, "650-%s", line->key);
1865 : } else {
1866 0 : smartlist_add_asprintf(lines, "650-%s=%s", line->key, line->value);
1867 : }
1868 : }
1869 0 : result = smartlist_join_strings(lines, "\r\n", 0, NULL);
1870 0 : send_control_event(EVENT_CONF_CHANGED,
1871 : "650-CONF_CHANGED\r\n%s\r\n650 OK\r\n", result);
1872 0 : tor_free(result);
1873 0 : SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
1874 0 : smartlist_free(lines);
1875 : }
1876 :
1877 : /** We just generated a new summary of which countries we've seen clients
1878 : * from recently. Send a copy to the controller in case it wants to
1879 : * display it for the user. */
1880 : void
1881 0 : control_event_clients_seen(const char *controller_str)
1882 : {
1883 0 : send_control_event(EVENT_CLIENTS_SEEN,
1884 : "650 CLIENTS_SEEN %s\r\n", controller_str);
1885 0 : }
1886 :
1887 : /** A new pluggable transport called <b>transport_name</b> was
1888 : * launched on <b>addr</b>:<b>port</b>. <b>mode</b> is either
1889 : * "server" or "client" depending on the mode of the pluggable
1890 : * transport.
1891 : * "650" SP "TRANSPORT_LAUNCHED" SP Mode SP Name SP Address SP Port
1892 : */
1893 : void
1894 5 : control_event_transport_launched(const char *mode, const char *transport_name,
1895 : tor_addr_t *addr, uint16_t port)
1896 : {
1897 5 : send_control_event(EVENT_TRANSPORT_LAUNCHED,
1898 : "650 TRANSPORT_LAUNCHED %s %s %s %u\r\n",
1899 : mode, transport_name, fmt_addr(addr), port);
1900 5 : }
1901 :
1902 : /** A pluggable transport called <b>pt_name</b> has emitted a log message
1903 : * found in <b>message</b> at <b>severity</b> log level. */
1904 : void
1905 5 : control_event_pt_log(const char *log)
1906 : {
1907 5 : send_control_event(EVENT_PT_LOG,
1908 : "650 PT_LOG %s\r\n",
1909 : log);
1910 5 : }
1911 :
1912 : /** A pluggable transport has emitted a STATUS message found in
1913 : * <b>status</b>. */
1914 : void
1915 3 : control_event_pt_status(const char *status)
1916 : {
1917 3 : send_control_event(EVENT_PT_STATUS,
1918 : "650 PT_STATUS %s\r\n",
1919 : status);
1920 3 : }
1921 :
1922 : /** Convert rendezvous auth type to string for HS_DESC control events
1923 : */
1924 : const char *
1925 9 : rend_auth_type_to_string(rend_auth_type_t auth_type)
1926 : {
1927 9 : const char *str;
1928 :
1929 9 : switch (auth_type) {
1930 : case REND_NO_AUTH:
1931 : str = "NO_AUTH";
1932 : break;
1933 0 : case REND_V3_AUTH:
1934 0 : str = "REND_V3_AUTH";
1935 0 : break;
1936 0 : default:
1937 0 : str = "UNKNOWN";
1938 : }
1939 :
1940 9 : return str;
1941 : }
1942 :
1943 : /** Return either the onion address if the given pointer is a non empty
1944 : * string else the unknown string. */
1945 : static const char *
1946 16 : rend_hsaddress_str_or_unknown(const char *onion_address)
1947 : {
1948 16 : static const char *str_unknown = "UNKNOWN";
1949 16 : const char *str_ret = str_unknown;
1950 :
1951 : /* No valid pointer, unknown it is. */
1952 16 : if (!onion_address) {
1953 0 : goto end;
1954 : }
1955 : /* Empty onion address thus we don't know, unknown it is. */
1956 16 : if (onion_address[0] == '\0') {
1957 0 : goto end;
1958 : }
1959 : /* All checks are good so return the given onion address. */
1960 : str_ret = onion_address;
1961 :
1962 16 : end:
1963 16 : return str_ret;
1964 : }
1965 :
1966 : /** send HS_DESC requested event.
1967 : *
1968 : * <b>rend_query</b> is used to fetch requested onion address and auth type.
1969 : * <b>hs_dir</b> is the description of contacting hs directory.
1970 : * <b>desc_id_base32</b> is the ID of requested hs descriptor.
1971 : * <b>hsdir_index</b> is the HSDir fetch index value for v3, an hex string.
1972 : */
1973 : void
1974 1 : control_event_hs_descriptor_requested(const char *onion_address,
1975 : rend_auth_type_t auth_type,
1976 : const char *id_digest,
1977 : const char *desc_id,
1978 : const char *hsdir_index)
1979 : {
1980 1 : char *hsdir_index_field = NULL;
1981 :
1982 1 : if (BUG(!id_digest || !desc_id)) {
1983 0 : return;
1984 : }
1985 :
1986 1 : if (hsdir_index) {
1987 1 : tor_asprintf(&hsdir_index_field, " HSDIR_INDEX=%s", hsdir_index);
1988 : }
1989 :
1990 1 : send_control_event(EVENT_HS_DESC,
1991 : "650 HS_DESC REQUESTED %s %s %s %s%s\r\n",
1992 : rend_hsaddress_str_or_unknown(onion_address),
1993 : rend_auth_type_to_string(auth_type),
1994 : node_describe_longname_by_id(id_digest),
1995 : desc_id,
1996 1 : hsdir_index_field ? hsdir_index_field : "");
1997 1 : tor_free(hsdir_index_field);
1998 : }
1999 :
2000 : /** send HS_DESC CREATED event when a local service generates a descriptor.
2001 : *
2002 : * <b>onion_address</b> is service address.
2003 : * <b>desc_id</b> is the descriptor ID.
2004 : * <b>replica</b> is the the descriptor replica number. If it is negative, it
2005 : * is ignored.
2006 : */
2007 : void
2008 45 : control_event_hs_descriptor_created(const char *onion_address,
2009 : const char *desc_id,
2010 : int replica)
2011 : {
2012 45 : char *replica_field = NULL;
2013 :
2014 45 : if (BUG(!onion_address || !desc_id)) {
2015 0 : return;
2016 : }
2017 :
2018 45 : if (replica >= 0) {
2019 0 : tor_asprintf(&replica_field, " REPLICA=%d", replica);
2020 : }
2021 :
2022 45 : send_control_event(EVENT_HS_DESC,
2023 : "650 HS_DESC CREATED %s UNKNOWN UNKNOWN %s%s\r\n",
2024 : onion_address, desc_id,
2025 45 : replica_field ? replica_field : "");
2026 45 : tor_free(replica_field);
2027 : }
2028 :
2029 : /** send HS_DESC upload event.
2030 : *
2031 : * <b>onion_address</b> is service address.
2032 : * <b>hs_dir</b> is the description of contacting hs directory.
2033 : * <b>desc_id</b> is the ID of requested hs descriptor.
2034 : */
2035 : void
2036 67 : control_event_hs_descriptor_upload(const char *onion_address,
2037 : const char *id_digest,
2038 : const char *desc_id,
2039 : const char *hsdir_index)
2040 : {
2041 67 : char *hsdir_index_field = NULL;
2042 :
2043 67 : if (BUG(!onion_address || !id_digest || !desc_id)) {
2044 0 : return;
2045 : }
2046 :
2047 67 : if (hsdir_index) {
2048 67 : tor_asprintf(&hsdir_index_field, " HSDIR_INDEX=%s", hsdir_index);
2049 : }
2050 :
2051 67 : send_control_event(EVENT_HS_DESC,
2052 : "650 HS_DESC UPLOAD %s UNKNOWN %s %s%s\r\n",
2053 : onion_address,
2054 : node_describe_longname_by_id(id_digest),
2055 : desc_id,
2056 67 : hsdir_index_field ? hsdir_index_field : "");
2057 67 : tor_free(hsdir_index_field);
2058 : }
2059 :
2060 : /** send HS_DESC event after got response from hs directory.
2061 : *
2062 : * NOTE: this is an internal function used by following functions:
2063 : * control_event_hsv3_descriptor_failed
2064 : *
2065 : * So do not call this function directly.
2066 : */
2067 : static void
2068 8 : event_hs_descriptor_receive_end(const char *action,
2069 : const char *onion_address,
2070 : const char *desc_id,
2071 : rend_auth_type_t auth_type,
2072 : const char *hsdir_id_digest,
2073 : const char *reason)
2074 : {
2075 8 : char *reason_field = NULL;
2076 :
2077 8 : if (BUG(!action || !onion_address)) {
2078 0 : return;
2079 : }
2080 :
2081 8 : if (reason) {
2082 1 : tor_asprintf(&reason_field, " REASON=%s", reason);
2083 : }
2084 :
2085 16 : send_control_event(EVENT_HS_DESC,
2086 : "650 HS_DESC %s %s %s %s%s%s\r\n",
2087 : action,
2088 : rend_hsaddress_str_or_unknown(onion_address),
2089 : rend_auth_type_to_string(auth_type),
2090 : hsdir_id_digest ?
2091 8 : node_describe_longname_by_id(hsdir_id_digest) :
2092 : "UNKNOWN",
2093 : desc_id ? desc_id : "",
2094 8 : reason_field ? reason_field : "");
2095 :
2096 8 : tor_free(reason_field);
2097 : }
2098 :
2099 : /** send HS_DESC event after got response from hs directory.
2100 : *
2101 : * NOTE: this is an internal function used by following functions:
2102 : * control_event_hs_descriptor_uploaded
2103 : * control_event_hs_descriptor_upload_failed
2104 : *
2105 : * So do not call this function directly.
2106 : */
2107 : void
2108 1 : control_event_hs_descriptor_upload_end(const char *action,
2109 : const char *onion_address,
2110 : const char *id_digest,
2111 : const char *reason)
2112 : {
2113 1 : char *reason_field = NULL;
2114 :
2115 1 : if (BUG(!action || !id_digest)) {
2116 0 : return;
2117 : }
2118 :
2119 1 : if (reason) {
2120 0 : tor_asprintf(&reason_field, " REASON=%s", reason);
2121 : }
2122 :
2123 1 : send_control_event(EVENT_HS_DESC,
2124 : "650 HS_DESC %s %s UNKNOWN %s%s\r\n",
2125 : action,
2126 : rend_hsaddress_str_or_unknown(onion_address),
2127 : node_describe_longname_by_id(id_digest),
2128 1 : reason_field ? reason_field : "");
2129 :
2130 1 : tor_free(reason_field);
2131 : }
2132 :
2133 : /* Send HS_DESC RECEIVED event
2134 : *
2135 : * Called when we successfully received a hidden service descriptor. */
2136 : void
2137 7 : control_event_hsv3_descriptor_received(const char *onion_address,
2138 : const char *desc_id,
2139 : const char *hsdir_id_digest)
2140 : {
2141 7 : char *desc_id_field = NULL;
2142 :
2143 7 : if (BUG(!onion_address || !desc_id || !hsdir_id_digest)) {
2144 0 : return;
2145 : }
2146 :
2147 : /* Because DescriptorID is an optional positional value, we need to add a
2148 : * whitespace before in order to not be next to the HsDir value. */
2149 7 : tor_asprintf(&desc_id_field, " %s", desc_id);
2150 :
2151 7 : event_hs_descriptor_receive_end("RECEIVED", onion_address, desc_id_field,
2152 : REND_NO_AUTH, hsdir_id_digest, NULL);
2153 7 : tor_free(desc_id_field);
2154 : }
2155 :
2156 : /** send HS_DESC UPLOADED event
2157 : *
2158 : * called when we successfully uploaded a hidden service descriptor.
2159 : */
2160 : void
2161 1 : control_event_hs_descriptor_uploaded(const char *id_digest,
2162 : const char *onion_address)
2163 : {
2164 1 : if (BUG(!id_digest)) {
2165 0 : return;
2166 : }
2167 :
2168 1 : control_event_hs_descriptor_upload_end("UPLOADED", onion_address,
2169 : id_digest, NULL);
2170 : }
2171 :
2172 : /** Send HS_DESC event to inform controller that the query to
2173 : * <b>onion_address</b> failed to retrieve hidden service descriptor
2174 : * <b>desc_id</b> from directory identified by <b>hsdir_id_digest</b>. If
2175 : * NULL, "UNKNOWN" is used. If <b>reason</b> is not NULL, add it to REASON=
2176 : * field. */
2177 : void
2178 1 : control_event_hsv3_descriptor_failed(const char *onion_address,
2179 : const char *desc_id,
2180 : const char *hsdir_id_digest,
2181 : const char *reason)
2182 : {
2183 1 : char *desc_id_field = NULL;
2184 :
2185 1 : if (BUG(!onion_address || !desc_id || !reason)) {
2186 0 : return;
2187 : }
2188 :
2189 : /* Because DescriptorID is an optional positional value, we need to add a
2190 : * whitespace before in order to not be next to the HsDir value. */
2191 1 : tor_asprintf(&desc_id_field, " %s", desc_id);
2192 :
2193 1 : event_hs_descriptor_receive_end("FAILED", onion_address, desc_id_field,
2194 : REND_NO_AUTH, hsdir_id_digest, reason);
2195 1 : tor_free(desc_id_field);
2196 : }
2197 :
2198 : /** Send HS_DESC_CONTENT event after completion of a successful fetch
2199 : * from hs directory. If <b>hsdir_id_digest</b> is NULL, it is replaced
2200 : * by "UNKNOWN". If <b>content</b> is NULL, it is replaced by an empty
2201 : * string. The <b>onion_address</b> or <b>desc_id</b> set to NULL will
2202 : * not trigger the control event. */
2203 : void
2204 6 : control_event_hs_descriptor_content(const char *onion_address,
2205 : const char *desc_id,
2206 : const char *hsdir_id_digest,
2207 : const char *content)
2208 : {
2209 6 : static const char *event_name = "HS_DESC_CONTENT";
2210 6 : char *esc_content = NULL;
2211 :
2212 6 : if (!onion_address || !desc_id) {
2213 0 : log_warn(LD_BUG, "Called with onion_address==%p, desc_id==%p, ",
2214 : onion_address, desc_id);
2215 0 : return;
2216 : }
2217 :
2218 6 : if (content == NULL) {
2219 : /* Point it to empty content so it can still be escaped. */
2220 0 : content = "";
2221 : }
2222 6 : write_escaped_data(content, strlen(content), &esc_content);
2223 :
2224 12 : send_control_event(EVENT_HS_DESC_CONTENT,
2225 : "650+%s %s %s %s\r\n%s650 OK\r\n",
2226 : event_name,
2227 : rend_hsaddress_str_or_unknown(onion_address),
2228 : desc_id,
2229 : hsdir_id_digest ?
2230 6 : node_describe_longname_by_id(hsdir_id_digest) :
2231 : "UNKNOWN",
2232 : esc_content);
2233 6 : tor_free(esc_content);
2234 : }
2235 :
2236 : /** Send HS_DESC event to inform controller upload of hidden service
2237 : * descriptor identified by <b>id_digest</b> failed. If <b>reason</b>
2238 : * is not NULL, add it to REASON= field.
2239 : */
2240 : void
2241 0 : control_event_hs_descriptor_upload_failed(const char *id_digest,
2242 : const char *onion_address,
2243 : const char *reason)
2244 : {
2245 0 : if (BUG(!id_digest)) {
2246 0 : return;
2247 : }
2248 0 : control_event_hs_descriptor_upload_end("FAILED", onion_address,
2249 : id_digest, reason);
2250 : }
2251 :
2252 : void
2253 235 : control_events_free_all(void)
2254 : {
2255 235 : smartlist_t *queued_events = NULL;
2256 :
2257 235 : stats_prev_n_read = stats_prev_n_written = 0;
2258 :
2259 235 : if (queued_control_events_lock) {
2260 4 : tor_mutex_acquire(queued_control_events_lock);
2261 4 : flush_queued_event_pending = 0;
2262 4 : queued_events = queued_control_events;
2263 4 : queued_control_events = NULL;
2264 4 : tor_mutex_release(queued_control_events_lock);
2265 : }
2266 4 : if (queued_events) {
2267 4 : SMARTLIST_FOREACH(queued_events, queued_event_t *, ev,
2268 : queued_event_free(ev));
2269 4 : smartlist_free(queued_events);
2270 : }
2271 235 : if (flush_queued_events_event) {
2272 4 : mainloop_event_free(flush_queued_events_event);
2273 4 : flush_queued_events_event = NULL;
2274 : }
2275 235 : global_event_mask = 0;
2276 235 : disable_log_messages = 0;
2277 235 : }
2278 :
2279 : #ifdef TOR_UNIT_TESTS
2280 : /* For testing: change the value of global_event_mask */
2281 : void
2282 83 : control_testing_set_global_event_mask(uint64_t mask)
2283 : {
2284 83 : global_event_mask = mask;
2285 83 : }
2286 : #endif /* defined(TOR_UNIT_TESTS) */
|