circuituse.c 119 KB
Newer Older
Roger Dingledine's avatar
Roger Dingledine committed
1
2
/* Copyright (c) 2001 Matej Pfajfar.
 * Copyright (c) 2001-2004, Roger Dingledine.
3
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
Nick Mathewson's avatar
Nick Mathewson committed
4
 * Copyright (c) 2007-2019, The Tor Project, Inc. */
5
6
7
8
/* See LICENSE for licensing information */

/**
 * \file circuituse.c
9
10
11
12
13
14
15
16
 * \brief Launch the right sort of circuits and attach the right streams to
 * them.
 *
 * As distinct from circuitlist.c, which manages lookups to find circuits, and
 * circuitbuild.c, which handles the logistics of circuit construction, this
 * module keeps track of which streams can be attached to which circuits (in
 * circuit_get_best()), and attaches streams to circuits (with
 * circuit_try_attaching_streams(), connection_ap_handshake_attach_circuit(),
17
 * and connection_ap_handshake_attach_chosen_circuit() ).
18
19
20
21
22
23
24
25
26
27
 *
 * This module also makes sure that we are building circuits for all of the
 * predicted ports, using circuit_remove_handled_ports(),
 * circuit_stream_is_being_handled(), and circuit_build_needed_cirs().  It
 * handles launching circuits for specific targets using
 * circuit_launch_by_extend_info().
 *
 * This is also where we handle expiring circuits that have been around for
 * too long without actually completing, along with the circuit_build_timeout
 * logic in circuitstats.c.
28
29
 **/

30
#include "core/or/or.h"
31
32
#include "app/config/config.h"
#include "core/mainloop/connection.h"
33
34
35
36
37
#include "core/or/channel.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuitstats.h"
#include "core/or/circuituse.h"
38
#include "core/or/circuitpadding.h"
39
#include "core/or/connection_edge.h"
40
41
42
43
44
#include "core/or/policies.h"
#include "feature/client/addressmap.h"
#include "feature/client/bridges.h"
#include "feature/client/circpathbias.h"
#include "feature/client/entrynodes.h"
45
#include "feature/control/control_events.h"
46
#include "feature/dircommon/directory.h"
47
#include "feature/hs/hs_circuit.h"
48
49
#include "feature/hs/hs_client.h"
#include "feature/hs/hs_common.h"
50
51
#include "feature/hs/hs_ident.h"
#include "feature/hs/hs_stats.h"
52
#include "feature/nodelist/describe.h"
53
#include "feature/nodelist/networkstatus.h"
54
55
56
57
#include "feature/nodelist/nodelist.h"
#include "feature/nodelist/routerlist.h"
#include "feature/relay/routermode.h"
#include "feature/relay/selftest.h"
58
59
60
#include "feature/rend/rendclient.h"
#include "feature/rend/rendcommon.h"
#include "feature/rend/rendservice.h"
61
#include "feature/stats/predict_ports.h"
62
#include "lib/math/fp.h"
63
#include "lib/time/tvdiff.h"
64

65
66
67
68
69
70
71
#include "core/or/cpath_build_state_st.h"
#include "feature/dircommon/dir_connection_st.h"
#include "core/or/entry_connection_st.h"
#include "core/or/extend_info_st.h"
#include "core/or/or_circuit_st.h"
#include "core/or/origin_circuit_st.h"
#include "core/or/socks_request_st.h"
72

Mike Perry's avatar
Mike Perry committed
73
STATIC void circuit_expire_old_circuits_clientside(void);
74
75
static void circuit_increment_failure_count(void);

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/** Check whether the hidden service destination of the stream at
 *  <b>edge_conn</b> is the same as the destination of the circuit at
 *  <b>origin_circ</b>. */
static int
circuit_matches_with_rend_stream(const edge_connection_t *edge_conn,
                                 const origin_circuit_t *origin_circ)
{
  /* Check if this is a v2 rendezvous circ/stream */
  if ((edge_conn->rend_data && !origin_circ->rend_data) ||
      (!edge_conn->rend_data && origin_circ->rend_data) ||
      (edge_conn->rend_data && origin_circ->rend_data &&
       rend_cmp_service_ids(rend_data_get_address(edge_conn->rend_data),
                            rend_data_get_address(origin_circ->rend_data)))) {
    /* this circ is not for this conn */
    return 0;
  }

  /* Check if this is a v3 rendezvous circ/stream */
  if ((edge_conn->hs_ident && !origin_circ->hs_ident) ||
      (!edge_conn->hs_ident && origin_circ->hs_ident) ||
      (edge_conn->hs_ident && origin_circ->hs_ident &&
       !ed25519_pubkey_eq(&edge_conn->hs_ident->identity_pk,
                          &origin_circ->hs_ident->identity_pk))) {
    /* this circ is not for this conn */
    return 0;
  }

  return 1;
}

106
/** Return 1 if <b>circ</b> could be returned by circuit_get_best().
107
108
 * Else return 0.
 */
109
static int
Nick Mathewson's avatar
Nick Mathewson committed
110
circuit_is_acceptable(const origin_circuit_t *origin_circ,
111
                      const entry_connection_t *conn,
112
113
                      int must_be_open, uint8_t purpose,
                      int need_uptime, int need_internal,
114
                      time_t now)
