Tor  0.4.4.0-alpha-dev
hs_circuitmap.c
Go to the documentation of this file.
1 /* Copyright (c) 2016-2020, 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"
20 
21 #include "core/or/or_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
35  const circuit_t *second_circuit)
36 {
37  const hs_token_t *first_token;
38  const hs_token_t *second_token;
39 
40  tor_assert(first_circuit);
41  tor_assert(second_circuit);
42 
43  first_token = first_circuit->hs_token;
44  second_token = second_circuit->hs_token;
45 
46  /* Both circs must have a token */
47  if (BUG(!first_token) || BUG(!second_token)) {
48  return 0;
49  }
50 
51  if (first_token->type != second_token->type) {
52  return 0;
53  }
54 
55  if (first_token->token_len != second_token->token_len)
56  return 0;
57 
58  return tor_memeq(first_token->token,
59  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
68 {
69  tor_assert(circuit->hs_token);
70 
71  return (unsigned) siphash24g(circuit->hs_token->token,
72  circuit->hs_token->token_len);
73 }
74 
75 /** Register the circuitmap hash table */
76 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
80 
81 HT_GENERATE2(hs_circuitmap_ht, circuit_t, hs_circuitmap_node,
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 get_hs_circuitmap(void)
90 {
91  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 hs_token_new(hs_token_type_t type, size_t token_len,
101  const uint8_t *token)
102 {
103  tor_assert(token);
104 
105  hs_token_t *hs_token = tor_malloc_zero(sizeof(hs_token_t));
106  hs_token->type = type;
107  hs_token->token_len = token_len;
108  hs_token->token = tor_memdup(token, token_len);
109 
110  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 hs_token_free_(hs_token_t *hs_token)
119 {
120  if (!hs_token) {
121  return;
122  }
123 
124  tor_free(hs_token->token);
125  tor_free(hs_token);
126 }
127 
128 /** Return the circuit from the circuitmap with token <b>search_token</b>. */
129 static circuit_t *
130 get_circuit_with_token(hs_token_t *search_token)
131 {
133 
134  /* We use a dummy circuit object for the hash table search routine. */
135  circuit_t search_circ;
136  search_circ.hs_token = search_token;
137  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 hs_circuitmap_register_impl(circuit_t *circ, hs_token_t *token)
144 {
145  tor_assert(circ);
146  tor_assert(token);
148 
149  /* If this circuit already has a token, clear it. */
150  if (circ->hs_token) {
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  circuit_t *found_circ;
159  found_circ = get_circuit_with_token(token);
160  if (found_circ) {
161  hs_circuitmap_remove_circuit(found_circ);
162  if (!found_circ->marked_for_close) {
163  circuit_mark_for_close(found_circ, END_CIRC_REASON_FINISHED);
164  }
165  }
166  }
167 
168  /* Register circuit and token to circuitmap. */
169  circ->hs_token = token;
170  HT_INSERT(hs_circuitmap_ht, the_hs_circuitmap, circ);
171 }
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
178  hs_token_type_t type, size_t token_len,
179  const uint8_t *token)
180 {
181  hs_token_t *hs_token = NULL;
182 
183  /* Create a new token and register it to the circuitmap */
184  tor_assert(token);
185  hs_token = hs_token_new(type, token_len, token);
186  tor_assert(hs_token);
187  hs_circuitmap_register_impl(circ, hs_token);
188 }
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 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  circuit_t *found_circ = NULL;
203 
205 
206  /* Check the circuitmap if we have a circuit with this token */
207  {
208  hs_token_t *search_hs_token = hs_token_new(type, token_len, token);
209  tor_assert(search_hs_token);
210  found_circ = get_circuit_with_token(search_hs_token);
211  hs_token_free(search_hs_token);
212  }
213 
214  /* Check that the circuit is useful to us */
215  if (!found_circ ||
216  found_circ->purpose != wanted_circ_purpose ||
217  found_circ->marked_for_close) {
218  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 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  circuit_t *circ;
235  tor_assert(token);
236  tor_assert(CIRCUIT_PURPOSE_IS_ORIGIN(wanted_circ_purpose));
237 
238  circ = hs_circuitmap_get_circuit_impl(type, token_len, token,
239  wanted_circ_purpose);
240  if (!circ) {
241  return NULL;
242  }
243 
245  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 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  circuit_t *circ;
259  tor_assert(token);
260  tor_assert(!CIRCUIT_PURPOSE_IS_ORIGIN(wanted_circ_purpose));
261 
262  circ = hs_circuitmap_get_circuit_impl(type, token_len, token,
263  wanted_circ_purpose);
264  if (!circ) {
265  return NULL;
266  }
267 
269  return TO_OR_CIRCUIT(circ);
270 }
271 
272 /************** Public circuitmap API ****************************************/
273 
274 /**** Public relay-side getters: */
275 
276 /** Public function: Return v2 and v3 introduction circuit to this relay.
277  * Always return a newly allocated list for which it is the caller's
278  * responsability to free it. */
279 smartlist_t *
281 {
282  circuit_t **iter;
283  smartlist_t *circuit_list = smartlist_new();
284 
285  HT_FOREACH(iter, hs_circuitmap_ht, the_hs_circuitmap) {
286  circuit_t *circ = *iter;
287 
288  /* An origin circuit or purpose is wrong or the hs token is not set to be
289  * a v2 or v3 intro relay side type, we ignore the circuit. Else, we have
290  * a match so add it to our list. */
291  if (CIRCUIT_IS_ORIGIN(circ) ||
293  (circ->hs_token->type != HS_TOKEN_INTRO_V3_RELAY_SIDE &&
294  circ->hs_token->type != HS_TOKEN_INTRO_V2_RELAY_SIDE)) {
295  continue;
296  }
297  smartlist_add(circuit_list, circ);
298  }
299 
300  return circuit_list;
301 }
302 
303 /** Public function: Return a v3 introduction circuit to this relay with
304  * <b>auth_key</b>. Return NULL if no such circuit is found in the
305  * circuitmap. */
306 or_circuit_t *
308  const ed25519_public_key_t *auth_key)
309 {
310  return hs_circuitmap_get_or_circuit(HS_TOKEN_INTRO_V3_RELAY_SIDE,
311  ED25519_PUBKEY_LEN, auth_key->pubkey,
313 }
314 
315 /** Public function: Return v2 introduction circuit to this relay with
316  * <b>digest</b>. Return NULL if no such circuit is found in the circuitmap. */
317 or_circuit_t *
319 {
320  return hs_circuitmap_get_or_circuit(HS_TOKEN_INTRO_V2_RELAY_SIDE,
321  REND_TOKEN_LEN, digest,
323 }
324 
325 /** Public function: Return rendezvous circuit to this relay with rendezvous
326  * <b>cookie</b>. Return NULL if no such circuit is found in the circuitmap. */
327 or_circuit_t *
329 {
330  return hs_circuitmap_get_or_circuit(HS_TOKEN_REND_RELAY_SIDE,
331  REND_TOKEN_LEN, cookie,
333 }
334 
335 /** Public relay-side setters: */
336 
337 /** Public function: Register rendezvous circuit with key <b>cookie</b> to the
338  * circuitmap. */
339 void
341  const uint8_t *cookie)
342 {
344  HS_TOKEN_REND_RELAY_SIDE,
345  REND_TOKEN_LEN, cookie);
346 }
347 /** Public function: Register v2 intro circuit with key <b>digest</b> to the
348  * circuitmap. */
349 void
351  const uint8_t *digest)
352 {
354  HS_TOKEN_INTRO_V2_RELAY_SIDE,
355  REND_TOKEN_LEN, digest);
356 }
357 
358 /** Public function: Register v3 intro circuit with key <b>auth_key</b> to the
359  * circuitmap. */
360 void
362  const ed25519_public_key_t *auth_key)
363 {
365  HS_TOKEN_INTRO_V3_RELAY_SIDE,
366  ED25519_PUBKEY_LEN, auth_key->pubkey);
367 }
368 
369 /**** Public servide-side getters: */
370 
371 /** Public function: Return v3 introduction circuit with <b>auth_key</b>
372  * originating from this hidden service. Return NULL if no such circuit is
373  * found in the circuitmap. */
376  ed25519_public_key_t *auth_key)
377 {
378  origin_circuit_t *circ = NULL;
379 
380  /* Check first for established intro circuits */
381  circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_INTRO_V3_SERVICE_SIDE,
382  ED25519_PUBKEY_LEN, auth_key->pubkey,
384  if (circ) {
385  return circ;
386  }
387 
388  /* ...if nothing found, check for pending intro circs */
389  circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_INTRO_V3_SERVICE_SIDE,
390  ED25519_PUBKEY_LEN, auth_key->pubkey,
392 
393  return circ;
394 }
395 
396 /** Public function: Return v2 introduction circuit originating from this
397  * hidden service with <b>digest</b>. Return NULL if no such circuit is found
398  * in the circuitmap. */
401 {
402  origin_circuit_t *circ = NULL;
403 
404  /* Check first for established intro circuits */
405  circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_INTRO_V2_SERVICE_SIDE,
406  REND_TOKEN_LEN, digest,
408  if (circ) {
409  return circ;
410  }
411 
412  /* ...if nothing found, check for pending intro circs */
413  circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_INTRO_V2_SERVICE_SIDE,
414  REND_TOKEN_LEN, digest,
416 
417  return circ;
418 }
419 
420 /** Public function: Return rendezvous circuit originating from this hidden
421  * service with rendezvous <b>cookie</b>. Return NULL if no such circuit is
422  * found in the circuitmap. */
425 {
426  origin_circuit_t *circ = NULL;
427 
428  /* Try to check if we have a connecting circuit. */
429  circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_REND_SERVICE_SIDE,
430  REND_TOKEN_LEN, cookie,
432  if (circ) {
433  return circ;
434  }
435 
436  /* Then try for connected circuit. */
437  circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_REND_SERVICE_SIDE,
438  REND_TOKEN_LEN, cookie,
440  return circ;
441 }
442 
443 /** Public function: Return client-side rendezvous circuit with rendezvous
444  * <b>cookie</b>. It will look for circuits with the following purposes:
445 
446  * a) CIRCUIT_PURPOSE_C_REND_READY: Established rend circuit (received
447  * RENDEZVOUS_ESTABLISHED). Waiting for RENDEZVOUS2 from service, and for
448  * INTRODUCE_ACK from intro point.
449  *
450  * b) CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED: Established rend circuit and
451  * introduce circuit acked. Waiting for RENDEZVOUS2 from service.
452  *
453  * c) CIRCUIT_PURPOSE_C_REND_JOINED: Established rend circuit and received
454  * RENDEZVOUS2 from service.
455  *
456  * d) CIRCUIT_PURPOSE_C_ESTABLISH_REND: Rend circuit open but not yet
457  * established.
458  *
459  * Return NULL if no such circuit is found in the circuitmap. */
462 {
463  origin_circuit_t *circ = NULL;
464 
466  if (circ) {
467  return circ;
468  }
469 
470  circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_REND_CLIENT_SIDE,
471  REND_TOKEN_LEN, cookie,
473  return circ;
474 }
475 
476 /** Public function: Return client-side established rendezvous circuit with
477  * rendezvous <b>cookie</b>. It will look for circuits with the following
478  * purposes:
479  *
480  * a) CIRCUIT_PURPOSE_C_REND_READY: Established rend circuit (received
481  * RENDEZVOUS_ESTABLISHED). Waiting for RENDEZVOUS2 from service, and for
482  * INTRODUCE_ACK from intro point.
483  *
484  * b) CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED: Established rend circuit and
485  * introduce circuit acked. Waiting for RENDEZVOUS2 from service.
486  *
487  * c) CIRCUIT_PURPOSE_C_REND_JOINED: Established rend circuit and received
488  * RENDEZVOUS2 from service.
489  *
490  * Return NULL if no such circuit is found in the circuitmap. */
493 {
494  origin_circuit_t *circ = NULL;
495 
496  circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_REND_CLIENT_SIDE,
497  REND_TOKEN_LEN, cookie,
499  if (circ) {
500  return circ;
501  }
502 
503  circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_REND_CLIENT_SIDE,
504  REND_TOKEN_LEN, cookie,
506  if (circ) {
507  return circ;
508  }
509 
510  circ = hs_circuitmap_get_origin_circuit(HS_TOKEN_REND_CLIENT_SIDE,
511  REND_TOKEN_LEN, cookie,
513  return circ;
514 }
515 
516 /**** Public servide-side setters: */
517 
518 /** Public function: Register v2 intro circuit with key <b>digest</b> to the
519  * circuitmap. */
520 void
522  const uint8_t *digest)
523 {
525  HS_TOKEN_INTRO_V2_SERVICE_SIDE,
526  REND_TOKEN_LEN, digest);
527 }
528 
529 /** Public function: Register v3 intro circuit with key <b>auth_key</b> to the
530  * circuitmap. */
531 void
533  const ed25519_public_key_t *auth_key)
534 {
536  HS_TOKEN_INTRO_V3_SERVICE_SIDE,
537  ED25519_PUBKEY_LEN, auth_key->pubkey);
538 }
539 
540 /** Public function: Register rendezvous circuit with key <b>cookie</b> to the
541  * circuitmap. */
542 void
544  const uint8_t *cookie)
545 {
547  HS_TOKEN_REND_SERVICE_SIDE,
548  REND_TOKEN_LEN, cookie);
549 }
550 
551 /** Public function: Register rendezvous circuit with key <b>cookie</b> to the
552  * client-side circuitmap. */
553 void
555  const uint8_t *cookie)
556 {
557  circuit_t *circ = TO_CIRCUIT(or_circ);
558  { /* Basic circ purpose sanity checking */
559  tor_assert_nonfatal(circ->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND);
560  }
561 
562  hs_circuitmap_register_circuit(circ, HS_TOKEN_REND_CLIENT_SIDE,
563  REND_TOKEN_LEN, cookie);
564 }
565 
566 /**** Misc public functions: */
567 
568 /** Public function: Remove this circuit from the HS circuitmap. Clear its HS
569  * token, and remove it from the hashtable. */
570 void
572 {
574 
575  if (!circ || !circ->hs_token) {
576  return;
577  }
578 
579  /* Remove circ from circuitmap */
580  circuit_t *tmp;
581  tmp = HT_REMOVE(hs_circuitmap_ht, the_hs_circuitmap, circ);
582  /* ... and ensure the removal was successful. */
583  if (tmp) {
584  tor_assert(tmp == circ);
585  } else {
586  log_warn(LD_BUG, "Could not find circuit (%u) in circuitmap.",
587  circ->n_circ_id);
588  }
589 
590  /* Clear token from circ */
591  hs_token_free(circ->hs_token);
592  circ->hs_token = NULL;
593 }
594 
595 /** Public function: Initialize the global HS circuitmap. */
596 void
598 {
600 
601  the_hs_circuitmap = tor_malloc_zero(sizeof(struct hs_circuitmap_ht));
602  HT_INIT(hs_circuitmap_ht, the_hs_circuitmap);
603 }
604 
605 /** Public function: Free all memory allocated by the global HS circuitmap. */
606 void
608 {
609  if (the_hs_circuitmap) {
610  HT_CLEAR(hs_circuitmap_ht, the_hs_circuitmap);
612  }
613 }
origin_circuit_t * hs_circuitmap_get_rend_circ_service_side(const uint8_t *cookie)
static struct hs_circuitmap_ht * the_hs_circuitmap
Definition: hs_circuitmap.c:29
#define CIRCUIT_PURPOSE_IS_ORIGIN(p)
Definition: circuitlist.h:139
#define CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED
Definition: circuitlist.h:88
static circuit_t * get_circuit_with_token(hs_token_t *search_token)
or_circuit_t * hs_circuitmap_get_rend_circ_relay_side(const uint8_t *cookie)
static int hs_circuits_have_same_token(const circuit_t *first_circuit, const circuit_t *second_circuit)
Definition: hs_circuitmap.c:34
#define CIRCUIT_IS_ORIGIN(c)
Definition: circuitlist.h:146
#define CIRCUIT_PURPOSE_REND_POINT_WAITING
Definition: circuitlist.h:45
uint8_t purpose
Definition: circuit_st.h:111
void smartlist_add(smartlist_t *sl, void *element)
HT_PROTOTYPE(HT_GENERATE2(hs_circuitmap_ht, HT_GENERATE2(circuit_t, HT_GENERATE2(hs_circuitmap_node, HT_GENERATE2(hs_circuit_hash_token, HT_GENERATE2(hs_circuits_have_same_token)
Definition: hs_circuitmap.c:76
#define TO_CIRCUIT(x)
Definition: or.h:951
#define CIRCUIT_PURPOSE_C_REND_READY
Definition: circuitlist.h:85
Header file for config.c.
#define tor_assert(expr)
Definition: util_bug.h:102
#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
Definition: circuitlist.h:103
void hs_circuitmap_register_intro_circ_v3_relay_side(or_circuit_t *circ, const ed25519_public_key_t *auth_key)
#define tor_free(p)
Definition: malloc.h:52
#define ED25519_PUBKEY_LEN
Definition: x25519_sizes.h:27
uint16_t marked_for_close
Definition: circuit_st.h:189
void hs_circuitmap_register_rend_circ_service_side(origin_circuit_t *circ, const uint8_t *cookie)
void hs_circuitmap_init(void)
origin_circuit_t * hs_circuitmap_get_intro_circ_v2_service_side(const uint8_t *digest)
static circuit_t * hs_circuitmap_get_circuit_impl(hs_token_type_t type, size_t token_len, const uint8_t *token, uint8_t wanted_circ_purpose)
smartlist_t * smartlist_new(void)
void hs_circuitmap_free_all(void)
smartlist_t * hs_circuitmap_get_all_intro_circ_relay_side(void)
origin_circuit_t * hs_circuitmap_get_intro_circ_v3_service_side(const ed25519_public_key_t *auth_key)
static void hs_token_free_(hs_token_t *hs_token)
origin_circuit_t * hs_circuitmap_get_established_rend_circ_client_side(const uint8_t *cookie)
int tor_memeq(const void *a, const void *b, size_t sz)
Definition: di_ops.c:107
static void hs_circuitmap_register_circuit(circuit_t *circ, hs_token_type_t type, size_t token_len, const uint8_t *token)
void hs_circuitmap_register_rend_circ_relay_side(or_circuit_t *circ, const uint8_t *cookie)
Origin circuit structure.
Master header file for Tor-specific functionality.
HT_GENERATE2(cdm_diff_ht, cdm_diff_t, node, cdm_diff_hash, cdm_diff_eq, 0.6, tor_reallocarray, tor_free_) static void cdm_diff_free_(cdm_diff_t *diff)
Definition: consdiffmgr.c:222
struct hs_token_t * hs_token
Definition: circuit_st.h:216
void hs_circuitmap_register_intro_circ_v3_service_side(origin_circuit_t *circ, const ed25519_public_key_t *auth_key)
or_circuit_t * hs_circuitmap_get_intro_circ_v2_relay_side(const uint8_t *digest)
#define CIRCUIT_PURPOSE_C_ESTABLISH_REND
Definition: circuitlist.h:83
void tor_free_(void *mem)
Definition: malloc.c:227
Header file for hs_circuitmap.c.
#define CIRCUIT_PURPOSE_S_CONNECT_REND
Definition: circuitlist.h:109
Header file for circuitlist.c.
or_circuit_t * hs_circuitmap_get_intro_circ_v3_relay_side(const ed25519_public_key_t *auth_key)
void hs_circuitmap_remove_circuit(circuit_t *circ)
#define CIRCUIT_PURPOSE_S_INTRO
Definition: circuitlist.h:106
static unsigned int hs_circuit_hash_token(const circuit_t *circuit)
Definition: hs_circuitmap.c:67
origin_circuit_t * hs_circuitmap_get_rend_circ_client_side(const uint8_t *cookie)
origin_circuit_t * TO_ORIGIN_CIRCUIT(circuit_t *x)
Definition: circuitlist.c:165
#define CIRCUIT_PURPOSE_INTRO_POINT
Definition: circuitlist.h:42
#define CIRCUIT_PURPOSE_C_REND_JOINED
Definition: circuitlist.h:90
or_circuit_t * TO_OR_CIRCUIT(circuit_t *x)
Definition: circuitlist.c:153
#define CIRCUIT_IS_ORCIRC(c)
Definition: circuitlist.h:153
circid_t n_circ_id
Definition: circuit_st.h:78
void hs_circuitmap_register_intro_circ_v2_relay_side(or_circuit_t *circ, const uint8_t *digest)
void hs_circuitmap_register_rend_circ_client_side(origin_circuit_t *or_circ, const uint8_t *cookie)
static void hs_circuitmap_register_impl(circuit_t *circ, hs_token_t *token)
static origin_circuit_t * hs_circuitmap_get_origin_circuit(hs_token_type_t type, size_t token_len, const uint8_t *token, uint8_t wanted_circ_purpose)
#define CIRCUIT_PURPOSE_S_REND_JOINED
Definition: circuitlist.h:112
void hs_circuitmap_register_intro_circ_v2_service_side(origin_circuit_t *circ, const uint8_t *digest)
static or_circuit_t * hs_circuitmap_get_or_circuit(hs_token_type_t type, size_t token_len, const uint8_t *token, uint8_t wanted_circ_purpose)
#define LD_BUG
Definition: log.h:86