LCOV - code coverage report
Current view: top level - feature/hs - hs_circuitmap.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 156 167 93.4 %
Date: 2021-11-24 03:28:48 Functions: 33 36 91.7 %

          Line data    Source code
       1             : /* Copyright (c) 2016-2021, The Tor Project, Inc. */
       2             : /* See LICENSE for licensing information */
       3             : 
       4             : /**
       5             :  * \file hs_circuitmap.c
       6             :  *
       7             :  * \brief Hidden service circuitmap: A hash table that maps binary tokens to
       8             :  *  introduction and rendezvous circuits; it's used:
       9             :  *  (a) by relays acting as intro points and rendezvous points
      10             :  *  (b) by hidden services to find intro and rend circuits and
      11             :  *  (c) by HS clients to find rendezvous circuits.
      12             :  **/
      13             : 
      14             : #define HS_CIRCUITMAP_PRIVATE
      15             : 
      16             : #include "core/or/or.h"
      17             : #include "app/config/config.h"
      18             : #include "core/or/circuitlist.h"
      19             : #include "feature/hs/hs_circuitmap.h"
      20             : 
      21             : #include "core/or/or_circuit_st.h"
      22             : #include "core/or/origin_circuit_st.h"
      23             : 
      24             : /************************** HS circuitmap code *******************************/
      25             : 
      26             : /** This is the hidden service circuitmap. It's a hash table that maps
      27             :    introduction and rendezvous tokens to specific circuits such that given a
      28             :    token it's easy to find the corresponding circuit. */
      29             : static struct hs_circuitmap_ht *the_hs_circuitmap = NULL;
      30             : 
      31             : /** This is a helper function used by the hash table code (HT_). It returns 1
      32             :  * if two circuits have the same HS token. */
      33             : static int
      34          58 : hs_circuits_have_same_token(const circuit_t *first_circuit,
      35             :                             const circuit_t *second_circuit)
      36             : {
      37          58 :   const hs_token_t *first_token;
      38          58 :   const hs_token_t *second_token;
      39             : 
      40          58 :   tor_assert(first_circuit);
      41          58 :   tor_assert(second_circuit);
      42             : 
      43          58 :   first_token = first_circuit->hs_token;
      44          58 :   second_token = second_circuit->hs_token;
      45             : 
      46             :   /* Both circs must have a token */
      47          58 :   if (BUG(!first_token) || BUG(!second_token)) {
      48           0 :     return 0;
      49             :   }
      50             : 
      51          58 :   if (first_token->type != second_token->type) {
      52             :     return 0;
      53             :   }
      54             : 
      55          50 :   if (first_token->token_len != second_token->token_len)
      56             :     return 0;
      57             : 
      58          50 :   return tor_memeq(first_token->token,
      59          50 :                    second_token->token,
      60             :                    first_token->token_len);
      61             : }
      62             : 
      63             : /** This is a helper function for the hash table code (HT_). It hashes a
      64             :  * circuit HS token into an unsigned int for use as a key by the hash table
      65             :  * routines.*/
      66             : static inline unsigned int
      67         126 : hs_circuit_hash_token(const circuit_t *circuit)
      68             : {
      69         126 :   tor_assert(circuit->hs_token);
      70             : 
      71         126 :   return (unsigned) siphash24g(circuit->hs_token->token,
      72             :                                circuit->hs_token->token_len);
      73             : }
      74             : 
      75             : /** Register the circuitmap hash table */
      76        1002 : HT_PROTOTYPE(hs_circuitmap_ht, // The name of the hashtable struct
      77             :              circuit_t,    // The name of the element struct,
      78             :              hs_circuitmap_node,        // The name of HT_ENTRY member
      79             :              hs_circuit_hash_token, hs_circuits_have_same_token);
      80             : 
      81         285 : HT_GENERATE2(hs_circuitmap_ht, circuit_t, hs_circuitmap_node,
      82             :              hs_circuit_hash_token, hs_circuits_have_same_token,
      83             :              0.6, tor_reallocarray, tor_free_);
      84             : 
      85             : #ifdef TOR_UNIT_TESTS
      86             : 
      87             : /** Return the global HS circuitmap. Used by unittests. */
      88             : hs_circuitmap_ht *
      89           4 : get_hs_circuitmap(void)
      90             : {
      91           4 :   return the_hs_circuitmap;
      92             : }
      93             : 
      94             : #endif /* defined(TOR_UNIT_TESTS) */
      95             : 
      96             : /****************** HS circuitmap utility functions **************************/
      97             : 
      98             : /** Return a new HS token of type <b>type</b> containing <b>token</b>. */
      99             : static hs_token_t *
     100          86 : hs_token_new(hs_token_type_t type, size_t token_len,
     101             :              const uint8_t *token)
     102             : {
     103          86 :   tor_assert(token);
     104             : 
     105          86 :   hs_token_t *hs_token = tor_malloc_zero(sizeof(hs_token_t));
     106          86 :   hs_token->type = type;
     107          86 :   hs_token->token_len = token_len;
     108          86 :   hs_token->token = tor_memdup(token, token_len);
     109             : 
     110          86 :   return hs_token;
     111             : }
     112             : 
     113             : #define hs_token_free(val) \
     114             :   FREE_AND_NULL(hs_token_t, hs_token_free_, (val))
     115             : 
     116             : /** Free memory allocated by this <b>hs_token</b>. */
     117             : static void
     118          86 : hs_token_free_(hs_token_t *hs_token)
     119             : {
     120          86 :   if (!hs_token) {
     121             :     return;
     122             :   }
     123             : 
     124          86 :   tor_free(hs_token->token);
     125          86 :   tor_free(hs_token);
     126             : }
     127             : 
     128             : /** Return the circuit from the circuitmap with token <b>search_token</b>. */
     129             : static circuit_t *
     130          86 : get_circuit_with_token(hs_token_t *search_token)
     131             : {
     132          86 :   tor_assert(the_hs_circuitmap);
     133             : 
     134             :   /* We use a dummy circuit object for the hash table search routine. */
     135          86 :   circuit_t search_circ;
     136          86 :   search_circ.hs_token = search_token;
     137          86 :   return HT_FIND(hs_circuitmap_ht, the_hs_circuitmap, &search_circ);
     138             : }
     139             : 
     140             : /** Helper function that registers <b>circ</b> with <b>token</b> on the HS
     141             :    circuitmap. This function steals reference of <b>token</b>. */
     142             : static void
     143          20 : hs_circuitmap_register_impl(circuit_t *circ, hs_token_t *token)
     144             : {
     145          20 :   tor_assert(circ);
     146          20 :   tor_assert(token);
     147          20 :   tor_assert(the_hs_circuitmap);
     148             : 
     149             :   /* If this circuit already has a token, clear it. */
     150          20 :   if (circ->hs_token) {
     151           1 :     hs_circuitmap_remove_circuit(circ);
     152             :   }
     153             : 
     154             :   /* Kill old circuits with the same token. We want new intro/rend circuits to
     155             :      take precedence over old ones, so that HSes and clients and reestablish
     156             :      killed circuits without changing the HS token. */
     157             :   {
     158          20 :     circuit_t *found_circ;
     159          20 :     found_circ = get_circuit_with_token(token);
     160          20 :     if (found_circ) {
     161           2 :       hs_circuitmap_remove_circuit(found_circ);
     162           2 :       if (!found_circ->marked_for_close) {
     163           2 :         circuit_mark_for_close(found_circ, END_CIRC_REASON_FINISHED);
     164             :       }
     165             :     }
     166             :   }
     167             : 
     168             :   /* Register circuit and token to circuitmap. */
     169          20 :   circ->hs_token = token;
     170          20 :   HT_INSERT(hs_circuitmap_ht, the_hs_circuitmap, circ);
     171          20 : }
     172             : 
     173             : /** Helper function: Register <b>circ</b> of <b>type</b> on the HS
     174             :  *  circuitmap. Use the HS <b>token</b> as the key to the hash table.  If
     175             :  *  <b>token</b> is not set, clear the circuit of any HS tokens. */
     176             : static void
     177          20 : hs_circuitmap_register_circuit(circuit_t *circ,
     178             :                                hs_token_type_t type, size_t token_len,
     179             :                                const uint8_t *token)
     180             : {
     181          20 :   hs_token_t *hs_token = NULL;
     182             : 
     183             :   /* Create a new token and register it to the circuitmap */
     184          20 :   tor_assert(token);
     185          20 :   hs_token = hs_token_new(type, token_len, token);
     186          20 :   tor_assert(hs_token);
     187          20 :   hs_circuitmap_register_impl(circ, hs_token);
     188          20 : }
     189             : 
     190             : /** Helper function for hs_circuitmap_get_origin_circuit() and
     191             :  * hs_circuitmap_get_or_circuit(). Because only circuit_t are indexed in the
     192             :  * circuitmap, this function returns object type so the specialized functions
     193             :  * using this helper can upcast it to the right type.
     194             :  *
     195             :  * Return NULL if not such circuit is found. */
     196             : static circuit_t *
     197          66 : hs_circuitmap_get_circuit_impl(hs_token_type_t type,
     198             :                                size_t token_len,
     199             :                                const uint8_t *token,
     200             :                                uint8_t wanted_circ_purpose)
     201             : {
     202          66 :   circuit_t *found_circ = NULL;
     203             : 
     204          66 :   tor_assert(the_hs_circuitmap);
     205             : 
     206             :   /* Check the circuitmap if we have a circuit with this token */
     207             :   {
     208          66 :     hs_token_t *search_hs_token = hs_token_new(type, token_len, token);
     209          66 :     tor_assert(search_hs_token);
     210          66 :     found_circ = get_circuit_with_token(search_hs_token);
     211          66 :     hs_token_free(search_hs_token);
     212             :   }
     213             : 
     214             :   /* Check that the circuit is useful to us */
     215          66 :   if (!found_circ ||
     216          28 :       found_circ->purpose != wanted_circ_purpose ||
     217          18 :       found_circ->marked_for_close) {
     218          48 :     return NULL;
     219             :   }
     220             : 
     221             :   return found_circ;
     222             : }
     223             : 
     224             : /** Helper function: Query circuitmap for origin circuit with <b>token</b> of
     225             :  * size <b>token_len</b> and <b>type</b>.  Only returns a circuit with purpose
     226             :  * equal to the <b>wanted_circ_purpose</b> parameter and if it is NOT marked
     227             :  * for close. Return NULL if no such circuit is found. */
     228             : static origin_circuit_t *
     229          40 : hs_circuitmap_get_origin_circuit(hs_token_type_t type,
     230             :                                  size_t token_len,
     231             :                                  const uint8_t *token,
     232             :                                  uint8_t wanted_circ_purpose)
     233             : {
     234          40 :   circuit_t *circ;
     235          40 :   tor_assert(token);
     236          40 :   tor_assert(CIRCUIT_PURPOSE_IS_ORIGIN(wanted_circ_purpose));
     237             : 
     238          40 :   circ = hs_circuitmap_get_circuit_impl(type, token_len, token,
     239             :                                         wanted_circ_purpose);
     240          40 :   if (!circ) {
     241             :     return NULL;
     242             :   }
     243             : 
     244           7 :   tor_assert(CIRCUIT_IS_ORIGIN(circ));
     245           7 :   return TO_ORIGIN_CIRCUIT(circ);
     246             : }
     247             : 
     248             : /** Helper function: Query circuitmap for OR circuit with <b>token</b> of size
     249             :  * <b>token_len</b> and <b>type</b>.  Only returns a circuit with purpose equal
     250             :  * to the <b>wanted_circ_purpose</b> parameter and if it is NOT marked for
     251             :  * close. Return NULL if no such circuit is found. */
     252             : static or_circuit_t *
     253          26 : hs_circuitmap_get_or_circuit(hs_token_type_t type,
     254             :                              size_t token_len,
     255             :                              const uint8_t *token,
     256             :                              uint8_t wanted_circ_purpose)
     257             : {
     258          26 :   circuit_t *circ;
     259          26 :   tor_assert(token);
     260          26 :   tor_assert(!CIRCUIT_PURPOSE_IS_ORIGIN(wanted_circ_purpose));
     261             : 
     262          26 :   circ = hs_circuitmap_get_circuit_impl(type, token_len, token,
     263             :                                         wanted_circ_purpose);
     264          26 :   if (!circ) {
     265             :     return NULL;
     266             :   }
     267             : 
     268          11 :   tor_assert(CIRCUIT_IS_ORCIRC(circ));
     269          11 :   return TO_OR_CIRCUIT(circ);
     270             : }
     271             : 
     272             : /************** Public circuitmap API ****************************************/
     273             : 
     274             : /**** Public relay-side getters: */
     275             : 
     276             : /** Public function: Return v3 introduction circuit to this relay.
     277             :  * Always return a newly allocated list for which it is the caller's
     278             :  * responsibility to free it. */
     279             : smartlist_t *
     280         196 : hs_circuitmap_get_all_intro_circ_relay_side(void)
     281             : {
     282         196 :   circuit_t **iter;
     283         196 :   smartlist_t *circuit_list = smartlist_new();
     284             : 
     285         196 :   HT_FOREACH(iter, hs_circuitmap_ht, the_hs_circuitmap) {
     286           0 :     circuit_t *circ = *iter;
     287             : 
     288             :     /* An origin circuit or purpose is wrong or the hs token is not set to be
     289             :      * a v3 intro relay side type, we ignore the circuit. Else, we have
     290             :      * a match so add it to our list. */
     291           0 :     if (CIRCUIT_IS_ORIGIN(circ) ||
     292           0 :         circ->purpose != CIRCUIT_PURPOSE_INTRO_POINT ||
     293           0 :         circ->hs_token->type != HS_TOKEN_INTRO_V3_RELAY_SIDE) {
     294           0 :       continue;
     295             :     }
     296           0 :     smartlist_add(circuit_list, circ);
     297             :   }
     298             : 
     299         196 :   return circuit_list;
     300             : }
     301             : 
     302             : /** Public function: Return a v3 introduction circuit to this relay with
     303             :  * <b>auth_key</b>. Return NULL if no such circuit is found in the
     304             :  * circuitmap. */
     305             : or_circuit_t *
     306          14 : hs_circuitmap_get_intro_circ_v3_relay_side(
     307             :                                           const ed25519_public_key_t *auth_key)
     308             : {
     309          28 :   return hs_circuitmap_get_or_circuit(HS_TOKEN_INTRO_V3_RELAY_SIDE,
     310          14 :                                       ED25519_PUBKEY_LEN, auth_key->pubkey,
     311             :                                       CIRCUIT_PURPOSE_INTRO_POINT);
     312             : }
     313             : 
     314             : /** Public function: Return rendezvous circuit to this relay with rendezvous
     315             :  * <b>cookie</b>. Return NULL if no such circuit is found in the circuitmap. */
     316             : or_circuit_t *
     317          12 : hs_circuitmap_get_rend_circ_relay_side(const uint8_t *cookie)
     318             : {
     319          12 :   return hs_circuitmap_get_or_circuit(HS_TOKEN_REND_RELAY_SIDE,
     320             :                                       REND_TOKEN_LEN, cookie,
     321             :                                       CIRCUIT_PURPOSE_REND_POINT_WAITING);
     322             : }
     323             : 
     324             : /** Public relay-side setters: */
     325             : 
     326             : /** Public function: Register rendezvous circuit with key <b>cookie</b> to the
     327             :  * circuitmap. */
     328             : void
     329           3 : hs_circuitmap_register_rend_circ_relay_side(or_circuit_t *circ,
     330             :                                             const uint8_t *cookie)
     331             : {
     332           3 :   hs_circuitmap_register_circuit(TO_CIRCUIT(circ),
     333             :                                  HS_TOKEN_REND_RELAY_SIDE,
     334             :                                  REND_TOKEN_LEN, cookie);
     335           3 : }
     336             : 
     337             : /** Public function: Register v3 intro circuit with key <b>auth_key</b> to the
     338             :  * circuitmap. */
     339             : void
     340          11 : hs_circuitmap_register_intro_circ_v3_relay_side(or_circuit_t *circ,
     341             :                                           const ed25519_public_key_t *auth_key)
     342             : {
     343          11 :   hs_circuitmap_register_circuit(TO_CIRCUIT(circ),
     344             :                                  HS_TOKEN_INTRO_V3_RELAY_SIDE,
     345          11 :                                  ED25519_PUBKEY_LEN, auth_key->pubkey);
     346          11 : }
     347             : 
     348             : /**** Public servide-side getters: */
     349             : 
     350             : /** Public function: Return v3 introduction circuit with <b>auth_key</b>
     351             :  * originating from this hidden service. Return NULL if no such circuit is
     352             :  * found in the circuitmap. */
     353             : origin_circuit_t *
     354          16 : hs_circuitmap_get_intro_circ_v3_service_side(const
     355             :                                              ed25519_public_key_t *auth_key)
     356             : {
     357          16 :   origin_circuit_t *circ = NULL;
     358             : 
     359             :   /* Check first for established intro circuits */
     360          32 :   circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_INTRO_V3_SERVICE_SIDE,
     361          16 :                                           ED25519_PUBKEY_LEN, auth_key->pubkey,
     362             :                                           CIRCUIT_PURPOSE_S_INTRO);
     363          16 :   if (circ) {
     364             :     return circ;
     365             :   }
     366             : 
     367             :   /* ...if nothing found, check for pending intro circs */
     368          14 :   circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_INTRO_V3_SERVICE_SIDE,
     369             :                                           ED25519_PUBKEY_LEN, auth_key->pubkey,
     370             :                                           CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
     371             : 
     372          14 :   return circ;
     373             : }
     374             : 
     375             : /** Public function: Return rendezvous circuit originating from this hidden
     376             :  * service with rendezvous <b>cookie</b>. Return NULL if no such circuit is
     377             :  * found in the circuitmap. */
     378             : origin_circuit_t *
     379           1 : hs_circuitmap_get_rend_circ_service_side(const uint8_t *cookie)
     380             : {
     381           1 :   origin_circuit_t *circ = NULL;
     382             : 
     383             :   /* Try to check if we have a connecting circuit. */
     384           1 :   circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_REND_SERVICE_SIDE,
     385             :                                           REND_TOKEN_LEN, cookie,
     386             :                                           CIRCUIT_PURPOSE_S_CONNECT_REND);
     387           1 :   if (circ) {
     388             :     return circ;
     389             :   }
     390             : 
     391             :   /* Then try for connected circuit. */
     392           1 :   circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_REND_SERVICE_SIDE,
     393             :                                           REND_TOKEN_LEN, cookie,
     394             :                                           CIRCUIT_PURPOSE_S_REND_JOINED);
     395           1 :   return circ;
     396             : }
     397             : 
     398             : /** Public function: Return client-side rendezvous circuit with rendezvous
     399             :  * <b>cookie</b>. It will look for circuits with the following purposes:
     400             : 
     401             :  * a) CIRCUIT_PURPOSE_C_REND_READY: Established rend circuit (received
     402             :  *    RENDEZVOUS_ESTABLISHED). Waiting for RENDEZVOUS2 from service, and for
     403             :  *    INTRODUCE_ACK from intro point.
     404             :  *
     405             :  * b) CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED: Established rend circuit and
     406             :  *    introduce circuit acked. Waiting for RENDEZVOUS2 from service.
     407             :  *
     408             :  * c) CIRCUIT_PURPOSE_C_REND_JOINED: Established rend circuit and received
     409             :  *    RENDEZVOUS2 from service.
     410             :  *
     411             :  * d) CIRCUIT_PURPOSE_C_ESTABLISH_REND: Rend circuit open but not yet
     412             :  *    established.
     413             :  *
     414             :  * Return NULL if no such circuit is found in the circuitmap. */
     415             : origin_circuit_t *
     416           2 : hs_circuitmap_get_rend_circ_client_side(const uint8_t *cookie)
     417             : {
     418           2 :   origin_circuit_t *circ = NULL;
     419             : 
     420           2 :   circ = hs_circuitmap_get_established_rend_circ_client_side(cookie);
     421           2 :   if (circ) {
     422             :     return circ;
     423             :   }
     424             : 
     425           2 :   circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_REND_CLIENT_SIDE,
     426             :                                           REND_TOKEN_LEN, cookie,
     427             :                                           CIRCUIT_PURPOSE_C_ESTABLISH_REND);
     428           2 :   return circ;
     429             : }
     430             : 
     431             : /**  Public function: Return client-side established rendezvous circuit with
     432             :  *  rendezvous <b>cookie</b>. It will look for circuits with the following
     433             :  *  purposes:
     434             :  *
     435             :  * a) CIRCUIT_PURPOSE_C_REND_READY: Established rend circuit (received
     436             :  *    RENDEZVOUS_ESTABLISHED). Waiting for RENDEZVOUS2 from service, and for
     437             :  *    INTRODUCE_ACK from intro point.
     438             :  *
     439             :  * b) CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED: Established rend circuit and
     440             :  *    introduce circuit acked. Waiting for RENDEZVOUS2 from service.
     441             :  *
     442             :  * c) CIRCUIT_PURPOSE_C_REND_JOINED: Established rend circuit and received
     443             :  *    RENDEZVOUS2 from service.
     444             :  *
     445             :  * Return NULL if no such circuit is found in the circuitmap. */
     446             : origin_circuit_t *
     447           2 : hs_circuitmap_get_established_rend_circ_client_side(const uint8_t *cookie)
     448             : {
     449           2 :   origin_circuit_t *circ = NULL;
     450             : 
     451           2 :   circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_REND_CLIENT_SIDE,
     452             :                                           REND_TOKEN_LEN, cookie,
     453             :                                           CIRCUIT_PURPOSE_C_REND_READY);
     454           2 :   if (circ) {
     455             :     return circ;
     456             :   }
     457             : 
     458           2 :   circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_REND_CLIENT_SIDE,
     459             :                                           REND_TOKEN_LEN, cookie,
     460             :                                  CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED);
     461           2 :   if (circ) {
     462             :     return circ;
     463             :   }
     464             : 
     465           2 :   circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_REND_CLIENT_SIDE,
     466             :                                           REND_TOKEN_LEN, cookie,
     467             :                                           CIRCUIT_PURPOSE_C_REND_JOINED);
     468           2 :   return circ;
     469             : }
     470             : 
     471             : /**** Public servide-side setters: */
     472             : 
     473             : /** Public function: Register v3 intro circuit with key <b>auth_key</b> to the
     474             :  * circuitmap. */
     475             : void
     476           5 : hs_circuitmap_register_intro_circ_v3_service_side(origin_circuit_t *circ,
     477             :                                           const ed25519_public_key_t *auth_key)
     478             : {
     479           5 :   hs_circuitmap_register_circuit(TO_CIRCUIT(circ),
     480             :                                  HS_TOKEN_INTRO_V3_SERVICE_SIDE,
     481           5 :                                  ED25519_PUBKEY_LEN, auth_key->pubkey);
     482           5 : }
     483             : 
     484             : /** Public function: Register rendezvous circuit with key <b>cookie</b> to the
     485             :  * circuitmap. */
     486             : void
     487           0 : hs_circuitmap_register_rend_circ_service_side(origin_circuit_t *circ,
     488             :                                               const uint8_t *cookie)
     489             : {
     490           0 :   hs_circuitmap_register_circuit(TO_CIRCUIT(circ),
     491             :                                  HS_TOKEN_REND_SERVICE_SIDE,
     492             :                                  REND_TOKEN_LEN, cookie);
     493           0 : }
     494             : 
     495             : /** Public function: Register rendezvous circuit with key <b>cookie</b> to the
     496             :  * client-side circuitmap. */
     497             : void
     498           1 : hs_circuitmap_register_rend_circ_client_side(origin_circuit_t *or_circ,
     499             :                                              const uint8_t *cookie)
     500             : {
     501           1 :   circuit_t *circ = TO_CIRCUIT(or_circ);
     502             :   { /* Basic circ purpose sanity checking */
     503           1 :     tor_assert_nonfatal(circ->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND);
     504             :   }
     505             : 
     506           1 :   hs_circuitmap_register_circuit(circ, HS_TOKEN_REND_CLIENT_SIDE,
     507             :                                  REND_TOKEN_LEN, cookie);
     508           1 : }
     509             : 
     510             : /**** Misc public functions: */
     511             : 
     512             : /** Public function: Remove this circuit from the HS circuitmap. Clear its HS
     513             :  *  token, and remove it from the hashtable. */
     514             : void
     515          20 : hs_circuitmap_remove_circuit(circuit_t *circ)
     516             : {
     517          20 :   tor_assert(the_hs_circuitmap);
     518             : 
     519          20 :   if (!circ || !circ->hs_token) {
     520             :     return;
     521             :   }
     522             : 
     523             :   /* Remove circ from circuitmap */
     524          20 :   circuit_t *tmp;
     525          20 :   tmp = HT_REMOVE(hs_circuitmap_ht, the_hs_circuitmap, circ);
     526             :   /* ... and ensure the removal was successful. */
     527          20 :   if (tmp) {
     528          20 :     tor_assert(tmp == circ);
     529             :   } else {
     530           0 :     log_warn(LD_BUG, "Could not find circuit (%u) in circuitmap.",
     531             :              circ->n_circ_id);
     532             :   }
     533             : 
     534             :   /* Clear token from circ */
     535          20 :   hs_token_free(circ->hs_token);
     536          20 :   circ->hs_token = NULL;
     537             : }
     538             : 
     539             : /** Public function: Initialize the global HS circuitmap. */
     540             : void
     541         288 : hs_circuitmap_init(void)
     542             : {
     543         288 :   tor_assert(!the_hs_circuitmap);
     544             : 
     545         288 :   the_hs_circuitmap = tor_malloc_zero(sizeof(struct hs_circuitmap_ht));
     546         288 :   HT_INIT(hs_circuitmap_ht, the_hs_circuitmap);
     547         288 : }
     548             : 
     549             : /** Public function: Free all memory allocated by the global HS circuitmap. */
     550             : void
     551         281 : hs_circuitmap_free_all(void)
     552             : {
     553         281 :   if (the_hs_circuitmap) {
     554         278 :     HT_CLEAR(hs_circuitmap_ht, the_hs_circuitmap);
     555         278 :     tor_free(the_hs_circuitmap);
     556             :   }
     557         281 : }

Generated by: LCOV version 1.14