115
{
Nick Mathewson's avatar
Nick Mathewson committed
116
  const circuit_t *circ = TO_CIRCUIT(origin_circ);
117
  const node_t *exitnode;
118
  cpath_build_state_t *build_state;
119
120
121
  tor_assert(circ);
  tor_assert(conn);
  tor_assert(conn->socks_request);
122

123
  if (must_be_open && (circ->state != CIRCUIT_STATE_OPEN || !circ->n_chan))
124
125
126
127
128
    return 0; /* ignore non-open circs */
  if (circ->marked_for_close)
    return 0;

  /* if this circ isn't our purpose, skip. */
129
130
  if (purpose == CIRCUIT_PURPOSE_C_REND_JOINED && !must_be_open) {
    if (circ->purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND &&
131
132
133
        circ->purpose != CIRCUIT_PURPOSE_C_REND_READY &&
        circ->purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED &&
        circ->purpose != CIRCUIT_PURPOSE_C_REND_JOINED)
134
      return 0;
135
136
  } else if (purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT &&
             !must_be_open) {
137
138
139
140
    if (circ->purpose != CIRCUIT_PURPOSE_C_INTRODUCING &&
        circ->purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT)
      return 0;
  } else {
141
    if (purpose != circ->purpose)
142
143
144
      return 0;
  }

145
146
147
148
149
  /* If this is a timed-out hidden service circuit, skip it. */
  if (origin_circ->hs_circ_has_timed_out) {
    return 0;
  }

150
  if (purpose == CIRCUIT_PURPOSE_C_GENERAL ||
151
152
      purpose == CIRCUIT_PURPOSE_C_HSDIR_GET ||
      purpose == CIRCUIT_PURPOSE_S_HSDIR_POST ||
153
      purpose == CIRCUIT_PURPOSE_HS_VANGUARDS ||
154
      purpose == CIRCUIT_PURPOSE_C_REND_JOINED) {
155
    if (circ->timestamp_dirty &&
156
       circ->timestamp_dirty+get_options()->MaxCircuitDirtiness <= now)
157
      return 0;
158
159
160
161
  }

  if (origin_circ->unusable_for_new_conns)
    return 0;
162

163
  /* decide if this circ is suitable for this conn */
164

165
  /* for rend circs, circ->cpath->prev is not the last router in the
166
   * circuit, it's the magical extra service hop. so just check the nickname
167
168
   * of the one we meant to finish at.
   */
Nick Mathewson's avatar
Nick Mathewson committed
169
  build_state = origin_circ->build_state;
170
  exitnode = build_state_get_exit_node(build_state);
171

172
  if (need_uptime && !build_state->need_uptime)
173
    return 0;
174
  if (need_internal != build_state->is_internal)
175
    return 0;
176

177
178
179
  if (purpose == CIRCUIT_PURPOSE_C_GENERAL ||
      purpose == CIRCUIT_PURPOSE_S_HSDIR_POST ||
      purpose == CIRCUIT_PURPOSE_C_HSDIR_GET) {
180
    tor_addr_t addr;
181
    if (!exitnode && !build_state->onehop_tunnel) {
182
      log_debug(LD_CIRC,"Not considering circuit with unknown router.");
183
184
185
      return 0; /* this circuit is screwed and doesn't know it yet,
                 * or is a rendezvous circuit. */
    }
186
    if (build_state->onehop_tunnel) {
187
      if (!conn->want_onehop) {
188
189
190
        log_debug(LD_CIRC,"Skipping one-hop circuit.");
        return 0;
      }
191
192
193
      tor_assert(conn->chosen_exit_name);
      if (build_state->chosen_exit) {
        char digest[DIGEST_LEN];
194
195
        if (hexdigest_to_digest(conn->chosen_exit_name, digest) < 0)
          return 0; /* broken digest, we don't want it */
196
        if (tor_memneq(digest, build_state->chosen_exit->identity_digest,
197
                          DIGEST_LEN))
198
          return 0; /* this is a circuit to somewhere else */
199
200
        if (tor_digest_is_zero(digest)) {
          /* we don't know the digest; have to compare addr:port */
201
202
          const int family = tor_addr_parse(&addr,
                                            conn->socks_request->address);
203
          if (family < 0 ||
204
              !tor_addr_eq(&build_state->chosen_exit->addr, &addr) ||
205
206
207
              build_state->chosen_exit->port != conn->socks_request->port)
            return 0;
        }
208
      }
209
    } else {
210
      if (conn->want_onehop) {
211
212
213
214
        /* don't use three-hop circuits -- that could hurt our anonymity. */
        return 0;
      }
    }
215
216
217
218
219
220
221
222
    if (origin_circ->prepend_policy) {
      if (tor_addr_parse(&addr, conn->socks_request->address) != -1) {
        int r = compare_tor_addr_to_addr_policy(&addr,
                                                conn->socks_request->port,
                                                origin_circ->prepend_policy);
        if (r == ADDR_POLICY_REJECTED)
          return 0;
      }
223
    }
224
    if (exitnode && !connection_ap_can_use_exit(conn, exitnode)) {
225
226
227
      /* can't exit from this router */
      return 0;
    }
228
  } else { /* not general: this might be a rend circuit */
229
    const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn);
230
    if (!circuit_matches_with_rend_stream(edge_conn, origin_circ)) {
231
      return 0;
232
233
    }
  }
Nick Mathewson's avatar
Nick Mathewson committed
234
235
236
237
238
239
240

  if (!connection_edge_compatible_with_circuit(conn, origin_circ)) {
    /* conn needs to be isolated from other conns that have already used
     * origin_circ */
    return 0;
  }

241
242
243
  return 1;
}

244
/** Return 1 if circuit <b>a</b> is better than circuit <b>b</b> for
Nick Mathewson's avatar
Nick Mathewson committed
245
 * <b>conn</b>, and return 0 otherwise. Used by circuit_get_best.
246
 */
247
static int
Nick Mathewson's avatar
Nick Mathewson committed
248
circuit_is_better(const origin_circuit_t *oa, const origin_circuit_t *ob,
249
                  const entry_connection_t *conn)
