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-4"
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 "3-5"
399#define PR_LINKAUTH_V "3"
400#define PR_MICRODESC_V "1-3"
401#define PR_PADDING_V "2"
402#define PR_RELAY_V "2-4"
410 case PRT_CONFLUX:
return PR_CONFLUX_V;
411 case PRT_CONS:
return PR_CONS_V;
412 case PRT_DESC:
return PR_DESC_V;
413 case PRT_DIRCACHE:
return PR_DIRCACHE_V;
414 case PRT_FLOWCTRL:
return PR_FLOWCTRL_V;
415 case PRT_HSDIR:
return PR_HSDIR_V;
416 case PRT_HSINTRO:
return PR_HSINTRO_V;
417 case PRT_HSREND:
return PR_HSREND_V;
418 case PRT_LINK:
return PR_LINK_V;
419 case PRT_LINKAUTH:
return PR_LINKAUTH_V;
420 case PRT_MICRODESC:
return PR_MICRODESC_V;
421 case PRT_PADDING:
return PR_PADDING_V;
422 case PRT_RELAY:
return PR_RELAY_V;
424 tor_assert_unreached();
473 "Conflux=" PR_CONFLUX_V
" "
474 "Cons=" PR_CONS_V
" "
475 "Desc=" PR_DESC_V
" "
476 "DirCache=" PR_DIRCACHE_V
" "
477 "FlowCtrl=" PR_FLOWCTRL_V
" "
478 "HSDir=" PR_HSDIR_V
" "
479 "HSIntro=" PR_HSINTRO_V
" "
480 "HSRend=" PR_HSREND_V
" "
481 "Link=" PR_LINK_V
" "
482 "LinkAuth=" PR_LINKAUTH_V
" "
483 "Microdesc=" PR_MICRODESC_V
" "
484 "Padding=" PR_PADDING_V
" "
520 return "Cons=2 Desc=2 DirCache=2 FlowCtrl=1-2 HSDir=2 HSIntro=4 HSRend=2 "
521 "Link=4-5 Microdesc=2 Relay=2-4";
529 return "Cons=2 Desc=2 DirCache=2 FlowCtrl=1-2 HSDir=2 HSIntro=4-5 HSRend=2 "
530 "Link=4-5 LinkAuth=3 Microdesc=2 Relay=2-4";
538 return "Cons=2 Desc=2 FlowCtrl=1 Link=4 Microdesc=2 Relay=2";
546 return "Cons=2 Desc=2 DirCache=2 FlowCtrl=1-2 HSDir=2 HSIntro=4-5 HSRend=2 "
547 "Link=4-5 LinkAuth=3 Microdesc=2 Relay=2-4";
576 return __builtin_ctzll((
unsigned long long)x);
579 for (i = 0; i <= 64; ++i) {
597 uint64_t mask = entry->bitmask;
601 const char *comma = first ?
"" :
",";
613 shift, shift + ones - 1);
628 const char *separator =
"";
636 } SMARTLIST_FOREACH_END(ent);
641 smartlist_free(chunks);
661 tor_assert(smartlist_len(list_of_proto_strings) < 256);
663 if (smartlist_len(list_of_proto_strings) == 0) {
664 return tor_strdup(
"");
675 log_warn(
LD_NET,
"I failed with parsing a protocol list from "
676 "an authority. The offending string was: %s",
684 } SMARTLIST_FOREACH_END(ent);
686 } SMARTLIST_FOREACH_END(vote);
703 for (
int i = 0; i < 64; ++i) {
704 if ((ent->bitmask &
BIT(i)) != 0) {
708 } SMARTLIST_FOREACH_END(vote);
710 uint64_t result_bitmask = 0;
711 for (
int i = 0; i < 64; ++i) {
712 if (
counts[i] >= threshold) {
713 result_bitmask |=
BIT(i);
716 if (result_bitmask != 0) {
717 proto_entry_t *newent = tor_malloc_zero(
sizeof(proto_entry_t));
718 newent->name = tor_strdup(
name);
719 newent->bitmask = result_bitmask;
722 } SMARTLIST_FOREACH_END(
name);
727 smartlist_free(result);
728 smartlist_free(proto_names);
732 } SMARTLIST_FOREACH_END(v);
733 smartlist_free(parsed);
753 if (BUG(entries == NULL)) {
754 log_warn(
LD_NET,
"Received an unparseable protocol list %s"
755 " from the consensus",
escaped(s));
764 if (ent->bitmask != 0) {
765 proto_entry_t *m = tor_malloc_zero(
sizeof(proto_entry_t));
766 m->name = tor_strdup(ent->name);
767 m->bitmask = ent->bitmask;
773 uint64_t missing_mask = ent->bitmask & ~mine->bitmask;
774 if (missing_mask != 0) {
775 proto_entry_t *m = tor_malloc_zero(
sizeof(proto_entry_t));
776 m->name = tor_strdup(ent->name);
777 m->bitmask = missing_mask;
780 } SMARTLIST_FOREACH_END(ent);
782 const int all_supported = (smartlist_len(missing) == 0);
783 if (!all_supported && missing_out) {
788 smartlist_free(missing);
791 smartlist_free(entries);
793 return all_supported;
798static const proto_entry_t *
805 if (!strcmp(ent->name,
name)) {
808 } SMARTLIST_FOREACH_END(ent);
819 if (BUG(protos == NULL)) {
823 if (BUG(pr_name == NULL)) {
832 return (ent->bitmask &
BIT(ver)) != 0;
847 if (version == NULL) {
849 version =
"0.2.5.15";
857 return "Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1-2 "
858 "Link=1-4 LinkAuth=1 "
859 "Microdesc=1-2 Relay=1-2";
864 return "Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 "
865 "Link=1-4 LinkAuth=1 "
866 "Microdesc=1-2 Relay=1-2";
870 return "Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 "
871 "Link=1-4 LinkAuth=1 "
872 "Microdesc=1 Relay=1-2";
888 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.