tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

btrack_circuit.c (4540B)


      1 /* Copyright (c) 2007-2021, The Tor Project, Inc. */
      2 /* See LICENSE for licensing information */
      3 
      4 /**
      5 * \file btrack_circuit.c
      6 * \brief Bootstrap tracker for origin circuits
      7 *
      8 * Track state changes of origin circuits, as published by the circuit
      9 * subsystem.
     10 **/
     11 
     12 #include "core/or/or.h"
     13 
     14 #include "core/or/ocirc_event.h"
     15 
     16 #include "feature/control/btrack_circuit.h"
     17 #include "feature/control/control.h"
     18 #include "lib/log/log.h"
     19 
     20 /** Pair of a best origin circuit GID with its state or status */
     21 typedef struct btc_best_t {
     22  uint32_t gid;
     23  int val;
     24 } btc_best_t;
     25 
     26 /** GID and state of the best origin circuit we've seen so far */
     27 static btc_best_t best_any_state = { 0, -1 };
     28 /** GID and state of the best application circuit we've seen so far */
     29 static btc_best_t best_ap_state = { 0, -1 };
     30 /** GID and status of the best origin circuit we've seen so far */
     31 static btc_best_t best_any_evtype = { 0, -1 };
     32 /** GID and status of the best application circuit we've seen so far */
     33 static btc_best_t best_ap_evtype = { 0, -1 };
     34 
     35 /** Reset cached "best" values */
     36 static void
     37 btc_reset_bests(void)
     38 {
     39  best_any_state.gid = best_ap_state.gid = 0;
     40  best_any_state.val = best_ap_state.val = -1;
     41  best_any_evtype.gid = best_ap_state.gid = 0;
     42  best_any_evtype.val = best_ap_evtype.val = -1;
     43 }
     44 
     45 /** True if @a state is a "better" origin circuit state than @a best->val */
     46 static bool
     47 btc_state_better(int state, const btc_best_t *best)
     48 {
     49  return state > best->val;
     50 }
     51 
     52 /**
     53 * Definine an ordering on circuit status events
     54 *
     55 * The CIRC_EVENT_ constants aren't sorted in a useful order, so this
     56 * array helps to decode them.  This approach depends on the statuses
     57 * being nonnegative and dense.
     58 **/
     59 static int circ_event_order[] = {
     60  [CIRC_EVENT_FAILED] = -1,
     61  [CIRC_EVENT_CLOSED] = -1,
     62  [CIRC_EVENT_LAUNCHED] = 1,
     63  [CIRC_EVENT_EXTENDED] = 2,
     64  [CIRC_EVENT_BUILT] = 3,
     65 };
     66 #define N_CIRC_EVENT_ORDER \
     67  (sizeof(circ_event_order) / sizeof(circ_event_order[0]))
     68 
     69 /** True if @a state is a "better" origin circuit event status than @a
     70    best->val */
     71 static bool
     72 btc_evtype_better(int state, const btc_best_t *best)
     73 {
     74  if (state < 0)
     75    return false;
     76  if (best->val < 0)
     77    return true;
     78 
     79  tor_assert(state >= 0 && (unsigned)state < N_CIRC_EVENT_ORDER);
     80  tor_assert(best->val >= 0 && (unsigned)best->val < N_CIRC_EVENT_ORDER);
     81  return circ_event_order[state] > circ_event_order[best->val];
     82 }
     83 
     84 static bool
     85 btc_update_state(const ocirc_state_msg_t *msg, btc_best_t *best,
     86                 const char *type)
     87 {
     88  if (btc_state_better(msg->state, best)) {
     89    log_info(LD_BTRACK, "CIRC BEST_%s state %d->%d gid=%"PRIu32, type,
     90             best->val, msg->state, msg->gid);
     91    best->gid = msg->gid;
     92    best->val = msg->state;
     93    return true;
     94  }
     95  return false;
     96 }
     97 
     98 static bool
     99 btc_update_evtype(const ocirc_cevent_msg_t *msg, btc_best_t *best,
    100                  const char *type)
    101 {
    102  if (btc_evtype_better(msg->evtype, best)) {
    103    log_info(LD_BTRACK, "CIRC BEST_%s evtype %d->%d gid=%"PRIu32, type,
    104             best->val, msg->evtype, msg->gid);
    105    best->gid = msg->gid;
    106    best->val = msg->evtype;
    107    return true;
    108  }
    109  return false;
    110 }
    111 
    112 DECLARE_SUBSCRIBE(ocirc_state, btc_state_rcvr);
    113 DECLARE_SUBSCRIBE(ocirc_cevent, btc_cevent_rcvr);
    114 DECLARE_SUBSCRIBE(ocirc_chan, btc_chan_rcvr);
    115 
    116 static void
    117 btc_state_rcvr(const msg_t *msg, const ocirc_state_msg_t *arg)
    118 {
    119  (void)msg;
    120  log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" state=%d onehop=%d",
    121            arg->gid, arg->state, arg->onehop);
    122 
    123  btc_update_state(arg, &best_any_state, "ANY");
    124  if (arg->onehop)
    125    return;
    126  btc_update_state(arg, &best_ap_state, "AP");
    127 }
    128 
    129 static void
    130 btc_cevent_rcvr(const msg_t *msg, const ocirc_cevent_msg_t *arg)
    131 {
    132  (void)msg;
    133  log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" evtype=%d reason=%d onehop=%d",
    134            arg->gid, arg->evtype, arg->reason, arg->onehop);
    135 
    136  btc_update_evtype(arg, &best_any_evtype, "ANY");
    137  if (arg->onehop)
    138    return;
    139  btc_update_evtype(arg, &best_ap_evtype, "AP");
    140 }
    141 
    142 static void
    143 btc_chan_rcvr(const msg_t *msg, const ocirc_chan_msg_t *arg)
    144 {
    145  (void)msg;
    146  log_debug(LD_BTRACK, "CIRC gid=%"PRIu32" chan=%"PRIu64" onehop=%d",
    147            arg->gid, arg->chan, arg->onehop);
    148 }
    149 
    150 int
    151 btrack_circ_add_pubsub(pubsub_connector_t *connector)
    152 {
    153  if (DISPATCH_ADD_SUB(connector, ocirc, ocirc_chan))
    154    return -1;
    155  if (DISPATCH_ADD_SUB(connector, ocirc, ocirc_cevent))
    156    return -1;
    157  if (DISPATCH_ADD_SUB(connector, ocirc, ocirc_state))
    158    return -1;
    159  return 0;
    160 }
    161 
    162 void
    163 btrack_circ_fini(void)
    164 {
    165  btc_reset_bests();
    166 }