250
{
Nick Mathewson's avatar
Nick Mathewson committed
251
252
  const circuit_t *a = TO_CIRCUIT(oa);
  const circuit_t *b = TO_CIRCUIT(ob);
253
  const uint8_t purpose = ENTRY_TO_CONN(conn)->purpose;
Nick Mathewson's avatar
Nick Mathewson committed
254
  int a_bits, b_bits;
Nick Mathewson's avatar
Nick Mathewson committed
255

256
257
258
259
260
261
262
  /* If one of the circuits was allowed to live due to relaxing its timeout,
   * it is definitely worse (it's probably a much slower path). */
  if (oa->relaxed_timeout && !ob->relaxed_timeout)
    return 0; /* ob is better. It's not relaxed. */
  if (!oa->relaxed_timeout && ob->relaxed_timeout)
    return 1; /* oa is better. It's not relaxed. */

263
  switch (purpose) {
264
265
    case CIRCUIT_PURPOSE_S_HSDIR_POST:
    case CIRCUIT_PURPOSE_C_HSDIR_GET:
266
267
268
269
    case CIRCUIT_PURPOSE_C_GENERAL:
      /* if it's used but less dirty it's best;
       * else if it's more recently created it's best
       */
270
271
      if (b->timestamp_dirty) {
        if (a->timestamp_dirty &&
272
            a->timestamp_dirty > b->timestamp_dirty)
273
274
          return 1;
      } else {
275
        if (a->timestamp_dirty ||
276
            timercmp(&a->timestamp_began, &b->timestamp_began, OP_GT))
277
          return 1;
Nick Mathewson's avatar
Nick Mathewson committed
278
        if (ob->build_state->is_internal)
279
          /* XXXX++ what the heck is this internal thing doing here. I
Roger Dingledine's avatar
Roger Dingledine committed
280
281
282
           * think we can get rid of it. circuit_is_acceptable() already
           * makes sure that is_internal is exactly what we need it to
           * be. -RD */
283
          return 1;
284
285
286
287
      }
      break;
    case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
      /* the closer it is to ack_wait the better it is */
288
      if (a->purpose > b->purpose)
289
290
291
292
        return 1;
      break;
    case CIRCUIT_PURPOSE_C_REND_JOINED:
      /* the closer it is to rend_joined the better it is */
293
      if (a->purpose > b->purpose)
294
295
296
        return 1;
      break;
  }
Nick Mathewson's avatar
Nick Mathewson committed
297

298
  /* XXXX Maybe this check should get a higher priority to avoid
Nick Mathewson's avatar
Nick Mathewson committed
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
   *   using up circuits too rapidly. */

  a_bits = connection_edge_update_circuit_isolation(conn,
                                                    (origin_circuit_t*)oa, 1);
  b_bits = connection_edge_update_circuit_isolation(conn,
                                                    (origin_circuit_t*)ob, 1);
  /* if x_bits < 0, then we have not used x for anything; better not to dirty
   * a connection if we can help it. */
  if (a_bits < 0) {
    return 0;
  } else if (b_bits < 0) {
    return 1;
  }
  a_bits &= ~ oa->isolation_flags_mixed;
  a_bits &= ~ ob->isolation_flags_mixed;
  if (n_bits_set_u8(a_bits) < n_bits_set_u8(b_bits)) {
    /* The fewer new restrictions we need to make on a circuit for stream
     * isolation, the better. */
    return 1;
  }

320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
  return 0;
}

/** Find the best circ that conn can use, preferably one which is
 * dirty. Circ must not be too old.
 *
 * Conn must be defined.
 *
 * If must_be_open, ignore circs not in CIRCUIT_STATE_OPEN.
 *
 * circ_purpose specifies what sort of circuit we must have.
 * It can be C_GENERAL, C_INTRODUCE_ACK_WAIT, or C_REND_JOINED.
 *
 * If it's REND_JOINED and must_be_open==0, then return the closest
 * rendezvous-purposed circuit that you can find.
 *
 * If it's INTRODUCE_ACK_WAIT and must_be_open==0, then return the
 * closest introduce-purposed circuit that you can find.
 */
339
static origin_circuit_t *
340
circuit_get_best(const entry_connection_t *conn,
Nick Mathewson's avatar
Nick Mathewson committed
341
                 int must_be_open, uint8_t purpose,
342
                 int need_uptime, int need_internal)
343
{
Nick Mathewson's avatar
Nick Mathewson committed
344
  origin_circuit_t *best=NULL;
345
  struct timeval now;
346
  int intro_going_on_but_too_old = 0;
347
348
349
350

  tor_assert(conn);

  tor_assert(purpose == CIRCUIT_PURPOSE_C_GENERAL ||
351
             purpose == CIRCUIT_PURPOSE_HS_VANGUARDS ||
352
353
             purpose == CIRCUIT_PURPOSE_C_HSDIR_GET ||
             purpose == CIRCUIT_PURPOSE_S_HSDIR_POST ||
354
355
356
             purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT ||
             purpose == CIRCUIT_PURPOSE_C_REND_JOINED);

357
358
  tor_gettimeofday(&now);

359
  SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
Nick Mathewson's avatar
Nick Mathewson committed
360
361
362
363
    origin_circuit_t *origin_circ;
    if (!CIRCUIT_IS_ORIGIN(circ))
      continue;
    origin_circ = TO_ORIGIN_CIRCUIT(circ);
364

Mike Perry's avatar
Mike Perry committed
365
366
    /* Log an info message if we're going to launch a new intro circ in
     * parallel */
367
    if (purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT &&
368
369
        !must_be_open && origin_circ->hs_circ_has_timed_out &&
        !circ->marked_for_close) {
Mike Perry's avatar
Mike Perry committed
370
371
        intro_going_on_but_too_old = 1;
        continue;
372
373
    }

Mike Perry's avatar
Mike Perry committed
374
    if (!circuit_is_acceptable(origin_circ,conn,must_be_open,purpose,
375
                               need_uptime,need_internal, (time_t)now.tv_sec))
Mike Perry's avatar
Mike Perry committed
376
377
      continue;

378
379
380
    /* now this is an acceptable circ to hand back. but that doesn't
     * mean it's the *best* circ to hand back. try to decide.
     */
Nick Mathewson's avatar
Nick Mathewson committed
381
    if (!best || circuit_is_better(origin_circ,best,conn))
Nick Mathewson's avatar
Nick Mathewson committed
382
      best = origin_circ;
383
  }
384
  SMARTLIST_FOREACH_END(circ);
385

