24#define PROTOVER_PRIVATE
47 { PRT_LINKAUTH,
"LinkAuth" },
48 { PRT_RELAY,
"Relay" },
49 { PRT_DIRCACHE,
"DirCache" },
50 { PRT_HSDIR,
"HSDir" },
51 { PRT_HSINTRO,
"HSIntro" },
52 { PRT_HSREND,
"HSRend" },
54 { PRT_MICRODESC,
"Microdesc"},
55 { PRT_PADDING,
"Padding"},
57 { PRT_FLOWCTRL,
"FlowCtrl"},
58 { PRT_CONFLUX,
"Conflux"},
61#define N_PROTOCOL_NAMES ARRAY_LENGTH(PROTOCOL_NAMES)
66static const unsigned MAX_PROTOCOL_NAME_LENGTH = 100;
76 for (i=0; i < N_PROTOCOL_NAMES; ++i) {
81 tor_assert_nonfatal_unreached_once();
99#define MAX_PROTOCOL_VERSION (63)
109 uint32_t *low_out, uint32_t *high_out)
118 if (BUG(!end_of_range))
119 end_of_range = s + strlen(s);
122 if (!TOR_ISDIGIT(*s)) {
131 if (next > end_of_range)
133 if (next == end_of_range) {
143 if (!TOR_ISDIGIT(*s)) {
150 if (next != end_of_range)
166is_valid_keyword(
const char *s,
size_t n)
168 for (
size_t i = 0; i < n; i++) {
169 if (!TOR_ISALNUM(s[i]) && s[i] !=
'-')
176#define BIT(x) (UINT64_C(1)<<(x))
185 uint64_t mask = ~(uint64_t)0;
187 mask >>= 63 - high + low;
197static proto_entry_t *
200 proto_entry_t *out = tor_malloc_zero(
sizeof(proto_entry_t));
203 if (BUG (!end_of_entry))
204 end_of_entry = s + strlen(s);
207 equals = memchr(s,
'=', end_of_entry - s);
216 if (equals - s > (
int)MAX_PROTOCOL_NAME_LENGTH) {
217 log_warn(
LD_NET,
"When parsing a protocol entry, I got a very large "
218 "protocol name. This is possibly an attack or a bug, unless "
219 "the Tor network truly supports protocol names larger than "
220 "%ud characters. The offending string was: %s",
221 MAX_PROTOCOL_NAME_LENGTH,
escaped(out->name));
226 if (!is_valid_keyword(s, equals-s))
229 out->name = tor_strndup(s, equals-s);
234 while (s < end_of_entry) {
235 const char *comma = memchr(s,
',', end_of_entry-s);
237 comma = end_of_entry;
239 uint32_t low=0, high=0;
248 if (s < (end_of_entry - 1))
255 proto_entry_free(out);
270 const char *end_of_entry = strchr(s,
' ');
271 proto_entry_t *entry;
273 end_of_entry = s + strlen(s);
291 smartlist_free(entries);
307 smartlist_free(list);
343 smartlist_free(protocols);
372 if (strcasecmp(proto->name, pr_name))
374 if (0 != (proto->bitmask & mask)) {
378 } SMARTLIST_FOREACH_END(proto);
382 smartlist_free(protocols);
390#define PR_CONFLUX_V "1"
391#define PR_CONS_V "1-2"
392#define PR_DESC_V "1-3"
393#define PR_DIRCACHE_V "2"
394#define PR_FLOWCTRL_V "1-2"
395#define PR_HSDIR_V "2"
396#define PR_HSINTRO_V "4-5"
397#define PR_HSREND_V "1-2"
398#define PR_LINK_V "1-5"
399#ifdef HAVE_WORKING_TOR_TLS_GET_TLSSECRETS
400#define PR_LINKAUTH_V "1,3"
402#define PR_LINKAUTH_V "3"
404#define PR_MICRODESC_V "1-3"
405#define PR_PADDING_V "2"
406#define PR_RELAY_V "2-4"
414 case PRT_CONFLUX:
return PR_CONFLUX_V;
415 case PRT_CONS:
return PR_CONS_V;
416 case PRT_DESC:
return PR_DESC_V;
417 case PRT_DIRCACHE:
return PR_DIRCACHE_V;
418 case PRT_FLOWCTRL:
return PR_FLOWCTRL_V;
419 case PRT_HSDIR:
return PR_HSDIR_V;
420 case PRT_HSINTRO:
return PR_HSINTRO_V;
421 case PRT_HSREND:
return PR_HSREND_V;
422 case PRT_LINK:
return PR_LINK_V;
423 case PRT_LINKAUTH:
return PR_LINKAUTH_V;
424 case PRT_MICRODESC:
return PR_MICRODESC_V;
425 case PRT_PADDING:
return PR_PADDING_V;
426 case PRT_RELAY:
return PR_RELAY_V;
428 tor_assert_unreached();
477 "Conflux=" PR_CONFLUX_V
" "
478 "Cons=" PR_CONS_V
" "
479 "Desc=" PR_DESC_V
" "
480 "DirCache=" PR_DIRCACHE_V
" "
481 "FlowCtrl=" PR_FLOWCTRL_V
" "
482 "HSDir=" PR_HSDIR_V
" "
483 "HSIntro=" PR_HSINTRO_V
" "
484 "HSRend=" PR_HSREND_V
" "
485 "Link=" PR_LINK_V
" "
486 "LinkAuth=" PR_LINKAUTH_V
" "
487 "Microdesc=" PR_MICRODESC_V
" "
488 "Padding=" PR_PADDING_V
" "
524 return "Cons=2 Desc=2 DirCache=2 HSDir=2 HSIntro=4 HSRend=2 "
525 "Link=4-5 Microdesc=2 Relay=2";
533 return "Cons=2 Desc=2 DirCache=2 HSDir=2 HSIntro=4 HSRend=2 "
534 "Link=4-5 LinkAuth=3 Microdesc=2 Relay=2";
542 return "Cons=2 Desc=2 Link=4 Microdesc=2 Relay=2";
550 return "Cons=2 Desc=2 DirCache=2 HSDir=2 HSIntro=4 HSRend=2 "
551 "Link=4-5 LinkAuth=3 Microdesc=2 Relay=2";
580 return __builtin_ctzll((
unsigned long long)x);
583 for (i = 0; i <= 64; ++i) {
601 uint64_t mask = entry->bitmask;
605 const char *comma = first ?
"" :
",";
617 shift, shift + ones - 1);
632 const char *separator =
"";
640 } SMARTLIST_FOREACH_END(ent);
645 smartlist_free(chunks);
665 tor_assert(smartlist_len(list_of_proto_strings) < 256);
667 if (smartlist_len(list_of_proto_strings) == 0) {
668 return tor_strdup(
"");
679 log_warn(
LD_NET,
"I failed with parsing a protocol list from "
680 "an authority. The offending string was: %s",
688 } SMARTLIST_FOREACH_END(ent);
690 } SMARTLIST_FOREACH_END(vote);
707 for (
int i = 0; i < 64; ++i) {
708 if ((ent->bitmask &
BIT(i)) != 0) {
712 } SMARTLIST_FOREACH_END(vote);
714 uint64_t result_bitmask = 0;
715 for (
int i = 0; i < 64; ++i) {
716 if (
counts[i] >= threshold) {
717 result_bitmask |=
BIT(i);
720 if (result_bitmask != 0) {
721 proto_entry_t *newent = tor_malloc_zero(
sizeof(proto_entry_t));
722 newent->name = tor_strdup(
name);
723 newent->bitmask = result_bitmask;
726 } SMARTLIST_FOREACH_END(
name);
731 smartlist_free(result);
732 smartlist_free(proto_names);
736 } SMARTLIST_FOREACH_END(v);
737 smartlist_free(parsed);
757 if (BUG(entries == NULL)) {
758 log_warn(
LD_NET,
"Received an unparseable protocol list %s"
759 " from the consensus",
escaped(s));
768 if (ent->bitmask != 0) {
769 proto_entry_t *m = tor_malloc_zero(
sizeof(proto_entry_t));
770 m->name = tor_strdup(ent->name);
771 m->bitmask = ent->bitmask;
777 uint64_t missing_mask = ent->bitmask & ~mine->bitmask;
778 if (missing_mask != 0) {
779 proto_entry_t *m = tor_malloc_zero(
sizeof(proto_entry_t));
780 m->name = tor_strdup(ent->name);
781 m->bitmask = missing_mask;
784 } SMARTLIST_FOREACH_END(ent);
786 const int all_supported = (smartlist_len(missing) == 0);
787 if (!all_supported && missing_out) {
792 smartlist_free(missing);
795 smartlist_free(entries);
797 return all_supported;
802static const proto_entry_t *
809 if (!strcmp(ent->name,
name)) {
812 } SMARTLIST_FOREACH_END(ent);
823 if (BUG(protos == NULL)) {
827 if (BUG(pr_name == NULL)) {
836 return (ent->bitmask &
BIT(ver)) != 0;
851 if (version == NULL) {
853 version =
"0.2.5.15";
861 return "Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1-2 "
862 "Link=1-4 LinkAuth=1 "
863 "Microdesc=1-2 Relay=1-2";
868 return "Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 "
869 "Link=1-4 LinkAuth=1 "
870 "Microdesc=1-2 Relay=1-2";
874 return "Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 "
875 "Link=1-4 LinkAuth=1 "
876 "Microdesc=1 Relay=1-2";
892 smartlist_free(entries);
static conn_counts_t counts
const char * escaped(const char *s)
Master header file for Tor-specific functionality.
unsigned long tor_parse_ulong(const char *s, int base, unsigned long min, unsigned long max, int *ok, char **next)
static proto_entry_t * parse_single_entry(const char *s, const char *end_of_entry)
STATIC char * encode_protocol_list(const smartlist_t *sl)
static const proto_entry_t * find_entry_by_name(const smartlist_t *protos, const char *name)
static uint64_t bitmask_for_range(uint32_t low, uint32_t high)
bool protover_list_is_invalid(const char *s)
STATIC void proto_entry_free_(proto_entry_t *entry)
const char * protover_get_recommended_relay_protocols(void)
const char * protover_get_required_relay_protocols(void)
static smartlist_t * supported_protocol_list
static const smartlist_t * get_supported_protocol_list(void)
#define MAX_PROTOCOL_VERSION
const char * protover_get_required_client_protocols(void)
void protover_free_all(void)
static const struct @12 PROTOCOL_NAMES[]
C_RUST_COUPLED: src/rust/protover/protover.rs PROTOCOL_NAMES
static void proto_entry_encode_into(smartlist_t *chunks, const proto_entry_t *entry)
STATIC const char * protocol_type_to_str(protocol_type_t pr)
int protover_is_supported_here(protocol_type_t pr, uint32_t ver)
const char * protover_get_recommended_client_protocols(void)
static int protocol_list_contains(const smartlist_t *protos, protocol_type_t pr, uint32_t ver)
int protocol_list_supports_protocol(const char *list, protocol_type_t tp, uint32_t version)
int protocol_list_supports_protocol_or_later(const char *list, protocol_type_t tp, uint32_t version)
char * protover_compute_vote(const smartlist_t *list_of_proto_strings, int threshold)
static int parse_version_range(const char *s, const char *end_of_range, uint32_t *low_out, uint32_t *high_out)
const char * protover_get_supported_protocols(void)
C_RUST_COUPLED: src/rust/protover/protover.rs SUPPORTED_PROTOCOLS
STATIC smartlist_t * parse_protocol_list(const char *s)
const char * protover_compute_for_old_tor(const char *version)
C_RUST_COUPLED: src/rust/protover/protover.rs compute_for_old_tor
static int trailing_zeros(uint64_t x)
const char * protover_get_supported(const protocol_type_t type)
int protover_all_supported(const char *s, char **missing_out)
Headers and type declarations for protover.c.
#define FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS
void smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern,...)
void smartlist_sort_strings(smartlist_t *sl)
int smartlist_contains_string(const smartlist_t *sl, const char *element)
char * smartlist_join_strings(smartlist_t *sl, const char *join, int terminate, size_t *len_out)
void smartlist_add_strdup(struct smartlist_t *sl, const char *string)
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
int tor_version_as_new_as(const char *platform, const char *cutoff)
Header file for versions.c.