386
387
388
389
390
  if (!best && intro_going_on_but_too_old)
    log_info(LD_REND|LD_CIRC, "There is an intro circuit being created "
             "right now, but it has already taken quite a while. Starting "
             "one in parallel.");

Nick Mathewson's avatar
Nick Mathewson committed
391
  return best;
392
393
}

394
395
396
397
398
399
/** Return the number of not-yet-open general-purpose origin circuits. */
static int
count_pending_general_client_circuits(void)
{
  int count = 0;

400
  SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
401
402
    if (circ->marked_for_close ||
        circ->state == CIRCUIT_STATE_OPEN ||
403
        !CIRCUIT_PURPOSE_COUNTS_TOWARDS_MAXPENDING(circ->purpose) ||
404
405
406
407
408
        !CIRCUIT_IS_ORIGIN(circ))
      continue;

    ++count;
  }
409
  SMARTLIST_FOREACH_END(circ);
410
411
412
413

  return count;
}

414
#if 0
415
/** Check whether, according to the policies in <b>options</b>, the
416
 * circuit <b>circ</b> makes sense. */
417
418
419
/* XXXX currently only checks Exclude{Exit}Nodes; it should check more.
 * Also, it doesn't have the right definition of an exit circuit. Also,
 * it's never called. */
420
421
422
423
424
425
int
circuit_conforms_to_options(const origin_circuit_t *circ,
                            const or_options_t *options)
{
  const crypt_path_t *cpath, *cpath_next = NULL;

426
427
  /* first check if it includes any excluded nodes */
  for (cpath = circ->cpath; cpath_next != circ->cpath; cpath = cpath_next) {
428
429
430
431
    cpath_next = cpath->next;
    if (routerset_contains_extendinfo(options->ExcludeNodes,
                                      cpath->extend_info))
      return 0;
432
  }
433

434
435
436
437
  /* then consider the final hop */
  if (routerset_contains_extendinfo(options->ExcludeExitNodes,
                                    circ->cpath->prev->extend_info))
    return 0;
438
439
440

  return 1;
}
441
#endif /* 0 */
442

443
444
/**
 * Close all circuits that start at us, aren't open, and were born
445
 * at least CircuitBuildTimeout seconds ago.
446
447
448
449
450
451
452
453
 *
 * TODO: This function is now partially redundant to
 * circuit_build_times_handle_completed_hop(), but that function only
 * covers circuits up to and including 3 hops that are still actually
 * completing hops. However, circuit_expire_building() also handles longer
 * circuits, as well as circuits that are completely stalled.
 * In the future (after prop247/other path selection revamping), we probably
 * want to eliminate this rats nest in favor of a simpler approach.
454
 */
455
void
456
circuit_expire_building(void)
457
{
458
459
460
  /* circ_times.timeout_ms and circ_times.close_ms are from
   * circuit_build_times_get_initial_timeout() if we haven't computed
   * custom timeouts yet */
461
  struct timeval general_cutoff, begindir_cutoff, fourhop_cutoff,
Mike Perry's avatar
Mike Perry committed
462
463
    close_cutoff, extremely_old_cutoff, hs_extremely_old_cutoff,
    cannibalized_cutoff, c_intro_cutoff, s_intro_cutoff, stream_cutoff;
464
  const or_options_t *options = get_options();
465
  struct timeval now;
466
  cpath_build_state_t *build_state;
467
  int any_opened_circs = 0;
468

469
  tor_gettimeofday(&now);
470
471
472
473
474

  /* Check to see if we have any opened circuits. If we don't,
   * we want to be more lenient with timeouts, in case the
   * user has relocated and/or changed network connections.
   * See bug #3443. */
475
  any_opened_circs = circuit_any_opened_circuits();
476

477
478
479
480
#define SET_CUTOFF(target, msec) do {                       \
    long ms = tor_lround(msec);                             \
    struct timeval diff;                                    \
    diff.tv_sec = ms / 1000;                                \
481
    diff.tv_usec = (int)((ms % 1000) * 1000);               \
482
483
484
    timersub(&now, &diff, &target);                         \
  } while (0)

Mike Perry's avatar
Mike Perry committed
485
  /**
Mike Perry's avatar
Mike Perry committed
486
487
488
489
490
491
492
493
494
   * Because circuit build timeout is calculated only based on 3 hop
   * general purpose circuit construction, we need to scale the timeout
   * to make it properly apply to longer circuits, and circuits of
   * certain usage types. The following diagram illustrates how we
   * derive the scaling below. In short, we calculate the number
   * of times our telescoping-based circuit construction causes cells
   * to traverse each link for the circuit purpose types in question,
   * and then assume each link is equivalent.
   *
Mike Perry's avatar
Mike Perry committed
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
   * OP --a--> A --b--> B --c--> C
   * OP --a--> A --b--> B --c--> C --d--> D
   *
   * Let h = a = b = c = d
   *
   * Three hops (general_cutoff)
   *   RTTs = 3a + 2b + c
   *   RTTs = 6h
   * Cannibalized:
   *   RTTs = a+b+c+d
   *   RTTs = 4h
   * Four hops:
   *   RTTs = 4a + 3b + 2c + d
   *   RTTs = 10h
   * Client INTRODUCE1+ACK: // XXX: correct?
   *   RTTs = 5a + 4b + 3c + 2d
   *   RTTs = 14h
   * Server intro:
   *   RTTs = 4a + 3b + 2c
   *   RTTs = 9h
   */
516
517
  SET_CUTOFF(general_cutoff, get_circuit_build_timeout_ms());
  SET_CUTOFF(begindir_cutoff, get_circuit_build_timeout_ms());
Mike Perry's avatar
Mike Perry committed
518

519
520
521
522
  // TODO: We should probably use route_len_for_purpose() here instead,
  // except that does not count the extra round trip for things like server
  // intros and rends.

Mike Perry's avatar
Mike Perry committed
523
524
  /* > 3hop circs seem to have a 1.0 second delay on their cannibalized
   * 4th hop. */
525
  SET_CUTOFF(fourhop_cutoff, get_circuit_build_timeout_ms() * (10/6.0) + 1000);
Mike Perry's avatar
Mike Perry committed
526
527
528
529
530
531

  /* CIRCUIT_PURPOSE_C_ESTABLISH_REND behaves more like a RELAY cell.
   * Use the stream cutoff (more or less). */
  SET_CUTOFF(stream_cutoff, MAX(options->CircuitStreamTimeout,15)*1000 + 1000);

  /* Be lenient with cannibalized circs. They already survived the official
Roger Dingledine's avatar
Roger Dingledine committed
532
   * CBT, and they're usually not performance-critical. */
Mike Perry's avatar
Mike Perry committed
533
  SET_CUTOFF(cannibalized_cutoff,
534
             MAX(get_circuit_build_close_time_ms()*(4/6.0),
Mike Perry's avatar
Mike Perry committed
535
536
                 options->CircuitStreamTimeout * 1000) + 1000);

Roger Dingledine's avatar
Roger Dingledine committed
537
  /* Intro circs have an extra round trip (and are also 4 hops long) */
538
  SET_CUTOFF(c_intro_cutoff, get_circuit_build_timeout_ms() * (14/6.0) + 1000);
Mike Perry's avatar
Mike Perry committed
539

Roger Dingledine's avatar
Roger Dingledine committed
540
  /* Server intro circs have an extra round trip */
541
  SET_CUTOFF(s_intro_cutoff, get_circuit_build_timeout_ms() * (9/6.0) + 1000);
Mike Perry's avatar
Mike Perry committed
542

543
544
  SET_CUTOFF(close_cutoff, get_circuit_build_close_time_ms());
  SET_CUTOFF(extremely_old_cutoff, get_circuit_build_close_time_ms()*2 + 1000);
545

546
  SET_CUTOFF(hs_extremely_old_cutoff,
547
             MAX(get_circuit_build_close_time_ms()*2 + 1000,
548
549
                 options->SocksTimeout * 1000));

550
  SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *,victim) {
551
    struct timeval cutoff;
552
553
    bool fixed_time = circuit_build_times_disabled(get_options());

554
    if (!CIRCUIT_IS_ORIGIN(victim) || /* didn't originate here */
555
556
557
558
559
560
561
562
563
564
565
566
        victim->marked_for_close)     /* don't mess with marked circs */
      continue;

    /* If we haven't yet started the first hop, it means we don't have
     * any orconns available, and thus have not started counting time yet
     * for this circuit. See circuit_deliver_create_cell() and uses of
     * timestamp_began.
     *
     * Continue to wait in this case. The ORConn should timeout
     * independently and kill us then.
     */
    if (TO_ORIGIN_CIRCUIT(victim)->cpath->state == CPATH_STATE_CLOSED) {
567
      continue;
568
    }
569

570
    build_state = TO_ORIGIN_CIRCUIT(victim)->build_state;
571
572
    if (build_state && build_state->onehop_tunnel)
      cutoff = begindir_cutoff;
573
574
    else if (victim->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT)
      cutoff = close_cutoff;
575
    else if (victim->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT)
Mike Perry's avatar
Mike Perry committed
576
577
578
579
580
      cutoff = c_intro_cutoff;
    else if (victim->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO)
      cutoff = s_intro_cutoff;
    else if (victim->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND)
      cutoff = stream_cutoff;
581
582
    else if (victim->purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING)
      cutoff = close_cutoff;
Mike Perry's avatar
Mike Perry committed
583
584
585
586
587
    else if (TO_ORIGIN_CIRCUIT(victim)->has_opened &&
             victim->state != CIRCUIT_STATE_OPEN)
      cutoff = cannibalized_cutoff;
    else if (build_state && build_state->desired_path_len >= 4)
      cutoff = fourhop_cutoff;
588
589
    else
      cutoff = general_cutoff;
590

591
592
593
    if (TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out)
      cutoff = hs_extremely_old_cutoff;

594
    if (timercmp(&victim->timestamp_began, &cutoff, OP_GT))
595
596
      continue; /* it's still young, leave it alone */

597
598
599
600
601
602
    /* We need to double-check the opened state here because
     * we don't want to consider opened 1-hop dircon circuits for
     * deciding when to relax the timeout, but we *do* want to relax
     * those circuits too if nothing else is opened *and* they still
     * aren't either. */
    if (!any_opened_circs && victim->state != CIRCUIT_STATE_OPEN) {
603
      /* It's still young enough that we wouldn't close it, right? */
604
      if (timercmp(&victim->timestamp_began, &close_cutoff, OP_GT)) {
605
606
607
        if (!TO_ORIGIN_CIRCUIT(victim)->relaxed_timeout) {
          int first_hop_succeeded = TO_ORIGIN_CIRCUIT(victim)->cpath->state
                                      == CPATH_STATE_OPEN;
608
609
610
611
612
613
614
615
616
617
618
619
620
          if (!fixed_time) {
            log_info(LD_CIRC,
                "No circuits are opened. Relaxing timeout for circuit %d "
                "(a %s %d-hop circuit in state %s with channel state %s).",
                TO_ORIGIN_CIRCUIT(victim)->global_identifier,
                circuit_purpose_to_string(victim->purpose),
                TO_ORIGIN_CIRCUIT(victim)->build_state ?
                  TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len :
                  -1,
                circuit_state_to_string(victim->state),
                victim->n_chan ?
                   channel_state_to_string(victim->n_chan->state) : "none");
          }
621
622
623
624
625

          /* We count the timeout here for CBT, because technically this
           * was a timeout, and the timeout value needs to reset if we
           * see enough of them. Note this means we also need to avoid
           * double-counting below, too. */
626
          circuit_build_times_count_timeout(get_circuit_build_times_mutable(),
627
              first_hop_succeeded);
628
629
630
631
          TO_ORIGIN_CIRCUIT(victim)->relaxed_timeout = 1;
        }
        continue;
      } else {
632
        static ratelim_t relax_timeout_limit = RATELIM_INIT(3600);
633
        const double build_close_ms = get_circuit_build_close_time_ms();
634
635
        if (!fixed_time) {
          log_fn_ratelim(&relax_timeout_limit, LOG_NOTICE, LD_CIRC,
636
637
638
                 "No circuits are opened. Relaxed timeout for circuit %d "
                 "(a %s %d-hop circuit in state %s with channel state %s) to "
                 "%ldms. However, it appears the circuit has timed out "
639
                 "anyway.",
640
641
                 TO_ORIGIN_CIRCUIT(victim)->global_identifier,
                 circuit_purpose_to_string(victim->purpose),
642
643
644
                 TO_ORIGIN_CIRCUIT(victim)->build_state ?
                   TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len :
                   -1,
645
                 circuit_state_to_string(victim->state),
Mike Perry's avatar
Mike Perry committed
646
647
                 victim->n_chan ?
                    channel_state_to_string(victim->n_chan->state) : "none",
648
                 (long)build_close_ms);
649
        }
650
651
652
      }
    }

653
#if 0
654
    /* some debug logs, to help track bugs */
655
    if (victim->purpose >= CIRCUIT_PURPOSE_C_INTRODUCING &&
656
        victim->purpose <= CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) {
657
      if (!victim->timestamp_dirty)
Nick Mathewson's avatar
Nick Mathewson committed
658
        log_fn(LOG_DEBUG,"Considering %sopen purpose %d to %s (circid %d)."
659
               "(clean).",
660
               victim->state == CIRCUIT_STATE_OPEN ? "" : "non",
Nick Mathewson's avatar
Nick Mathewson committed
661
               victim->purpose, victim->build_state->chosen_exit_name,
662
663
               victim->n_circ_id);
      else
Nick Mathewson's avatar
Nick Mathewson committed
664
        log_fn(LOG_DEBUG,"Considering %sopen purpose %d to %s (circid %d). "
665
               "%d secs since dirty.",
666
               victim->state == CIRCUIT_STATE_OPEN ? "" : "non",
Nick Mathewson's avatar
Nick Mathewson committed
667
               victim->purpose, victim->build_state->chosen_exit_name,
668
669
670
               victim->n_circ_id,
               (int)(now - victim->timestamp_dirty));
    }
671
#endif /* 0 */
672
673
674

    /* if circ is !open, or if it's open but purpose is a non-finished
     * intro or rend, then mark it for close */
675
676
    if (victim->state == CIRCUIT_STATE_OPEN) {
      switch (victim->purpose) {
677
        default: /* most open circuits can be left alone. */
678
679
          continue; /* yes, continue inside a switch refers to the nearest
                     * enclosing loop. C is smart. */
680
        case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
681
          break; /* too old, need to die */
682
683
        case CIRCUIT_PURPOSE_C_REND_READY:
          /* it's a rend_ready circ -- has it already picked a query? */
684
685
686
          /* c_rend_ready circs measure age since timestamp_dirty,
           * because that's set when they switch purposes
           */
687
          if (TO_ORIGIN_CIRCUIT(victim)->rend_data ||
688
              TO_ORIGIN_CIRCUIT(victim)->hs_ident ||
689
              victim->timestamp_dirty > cutoff.tv_sec)
690
691
            continue;
          break;
692
693
694
695
696
        case CIRCUIT_PURPOSE_PATH_BIAS_TESTING:
          /* Open path bias testing circuits are given a long
           * time to complete the test, but not forever */
          TO_ORIGIN_CIRCUIT(victim)->path_state = PATH_STATE_USE_FAILED;
          break;
Mike Perry's avatar
Mike Perry committed
697
        case CIRCUIT_PURPOSE_C_INTRODUCING:
698
          /* That purpose means that the intro point circuit has been opened
699
           * successfully but the INTRODUCE1 cell hasn't been sent yet because
700
701
702
703
704
           * the client is waiting for the rendezvous point circuit to open.
           * Keep this circuit open while waiting for the rendezvous circuit.
           * We let the circuit idle timeout take care of cleaning this
           * circuit if it never used. */
          continue;
Mike Perry's avatar
Mike Perry committed
705
        case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
706
707
708
709
710
711
        case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
        case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
          /* rend and intro circs become dirty each time they
           * make an introduction attempt. so timestamp_dirty
           * will reflect the time since the last attempt.
           */
712
          if (victim->timestamp_dirty > cutoff.tv_sec)
713
714
715
            continue;
          break;
      }
716
717
718
    } else { /* circuit not open, consider recording failure as timeout */
      int first_hop_succeeded = TO_ORIGIN_CIRCUIT(victim)->cpath &&
            TO_ORIGIN_CIRCUIT(victim)->cpath->state == CPATH_STATE_OPEN;
719
720

      if (TO_ORIGIN_CIRCUIT(victim)->p_streams != NULL) {
721
        log_warn(LD_BUG, "Circuit %d (purpose %d, %s) has timed out, "
722
723
                 "yet has attached streams!",
                 TO_ORIGIN_CIRCUIT(victim)->global_identifier,
724
725
                 victim->purpose,
                 circuit_purpose_to_string(victim->purpose));
726
727
728
729
        tor_fragile_assert();
        continue;
      }

730
      if (circuit_timeout_want_to_count_circ(TO_ORIGIN_CIRCUIT(victim)) &&
731
          circuit_build_times_enough_to_compute(get_circuit_build_times())) {
732
733

        log_info(LD_CIRC,
734
735
                 "Deciding to count the timeout for circuit %"PRIu32"\n",
                 TO_ORIGIN_CIRCUIT(victim)->global_identifier);
736

737
738
739
        /* Circuits are allowed to last longer for measurement.
         * Switch their purpose and wait. */
        if (victim->purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) {
740
741
          circuit_build_times_mark_circ_as_measurement_only(TO_ORIGIN_CIRCUIT(
                                                            victim));
742
743
          continue;
        }
744

745
746
747
748
749
        /*
         * If the circuit build time is much greater than we would have cut
         * it off at, we probably had a suspend event along this codepath,
         * and we should discard the value.
         */
750
        if (timercmp(&victim->timestamp_began, &extremely_old_cutoff, OP_LT)) {
751
752
          log_notice(LD_CIRC,
                     "Extremely large value for circuit build timeout: %lds. "
753
                     "Assuming clock jump. Purpose %d (%s)",
754
                     (long)(now.tv_sec - victim->timestamp_began.tv_sec),
755
                     victim->purpose,
756
                     circuit_purpose_to_string(victim->purpose));
757
        } else if (circuit_build_times_count_close(
758
759
760
            get_circuit_build_times_mutable(),
            first_hop_succeeded,
            (time_t)victim->timestamp_created.tv_sec)) {
761
          circuit_build_times_set_timeout(get_circuit_build_times_mutable());
762
        }
763
      }
764
    }
765

766
767
768
769
    /* If this is a hidden service client circuit which is far enough along in
     * connecting to its destination, and we haven't already flagged it as
     * 'timed out', flag it so we'll launch another intro or rend circ, but
     * don't mark it for close yet.
770
771
772
773
     *
     * (Circs flagged as 'timed out' are given a much longer timeout
     * period above, so we won't close them in the next call to
     * circuit_expire_building.) */
774
    if (!(TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out)) {
775
776
777
778
779
780
781
782
      switch (victim->purpose) {
      case CIRCUIT_PURPOSE_C_REND_READY:
        /* We only want to spare a rend circ if it has been specified in
         * an INTRODUCE1 cell sent to a hidden service.  A circ's
         * pending_final_cpath field is non-NULL iff it is a rend circ
         * and we have tried to send an INTRODUCE1 cell specifying it.
         * Thus, if the pending_final_cpath field *is* NULL, then we
         * want to not spare it. */
783
784
        if (TO_ORIGIN_CIRCUIT(victim)->build_state &&
            TO_ORIGIN_CIRCUIT(victim)->build_state->pending_final_cpath ==
785
786
            NULL)
          break;
787
        FALLTHROUGH;
788
789
790
      case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
      case CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED:
        /* If we have reached this line, we want to spare the circ for now. */
791
        log_info(LD_CIRC,"Marking circ %u (state %d:%s, purpose %d) "
792
                 "as timed-out HS circ",
793
                 (unsigned)victim->n_circ_id,
794
795
796
797
798
799
800
801
802
                 victim->state, circuit_state_to_string(victim->state),
                 victim->purpose);
        TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out = 1;
        continue;
      default:
        break;
      }
    }

803
804
805
    /* If this is a service-side rendezvous circuit which is far
     * enough along in connecting to its destination, consider sparing
     * it. */
806
    if (!(TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out) &&
807
        victim->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND) {
808
      log_info(LD_CIRC,"Marking circ %u (state %d:%s, purpose %d) "
809
               "as timed-out HS circ; relaunching rendezvous attempt.",
810
               (unsigned)victim->n_circ_id,
811
812
813
               victim->state, circuit_state_to_string(victim->state),
               victim->purpose);
      TO_ORIGIN_CIRCUIT(victim)->hs_circ_has_timed_out = 1;
814
      hs_circ_retry_service_rendezvous_point(TO_ORIGIN_CIRCUIT(victim));
815
816
817
      continue;
    }

818
    if (victim->n_chan)
Mike Perry's avatar
Mike Perry committed
819
      log_info(LD_CIRC,
820
               "Abandoning circ %u %s:%u (state %d,%d:%s, purpose %d, "
Mike Perry's avatar
Mike Perry committed
821
               "len %d)", TO_ORIGIN_CIRCUIT(victim)->global_identifier,
822
               channel_get_canonical_remote_descr(victim->n_chan),
823
               (unsigned)victim->n_circ_id,
Mike Perry's avatar
Mike Perry committed
824
               TO_ORIGIN_CIRCUIT(victim)->has_opened,
825
               victim->state, circuit_state_to_string(victim->state),
Mike Perry's avatar
Mike Perry committed
826
               victim->purpose,
827
828
829
               TO_ORIGIN_CIRCUIT(victim)->build_state ?
                 TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len :
                 -1);
830
    else
Mike Perry's avatar
Mike Perry committed
831
      log_info(LD_CIRC,
832
               "Abandoning circ %u %u (state %d,%d:%s, purpose %d, len %d)",
Mike Perry's avatar
Mike Perry committed
833
               TO_ORIGIN_CIRCUIT(victim)->global_identifier,
834
835
               (unsigned)victim->n_circ_id,
               TO_ORIGIN_CIRCUIT(victim)->has_opened,
Mike Perry's avatar
Mike Perry committed
836
837
               victim->state,
               circuit_state_to_string(victim->state), victim->purpose,
838
839
840
               TO_ORIGIN_CIRCUIT(victim)->build_state ?
                 TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len :
                 -1);
841

842
    circuit_log_path(LOG_INFO,LD_CIRC,TO_ORIGIN_CIRCUIT(victim));
843
844
845
846
    if (victim->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT)
      circuit_mark_for_close(victim, END_CIRC_REASON_MEASUREMENT_EXPIRED);
    else
      circuit_mark_for_close(victim, END_CIRC_REASON_TIMEOUT);
847
848

    pathbias_count_timeout(TO_ORIGIN_CIRCUIT(victim));
849
  } SMARTLIST_FOREACH_END(victim);
850
851
}

852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
/**
 * Mark for close all circuits that start here, that were built through a
 * guard we weren't sure if we wanted to use, and that have been waiting
 * around for way too long.
 */
void
circuit_expire_waiting_for_better_guard(void)
{
  SMARTLIST_FOREACH_BEGIN(circuit_get_global_origin_circuit_list(),
                          origin_circuit_t *, circ) {
    if (TO_CIRCUIT(circ)->marked_for_close)
      continue;
    if (circ->guard_state == NULL)
      continue;
    if (entry_guard_state_should_expire(circ->guard_state))
      circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_NONE);
  } SMARTLIST_FOREACH_END(circ);
}

Nick Mathewson's avatar
Nick Mathewson committed
871
872
873
874
/** For debugging #8387: track when we last called
 * circuit_expire_old_circuits_clientside. */
static time_t last_expired_clientside_circuits = 0;

875
876
877
/**
 * As a diagnostic for bug 8387, log information about how many one-hop
 * circuits we have around that have been there for at least <b>age</b>
David Goulet's avatar
David Goulet committed
878
 * seconds. Log a few of them. Ignores Single Onion Service intro, it is
879
 * expected to be long-term one-hop circuits.
880
881
882
883
884
 */
void
circuit_log_ancient_one_hop_circuits(int age)
{
#define MAX_ANCIENT_ONEHOP_CIRCUITS_TO_LOG 10
885
886
  time_t now = time(NULL);
  time_t cutoff = now - age;
887
888
  int n_found = 0;
  smartlist_t *log_these = smartlist_new();
889
  const or_options_t *options = get_options();
890

891
  SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
892
893
894
895
896
    const origin_circuit_t *ocirc;
    if (! CIRCUIT_IS_ORIGIN(circ))
      continue;
    if (circ->timestamp_created.tv_sec >= cutoff)
      continue;
897
    /* Single Onion Services deliberately make long term one-hop intro
898
     * and rendezvous connections. Don't log the established ones. */
899
    if (rend_service_allow_non_anonymous_connection(options) &&
900
901
        (circ->purpose == CIRCUIT_PURPOSE_S_INTRO ||
         circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED))
902
      continue;
903
904
905
906
907
908
909
910
911
    ocirc = CONST_TO_ORIGIN_CIRCUIT(circ);

    if (ocirc->build_state && ocirc->build_state->onehop_tunnel) {
      ++n_found;

      if (smartlist_len(log_these) < MAX_ANCIENT_ONEHOP_CIRCUITS_TO_LOG)
        smartlist_add(log_these, (origin_circuit_t*) ocirc);
    }
  }
912
  SMARTLIST_FOREACH_END(circ);
913
914
915
916
917

  if (n_found == 0)
    goto done;

  log_notice(LD_HEARTBEAT,
918
919
             "Diagnostic for issue 8387: Found %d one-hop circuits more "
             "than %d seconds old! Logging %d...",
920
921
922
923
             n_found, age, smartlist_len(log_these));

  SMARTLIST_FOREACH_BEGIN(log_these, const origin_circuit_t *, ocirc) {
    char created[ISO_TIME_LEN+1];
924
925
926
    int stream_num;
    const edge_connection_t *conn;
    char *dirty = NULL;
927
    const circuit_t *circ = TO_CIRCUIT(ocirc);
928

929
    format_local_iso_time(created,
930
                          (time_t)circ->timestamp_created.tv_sec);
931

932
933
934
935
936
937
    if (circ->timestamp_dirty) {
      char dirty_since[ISO_TIME_LEN+1];
      format_local_iso_time(dirty_since, circ->timestamp_dirty);

      tor_asprintf(&dirty, "Dirty since %s (%ld seconds vs %ld-second cutoff)",
                   dirty_since, (long)(now - circ->timestamp_dirty),
938
                   (long) options->MaxCircuitDirtiness);
939
940
941
942
    } else {
      dirty = tor_strdup("Not marked dirty");
    }

943
    log_notice(LD_HEARTBEAT, "  #%d created at %s. %s, %s. %s for close. "
944
               "Package window: %d. "
945
               "%s for new conns. %s.",
946
947
948
949
950
               ocirc_sl_idx,
               created,
               circuit_state_to_string(circ->state),
               circuit_purpose_to_string(circ->purpose),
               circ->marked_for_close ? "Marked" : "Not marked",
951
               circ->package_window,
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
               ocirc->unusable_for_new_conns ? "Not usable" : "usable",
               dirty);
    tor_free(dirty);

    stream_num = 0;
    for (conn = ocirc->p_streams; conn; conn = conn->next_stream) {
      const connection_t *c = TO_CONN(conn);
      char stream_created[ISO_TIME_LEN+1];
      if (++stream_num >= 5)
        break;

      format_local_iso_time(stream_created, c->timestamp_created);

      log_notice(LD_HEARTBEAT, "     Stream#%d created at %s. "
                 "%s conn in state %s. "
967
968
                 "It is %slinked and %sreading from a linked connection %p. "
                 "Package window %d. "
969
970
971
972
973
974
                 "%s for close (%s:%d). Hold-open is %sset. "
                 "Has %ssent RELAY_END. %s on circuit.",
                 stream_num,
                 stream_created,
                 conn_type_to_string(c->type),
                 conn_state_to_string(c->type, c->state),
975
976
977
978
                 c->linked ? "" : "not ",
                 c->reading_from_linked_conn ? "": "not",
                 c->linked_conn,
                 conn->package_window,
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
                 c->marked_for_close ? "Marked" : "Not marked",
                 c->marked_for_close_file ? c->marked_for_close_file : "--",
                 c->marked_for_close,
                 c->hold_open_until_flushed ? "" : "not ",
                 conn->edge_has_sent_end ? "" : "not ",
                 conn->edge_blocked_on_circ ? "Blocked" : "Not blocked");
      if (! c->linked_conn)
        continue;

      c = c->linked_conn;

      log_notice(LD_HEARTBEAT, "        Linked to %s connection in state %s "
                 "(Purpose %d). %s for close (%s:%d). Hold-open is %sset. ",
                 conn_type_to_string(c->type),
                 conn_state_to_string(c->type, c->state),
                 c->purpose,
                 c->marked_for_close ? "Marked" : "Not marked",
                 c->marked_for_close_file ? c->marked_for_close_file : "--",
                 c->marked_for_close,
                 c->hold_open_until_flushed ? "" : "not ");
    }
1000
  } SMARTLIST_FOREACH_END(ocirc);