12#define NS_PARSE_PRIVATE
66 T1_START(
"network-status-version", K_NETWORK_STATUS_VERSION,
68 T1(
"vote-status", K_VOTE_STATUS,
GE(1),
NO_OBJ ),
73 T1(
"voting-delay", K_VOTING_DELAY,
GE(2),
NO_OBJ ),
79 T0N(
"shared-rand-commit", K_COMMIT,
GE(3),
NO_OBJ ),
80 T01(
"shared-rand-previous-value", K_PREVIOUS_SRV,
EQ(2),
NO_OBJ ),
81 T01(
"shared-rand-current-value", K_CURRENT_SRV,
EQ(2),
NO_OBJ ),
83 T01(
"recommended-client-protocols", K_RECOMMENDED_CLIENT_PROTOCOLS,
85 T01(
"recommended-relay-protocols", K_RECOMMENDED_RELAY_PROTOCOLS,
87 T01(
"required-client-protocols", K_REQUIRED_CLIENT_PROTOCOLS,
89 T01(
"required-relay-protocols", K_REQUIRED_RELAY_PROTOCOLS,
96 T1(
"dir-source", K_DIR_SOURCE,
GE(6),
NO_OBJ ),
97 T01(
"legacy-dir-key", K_LEGACY_DIR_KEY,
GE(1),
NO_OBJ ),
101 T1(
"consensus-methods", K_CONSENSUS_METHODS,
GE(1),
NO_OBJ ),
109static token_rule_t networkstatus_consensus_token_table[] = {
110 T1_START(
"network-status-version", K_NETWORK_STATUS_VERSION,
112 T1(
"vote-status", K_VOTE_STATUS,
GE(1),
NO_OBJ ),
116 T1(
"voting-delay", K_VOTING_DELAY,
GE(2),
NO_OBJ ),
128 T01(
"consensus-method", K_CONSENSUS_METHOD,
EQ(1),
NO_OBJ),
131 T01(
"shared-rand-previous-value", K_PREVIOUS_SRV,
EQ(2),
NO_OBJ ),
132 T01(
"shared-rand-current-value", K_CURRENT_SRV,
EQ(2),
NO_OBJ ),
134 T01(
"recommended-client-protocols", K_RECOMMENDED_CLIENT_PROTOCOLS,
136 T01(
"recommended-relay-protocols", K_RECOMMENDED_RELAY_PROTOCOLS,
138 T01(
"required-client-protocols", K_REQUIRED_CLIENT_PROTOCOLS,
140 T01(
"required-relay-protocols", K_REQUIRED_RELAY_PROTOCOLS,
149static token_rule_t networkstatus_vote_footer_token_table[] = {
152 T(
"directory-signature", K_DIRECTORY_SIGNATURE,
GE(2),
NEED_OBJ ),
165 const char **start_out,
166 const char **end_out)
169 "network-status-version",
170 "\ndirectory-signature",
180 const char *s,
size_t len)
182 const char *start, *end;
201 "network-status-version",
202 "\ndirectory-signature",
210static inline const char *
211find_start_of_next_routerstatus(
const char *s,
const char *s_eos)
213 const char *eos, *footer, *sig;
214 if ((eos = tor_memstr(s, s_eos - s,
"\nr ")))
219 footer = tor_memstr(s, eos-s,
"\ndirectory-footer");
220 sig = tor_memstr(s, eos-s,
"\ndirectory-signature");
223 return MIN(footer, sig) + 1;
238routerstatus_parse_guardfraction(
const char *guardfraction_str,
244 const char *end_of_header = NULL;
245 int is_consensus = !vote_rs;
246 uint32_t guardfraction;
256 end_of_header = strchr(guardfraction_str,
'=');
257 if (!end_of_header) {
262 10, 0, 100, &ok, NULL);
264 log_warn(
LD_DIR,
"Invalid GuardFraction %s",
escaped(guardfraction_str));
268 log_debug(
LD_GENERAL,
"[*] Parsed %s guardfraction '%s' for '%s'.",
269 is_consensus ?
"consensus" :
"vote",
281 log_warn(
LD_BUG,
"Got GuardFraction for non-guard %s. "
282 "This is not supposed to happen. Not applying. ", rs->
nickname);
304routerstatus_parse_entry_from_string(
memarea_t *area,
305 const char **s,
const char *s_eos,
309 int consensus_method,
312 const char *eos, *s_dup = *s;
315 char timebuf[ISO_TIME_LEN+1];
321 if (!consensus_method)
323 tor_assert(flav == FLAV_NS || flav == FLAV_MICRODESC);
325 eos = find_start_of_next_routerstatus(*s, s_eos);
328 log_warn(
LD_DIR,
"Error tokenizing router status");
331 if (smartlist_len(tokens) < 1) {
332 log_warn(
LD_DIR,
"Impossibly short router status");
335 tok = find_by_keyword(tokens, K_R);
337 if (flav == FLAV_NS) {
339 log_warn(
LD_DIR,
"Too few arguments to r");
342 }
else if (flav == FLAV_MICRODESC) {
354 "Invalid nickname %s in router status; skipping.",
361 log_warn(
LD_DIR,
"Error decoding identity digest %s",
366 if (flav == FLAV_NS) {
368 log_warn(
LD_DIR,
"Error decoding descriptor digest %s",
376 tok->
args[3+offset], tok->
args[4+offset]) < 0 ||
378 log_warn(
LD_DIR,
"Error parsing time '%s %s' [%d %d]",
379 tok->
args[3+offset], tok->
args[4+offset],
387 log_warn(
LD_DIR,
"Error parsing router address in network-status %s",
394 10,0,65535,NULL,NULL);
396 10,0,65535,NULL,NULL);
402 smartlist_free(a_lines);
410 for (i=0; i < tok->
n_args; ++i) {
413 vote_rs->
flags |= (UINT64_C(1)<<p);
415 log_warn(
LD_DIR,
"Flags line had a flag %s not listed in known_flags.",
423 for (i=0; i < tok->
n_args; ++i) {
424 if (!strcmp(tok->
args[i],
"Exit"))
426 else if (!strcmp(tok->
args[i],
"Stable"))
428 else if (!strcmp(tok->
args[i],
"Fast"))
430 else if (!strcmp(tok->
args[i],
"Running"))
432 else if (!strcmp(tok->
args[i],
"Named"))
434 else if (!strcmp(tok->
args[i],
"Valid"))
436 else if (!strcmp(tok->
args[i],
"Guard"))
438 else if (!strcmp(tok->
args[i],
"BadExit"))
440 else if (!strcmp(tok->
args[i],
"MiddleOnly"))
442 else if (!strcmp(tok->
args[i],
"Authority"))
444 else if (!strcmp(tok->
args[i],
"Unnamed") &&
445 consensus_method >= 2) {
448 }
else if (!strcmp(tok->
args[i],
"HSDir")) {
450 }
else if (!strcmp(tok->
args[i],
"V2Dir")) {
452 }
else if (!strcmp(tok->
args[i],
"StaleDesc")) {
454 }
else if (!strcmp(tok->
args[i],
"Sybil")) {
464 const char *protocols = NULL, *version = NULL;
467 protocols = tok->
args[0];
471 version = tok->
args[0];
487 for (i=0; i < tok->
n_args; ++i) {
503 10, 0, UINT32_MAX, &ok, NULL);
505 log_warn(
LD_DIR,
"Invalid Measured Bandwidth %s",
514 if (routerstatus_parse_guardfraction(tok->
args[i],
515 vote, vote_rs, rs) < 0) {
527 log_warn(
LD_DIR,
"Unknown exit policy summary type %s.",
541 if (t->tp == K_M && t->n_args) {
550 if (!strcmp(t->args[0],
"ed25519")) {
552 if (strcmp(t->args[1],
"none") &&
555 log_warn(
LD_DIR,
"Bogus ed25519 key in networkstatus vote");
560 if (t->tp == K_PROTO) {
562 vote_rs->
protocols = tor_strdup(t->args[0]);
564 } SMARTLIST_FOREACH_END(t);
565 }
else if (flav == FLAV_MICRODESC) {
570 log_warn(
LD_DIR,
"Error decoding microdescriptor digest %s",
575 log_info(
LD_BUG,
"Found an entry in networkstatus with no "
576 "microdescriptor digest. (Router %s ($%s) at %s:%d.)",
589 routerstatus_free(rs);
595 DUMP_AREA(area,
"routerstatus entry");
604compare_vote_routerstatus_entries(
const void **_a,
const void **_b)
615 int64_t G=0, M=0, E=0, D=0,
T=0;
616 double Wgg, Wgm, Wgd, Wmg, Wmm, Wme, Wmd, Weg, Wem, Wee, Wed;
617 double Gtotal=0, Mtotal=0, Etotal=0;
618 const char *casename = NULL;
620 (void) consensus_method;
636 if (Wgg<0 || Wgm<0 || Wgd<0 || Wmg<0 || Wmm<0 || Wme<0 || Wmd<0 || Weg<0
637 || Wem<0 || Wee<0 || Wed<0) {
638 log_warn(
LD_BUG,
"No bandwidth weights produced in consensus!");
645 if (fabs(Wmm - weight_scale) > 1) {
646 log_warn(
LD_BUG,
"Wmm=%f != %"PRId64,
647 Wmm, (weight_scale));
651 if (fabs(Wem - Wee) > 1) {
652 log_warn(
LD_BUG,
"Wem=%f != Wee=%f", Wem, Wee);
656 if (fabs(Wgm - Wgg) > 1) {
657 log_warn(
LD_BUG,
"Wgm=%f != Wgg=%f", Wgm, Wgg);
661 if (fabs(Weg - Wed) > 1) {
662 log_warn(
LD_BUG,
"Wed=%f != Weg=%f", Wed, Weg);
666 if (fabs(Wgg + Wmg - weight_scale) > 0.001*weight_scale) {
667 log_warn(
LD_BUG,
"Wgg=%f != %"PRId64
" - Wmg=%f", Wgg,
668 (weight_scale), Wmg);
672 if (fabs(Wee + Wme - weight_scale) > 0.001*weight_scale) {
673 log_warn(
LD_BUG,
"Wee=%f != %"PRId64
" - Wme=%f", Wee,
674 (weight_scale), Wme);
678 if (fabs(Wgd + Wmd + Wed - weight_scale) > 0.001*weight_scale) {
679 log_warn(
LD_BUG,
"Wgd=%f + Wmd=%f + Wed=%f != %"PRId64,
680 Wgd, Wmd, Wed, (weight_scale));
685 Wgm /= weight_scale; (void) Wgm;
693 Weg /= weight_scale; (void) Weg;
694 Wem /= weight_scale; (void) Wem;
710 }
else if (is_exit) {
723 log_warn(
LD_BUG,
"Missing consensus bandwidth for router %s",
726 } SMARTLIST_FOREACH_END(rs);
732 if (3*E >=
T && 3*G >=
T) {
735 if (fabs(Etotal-Mtotal) > 0.01*
MAX(Etotal,Mtotal)) {
737 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
738 "G=%"PRId64
" M=%"PRId64
" E=%"PRId64
" D=%"PRId64
740 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
741 casename, Etotal, Mtotal,
744 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
747 if (fabs(Etotal-Gtotal) > 0.01*
MAX(Etotal,Gtotal)) {
749 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
750 "G=%"PRId64
" M=%"PRId64
" E=%"PRId64
" D=%"PRId64
752 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
753 casename, Etotal, Gtotal,
756 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
759 if (fabs(Gtotal-Mtotal) > 0.01*
MAX(Gtotal,Mtotal)) {
761 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
762 "G=%"PRId64
" M=%"PRId64
" E=%"PRId64
" D=%"PRId64
764 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
765 casename, Mtotal, Gtotal,
768 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
771 }
else if (3*E <
T && 3*G <
T) {
772 int64_t R = MIN(E, G);
773 int64_t S =
MAX(E, G);
781 double Rtotal, Stotal;
789 casename =
"Case 2a";
791 if (Rtotal > Stotal) {
793 "Bw Weight Failure for %s: Rtotal %f > Stotal %f. "
794 "G=%"PRId64
" M=%"PRId64
" E=%"PRId64
" D=%"PRId64
796 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
797 casename, Rtotal, Stotal,
800 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
806 "Bw Weight Failure for %s: 3*Rtotal %f > T "
807 "%"PRId64
". G=%"PRId64
" M=%"PRId64
" E=%"PRId64
808 " D=%"PRId64
" T=%"PRId64
". "
809 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
810 casename, Rtotal*3, (
T),
813 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
819 "Bw Weight Failure for %s: 3*Stotal %f > T "
820 "%"PRId64
". G=%"PRId64
" M=%"PRId64
" E=%"PRId64
821 " D=%"PRId64
" T=%"PRId64
". "
822 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
823 casename, Stotal*3, (
T),
826 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
832 "Bw Weight Failure for %s: 3*Mtotal %f < T "
834 "G=%"PRId64
" M=%"PRId64
" E=%"PRId64
" D=%"PRId64
836 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
837 casename, Mtotal*3, (
T),
840 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
844 casename =
"Case 2b";
847 if (D != 0 && 3*M <
T) {
848 casename =
"Case 2b (balanced)";
849 if (fabs(Etotal-Mtotal) > 0.01*
MAX(Etotal,Mtotal)) {
851 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
852 "G=%"PRId64
" M=%"PRId64
" E=%"PRId64
" D=%"PRId64
854 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
855 casename, Etotal, Mtotal,
858 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
861 if (fabs(Etotal-Gtotal) > 0.01*
MAX(Etotal,Gtotal)) {
863 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
864 "G=%"PRId64
" M=%"PRId64
" E=%"PRId64
" D=%"PRId64
866 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
867 casename, Etotal, Gtotal,
870 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
873 if (fabs(Gtotal-Mtotal) > 0.01*
MAX(Gtotal,Mtotal)) {
875 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
876 "G=%"PRId64
" M=%"PRId64
" E=%"PRId64
" D=%"PRId64
878 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
879 casename, Mtotal, Gtotal,
882 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
886 if (fabs(Etotal-Gtotal) > 0.01*
MAX(Etotal,Gtotal)) {
888 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
889 "G=%"PRId64
" M=%"PRId64
" E=%"PRId64
" D=%"PRId64
891 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
892 casename, Etotal, Gtotal,
895 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
901 int64_t S = MIN(E, G);
902 int64_t NS =
MAX(E, G);
907 casename =
"Case 3a (G scarce)";
911 casename =
"Case 3a (E scarce)";
918 "Bw Weight Failure for %s: 3*Stotal %f > T "
919 "%"PRId64
". G=%"PRId64
" M=%"PRId64
" E=%"PRId64
920 " D=%"PRId64
" T=%"PRId64
". "
921 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
922 casename, Stotal*3, (
T),
925 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
929 if (fabs(NStotal-Mtotal) > 0.01*
MAX(NStotal,Mtotal)) {
931 "Bw Weight Failure for %s: NStotal %f != Mtotal %f. "
932 "G=%"PRId64
" M=%"PRId64
" E=%"PRId64
" D=%"PRId64
934 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
935 casename, NStotal, Mtotal,
938 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
945 "Bw Weight Failure for %s: 3*NStotal %f < T "
946 "%"PRId64
". G=%"PRId64
" M=%"PRId64
947 " E=%"PRId64
" D=%"PRId64
" T=%"PRId64
". "
948 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
949 casename, NStotal*3, (
T),
952 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
957 casename =
"Case 3b";
958 if (fabs(Etotal-Mtotal) > 0.01*
MAX(Etotal,Mtotal)) {
960 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
961 "G=%"PRId64
" M=%"PRId64
" E=%"PRId64
" D=%"PRId64
963 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
964 casename, Etotal, Mtotal,
967 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
970 if (fabs(Etotal-Gtotal) > 0.01*
MAX(Etotal,Gtotal)) {
972 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
973 "G=%"PRId64
" M=%"PRId64
" E=%"PRId64
" D=%"PRId64
975 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
976 casename, Etotal, Gtotal,
979 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
982 if (fabs(Gtotal-Mtotal) > 0.01*
MAX(Gtotal,Mtotal)) {
984 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
985 "G=%"PRId64
" M=%"PRId64
" E=%"PRId64
" D=%"PRId64
987 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
988 casename, Mtotal, Gtotal,
991 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
998 log_notice(
LD_DIR,
"Bandwidth-weight %s is verified and valid.",
1026 for (
int i = 0; i < tok->
n_args; i++) {
1038 smartlist_free(chunks);
1047 const char *voter_identity;
1055 if (ns->
type == NS_TYPE_VOTE) {
1056 voter = smartlist_get(ns->
voters, 0);
1062 voter_identity =
"consensus";
1067 if (extract_one_srv(tokens, K_PREVIOUS_SRV, &ns->
sr_info.previous_srv) < 0) {
1068 log_warn(
LD_DIR,
"SR: Unable to parse previous SRV from %s",
1072 if (extract_one_srv(tokens, K_CURRENT_SRV, &ns->
sr_info.current_srv) < 0) {
1073 log_warn(
LD_DIR,
"SR: Unable to parse current SRV from %s",
1088 return tor_strdup(tok->
args[0]);
1096 const char **eos_out,
1100 smartlist_t *rs_tokens = NULL, *footer_tokens = NULL;
1105 const char *cert, *end_of_header, *end_of_footer, *s_dup = s;
1108 int i, inorder, n_signatures = 0;
1109 memarea_t *area = NULL, *rs_area = NULL;
1111 char *last_kwd=NULL;
1112 const char *eos = s + s_len;
1122 log_warn(
LD_DIR,
"Unable to compute digest of network-status");
1127 end_of_header = find_start_of_next_routerstatus(s, eos);
1129 (ns_type == NS_TYPE_CONSENSUS) ?
1130 networkstatus_consensus_token_table :
1131 networkstatus_token_table, 0)) {
1132 log_warn(
LD_DIR,
"Error tokenizing network-status header");
1137 memcpy(&ns->
digests, &ns_digests,
sizeof(ns_digests));
1140 tok = find_by_keyword(tokens, K_NETWORK_STATUS_VERSION);
1145 log_warn(
LD_DIR,
"Can't parse document with unknown flavor %s",
1149 ns->
flavor = flav = flavor;
1151 if (flav != FLAV_NS && ns_type != NS_TYPE_CONSENSUS) {
1152 log_warn(
LD_DIR,
"Flavor found on non-consensus networkstatus.");
1156 if (ns_type != NS_TYPE_CONSENSUS) {
1157 const char *end_of_cert = NULL;
1158 if (!(cert = tor_memstr(s, end_of_header - s,
1159 "\ndir-key-certificate-version")))
1164 if (!ns->
cert || !end_of_cert || end_of_cert > end_of_header)
1168 tok = find_by_keyword(tokens, K_VOTE_STATUS);
1170 if (!strcmp(tok->
args[0],
"vote")) {
1171 ns->
type = NS_TYPE_VOTE;
1172 }
else if (!strcmp(tok->
args[0],
"consensus")) {
1173 ns->
type = NS_TYPE_CONSENSUS;
1174 }
else if (!strcmp(tok->
args[0],
"opinion")) {
1175 ns->
type = NS_TYPE_OPINION;
1177 log_warn(
LD_DIR,
"Unrecognized vote status %s in network-status",
1181 if (ns_type != ns->
type) {
1182 log_warn(
LD_DIR,
"Got the wrong kind of v3 networkstatus.");
1186 if (ns->
type == NS_TYPE_VOTE || ns->
type == NS_TYPE_OPINION) {
1187 tok = find_by_keyword(tokens, K_PUBLISHED);
1194 for (i=0; i < tok->
n_args; ++i)
1213 bool unparseable =
false;
1214 ns->recommended_client_protocols = dup_protocols_string(tokens, &unparseable,
1215 K_RECOMMENDED_CLIENT_PROTOCOLS);
1217 K_RECOMMENDED_RELAY_PROTOCOLS);
1218 ns->required_client_protocols = dup_protocols_string(tokens, &unparseable,
1219 K_REQUIRED_CLIENT_PROTOCOLS);
1220 ns->required_relay_protocols = dup_protocols_string(tokens, &unparseable,
1221 K_REQUIRED_RELAY_PROTOCOLS);
1225 tok = find_by_keyword(tokens, K_VALID_AFTER);
1229 tok = find_by_keyword(tokens, K_FRESH_UNTIL);
1233 tok = find_by_keyword(tokens, K_VALID_UNTIL);
1237 tok = find_by_keyword(tokens, K_VOTING_DELAY);
1253 log_warn(
LD_DIR,
"Vote/consensus freshness interval is too short");
1259 log_warn(
LD_DIR,
"Vote/consensus liveness interval is too short");
1263 log_warn(
LD_DIR,
"Vote seconds is too short");
1267 log_warn(
LD_DIR,
"Dist seconds is too short");
1275 ns->server_versions = tor_strdup(tok->
args[0]);
1285 smartlist_free(package_lst);
1288 tok = find_by_keyword(tokens, K_KNOWN_FLAGS);
1291 for (i = 0; i < tok->
n_args; ++i) {
1293 if (i>0 && strcmp(tok->
args[i-1], tok->
args[i])>= 0) {
1299 log_warn(
LD_DIR,
"known-flags not in order");
1302 if (ns->
type != NS_TYPE_CONSENSUS &&
1309 log_warn(
LD_DIR,
"Too many known-flags in consensus vote or opinion");
1318 for (i = 0; i < tok->
n_args; ++i) {
1320 char *eq = strchr(tok->
args[i],
'=');
1326 eq_pos = eq-tok->
args[i];
1332 if (i > 0 && strcmp(tok->
args[i-1], tok->
args[i]) >= 0) {
1336 if (last_kwd && eq_pos == strlen(last_kwd) &&
1338 log_warn(
LD_DIR,
"Duplicate value for %s parameter",
1343 last_kwd = tor_strndup(tok->
args[i], eq_pos);
1347 log_warn(
LD_DIR,
"params not in order");
1351 log_warn(
LD_DIR,
"Duplicate in parameters");
1360 if (tok->
tp == K_DIR_SOURCE) {
1367 if (ns->
type != NS_TYPE_CONSENSUS)
1375 log_warn(
LD_DIR,
"Error decoding identity digest %s in "
1376 "network-status document.",
escaped(tok->
args[1]));
1379 if (ns->
type != NS_TYPE_CONSENSUS &&
1382 log_warn(
LD_DIR,
"Mismatch between identities in certificate and vote");
1385 if (ns->
type != NS_TYPE_CONSENSUS) {
1387 log_warn(
LD_DIR,
"Rejecting vote signature made with denylisted "
1395 log_warn(
LD_DIR,
"Error decoding IP address %s in network-status.",
1409 }
else if (tok->
tp == K_CONTACT) {
1410 if (!voter || voter->
contact) {
1411 log_warn(
LD_DIR,
"contact element is out of place.");
1415 }
else if (tok->
tp == K_VOTE_DIGEST) {
1419 log_warn(
LD_DIR,
"vote-digest element is out of place.");
1426 log_warn(
LD_DIR,
"Error decoding vote digest %s in "
1427 "network-status consensus.",
escaped(tok->
args[0]));
1431 } SMARTLIST_FOREACH_END(_tok);
1436 if (smartlist_len(ns->
voters) == 0) {
1437 log_warn(
LD_DIR,
"Missing dir-source elements in a networkstatus.");
1439 }
else if (ns->
type != NS_TYPE_CONSENSUS && smartlist_len(ns->
voters) != 1) {
1440 log_warn(
LD_DIR,
"Too many dir-source elements in a vote networkstatus.");
1444 if (ns->
type != NS_TYPE_CONSENSUS &&
1456 log_warn(
LD_DIR,
"Invalid legacy key digest %s on vote.",
1463 if (ns->
type == NS_TYPE_VOTE) {
1464 dirvote_parse_sr_commits(ns, tokens);
1467 if (ns->
type == NS_TYPE_VOTE || ns->
type == NS_TYPE_CONSENSUS) {
1468 extract_shared_random_srvs(ns, tokens);
1477 while (eos - s >= 2 &&
fast_memeq(s,
"r ", 2)) {
1478 if (ns->
type != NS_TYPE_CONSENSUS) {
1480 if (routerstatus_parse_entry_from_string(rs_area, &s, eos, rs_tokens, ns,
1484 vote_routerstatus_free(rs);
1489 if ((rs = routerstatus_parse_entry_from_string(rs_area, &s, eos,
1503 if (ns->
type != NS_TYPE_CONSENSUS) {
1513 log_warn(
LD_DIR,
"Networkstatus entries not sorted by identity digest");
1517 if (ns_type != NS_TYPE_CONSENSUS) {
1518 digest256map_t *ed_id_map = digest256map_new();
1521 if (! vrs->has_ed25519_listing ||
1524 if (digest256map_get(ed_id_map, vrs->ed25519_id) != NULL) {
1525 log_warn(
LD_DIR,
"Vote networkstatus ed25519 identities were not "
1527 digest256map_free(ed_id_map, NULL);
1530 digest256map_set(ed_id_map, vrs->ed25519_id, (
void*)1);
1531 } SMARTLIST_FOREACH_END(vrs);
1532 digest256map_free(ed_id_map, NULL);
1537 if ((end_of_footer = tor_memstr(s, eos-s,
"\nnetwork-status-version ")))
1540 end_of_footer = eos;
1542 networkstatus_vote_footer_token_table, 0)) {
1543 log_warn(
LD_DIR,
"Error tokenizing network-status vote footer.");
1551 if (tok->
tp == K_DIRECTORY_SIGNATURE)
1553 else if (found_sig) {
1554 log_warn(
LD_DIR,
"Extraneous token after first directory-signature");
1557 } SMARTLIST_FOREACH_END(_tok);
1561 if (tok != smartlist_get(footer_tokens, 0)) {
1562 log_warn(
LD_DIR,
"Misplaced directory-footer token");
1570 for (i = 0; i < tok->
n_args; ++i) {
1572 char *eq = strchr(tok->
args[i],
'=');
1574 log_warn(
LD_DIR,
"Bad element '%s' in weight params",
1591 const char *id_hexdigest = NULL;
1592 const char *sk_hexdigest = NULL;
1595 if (tok->
tp != K_DIRECTORY_SIGNATURE)
1599 id_hexdigest = tok->
args[0];
1600 sk_hexdigest = tok->
args[1];
1602 const char *algname = tok->
args[0];
1604 id_hexdigest = tok->
args[1];
1605 sk_hexdigest = tok->
args[2];
1608 log_warn(
LD_DIR,
"Unknown digest algorithm %s; skipping",
1618 log_warn(
LD_DIR,
"Bad object type or length on directory-signature");
1625 !=
sizeof(declared_identity)) {
1626 log_warn(
LD_DIR,
"Error decoding declared identity %s in "
1627 "network-status document.",
escaped(id_hexdigest));
1631 log_warn(
LD_DIR,
"ID on signature on network-status document does "
1632 "not match any declared directory source.");
1642 log_warn(
LD_DIR,
"Error decoding declared signing key digest %s in "
1643 "network-status document.",
escaped(sk_hexdigest));
1648 if (ns->
type != NS_TYPE_CONSENSUS) {
1651 log_warn(
LD_DIR,
"Digest mismatch between declared and actual on "
1652 "network-status vote.");
1661 log_fn(LOG_PROTOCOL_WARN,
LD_DIR,
"We received a networkstatus "
1662 "that contains two signatures from the same voter with the same "
1663 "algorithm. Ignoring the second signature.");
1668 if (ns->
type != NS_TYPE_CONSENSUS) {
1671 "network-status document")) {
1687 } SMARTLIST_FOREACH_END(_tok);
1689 if (! n_signatures) {
1690 log_warn(
LD_DIR,
"No signatures on networkstatus document.");
1692 }
else if (ns->
type == NS_TYPE_VOTE && n_signatures != 1) {
1693 log_warn(
LD_DIR,
"Received more than one signature on a "
1694 "network-status vote.");
1699 *eos_out = end_of_footer;
1704 networkstatus_vote_free(ns);
1709 smartlist_free(tokens);
1714 document_signature_free(sig));
1715 smartlist_free(voter->
sigs);
1724 smartlist_free(rs_tokens);
1726 if (footer_tokens) {
1728 smartlist_free(footer_tokens);
1731 DUMP_AREA(area,
"v3 networkstatus");
#define tor_addr_from_in(dest, in)
int authority_cert_is_denylisted(const authority_cert_t *cert)
Header file for authcert.c.
List of tokens common to V3 authority certificates and V3 consensuses.
authority_cert_t * authority_cert_parse_from_string(const char *s, size_t maxlen, const char **end_of_string)
Header file for authcert_parse.c.
Authority certificate structure.
const char * hex_str(const char *from, size_t fromlen)
int base16_decode(char *dest, size_t destlen, const char *src, size_t srclen)
const or_options_t * get_options(void)
Header file for config.c.
int crypto_digest_algorithm_parse_name(const char *name)
int crypto_digest256(char *digest, const char *m, size_t len, digest_algorithm_t algorithm)
const char * routerstatus_describe(const routerstatus_t *rs)
Header file for describe.c.
#define fast_memeq(a, b, c)
#define fast_memcmp(a, b, c)
#define tor_memneq(a, b, sz)
Header file for dirvote.c.
#define MIN_VOTE_INTERVAL_TESTING
#define MIN_VOTE_INTERVAL
Authority signature structure.
int should_apply_guardfraction(const networkstatus_t *ns)
Header file for circuitbuild.c.
const char * escaped(const char *s)
int tor_inet_aton(const char *str, struct in_addr *addr)
#define log_fn(severity, domain, args,...)
void memarea_clear(memarea_t *area)
memarea_t * memarea_new(void)
#define memarea_drop_all(area)
int networkstatus_parse_flavor_name(const char *flavname)
document_signature_t * networkstatus_get_voter_sig_by_alg(const networkstatus_voter_info_t *voter, digest_algorithm_t alg)
networkstatus_voter_info_t * networkstatus_get_voter_by_id(networkstatus_t *vote, const char *identity)
int32_t networkstatus_get_bw_weight(networkstatus_t *ns, const char *weight_name, int32_t default_val)
int networkstatus_get_weight_scale_param(networkstatus_t *ns)
Header file for networkstatus.c.
Networkstatus consensus/vote structure.
Single consensus voter structure.
int is_legal_nickname(const char *s)
Header file for nickname.c.
Header file for ns_parse.c.
int router_get_networkstatus_v3_sha3_as_signed(uint8_t *digest_out, const char *s, size_t len)
int router_get_networkstatus_v3_signed_boundaries(const char *s, size_t len, const char **start_out, const char **end_out)
networkstatus_t * networkstatus_parse_vote_from_string(const char *s, size_t len, const char **eos_out, enum networkstatus_type_t ns_type)
int networkstatus_verify_bw_weights(networkstatus_t *ns, int)
int router_get_networkstatus_v3_hashes(const char *s, size_t len, common_digests_t *digests)
Master header file for Tor-specific functionality.
#define UNNAMED_ROUTER_NICKNAME
long tor_parse_long(const char *s, int base, long min, long max, int *ok, char **next)
unsigned long tor_parse_ulong(const char *s, int base, unsigned long min, unsigned long max, int *ok, char **next)
void token_clear(directory_token_t *tok)
smartlist_t * find_all_by_keyword(const smartlist_t *s, directory_keyword k)
int tokenize_string(memarea_t *area, const char *start, const char *end, smartlist_t *out, const token_rule_t *table, int flags)
directory_token_t * find_opt_by_keyword(const smartlist_t *s, directory_keyword keyword)
Header file for parsecommon.c.
#define T1_START(s, t, a, o)
int tor_snprintf(char *str, size_t size, const char *format,...)
bool protover_list_is_invalid(const char *s)
Headers and type declarations for protover.c.
int find_single_ipv6_orport(const smartlist_t *list, tor_addr_t *addr_out, uint16_t *port_out)
Header file for routerparse.c.
sr_srv_t * sr_parse_srv(const smartlist_t *args)
Header file for shared_random_client.c.
int check_signature_token(const char *digest, ssize_t digest_len, directory_token_t *tok, crypto_pk_t *pkey, int flags, const char *doctype)
int router_get_hash_impl_helper(const char *s, size_t s_len, const char *start_str, const char *end_str, char end_c, int log_severity, const char **start_out, const char **end_out)
int router_get_hashes_impl(const char *s, size_t s_len, common_digests_t *digests, const char *start_str, const char *end_str, char end_c)
Header file for sigcommon.c.
int smartlist_string_pos(const smartlist_t *sl, const char *element)
void smartlist_add_strdup(struct smartlist_t *sl, const char *string)
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
void smartlist_clear(smartlist_t *sl)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
crypto_pk_t * signing_key
char signing_key_digest[DIGEST_LEN]
signed_descriptor_t cache_info
char d[N_COMMON_DIGEST_ALGORITHMS][DIGEST256_LEN]
unsigned int good_signature
char identity_digest[DIGEST_LEN]
char signing_key_digest[DIGEST_LEN]
smartlist_t * known_flags
char * recommended_relay_protocols
smartlist_t * weight_params
smartlist_t * package_lines
smartlist_t * supported_methods
smartlist_t * routerstatus_list
unsigned int has_measured_bws
networkstatus_sr_info_t sr_info
uint8_t digest_sha3_as_signed[DIGEST256_LEN]
struct authority_cert_t * cert
consensus_flavor_t flavor
networkstatus_type_t type
char legacy_id_digest[DIGEST_LEN]
char identity_digest[DIGEST_LEN]
char vote_digest[DIGEST_LEN]
protover_summary_flags_t pv
unsigned int is_staledesc
char descriptor_digest[DIGEST256_LEN]
unsigned int has_exitsummary
char identity_digest[DIGEST_LEN]
unsigned int has_guardfraction
unsigned int bw_is_unmeasured
char nickname[MAX_NICKNAME_LEN+1]
unsigned int has_bandwidth
unsigned int is_possible_guard
unsigned int is_flagged_running
unsigned int is_middle_only
unsigned int is_authority
uint32_t guardfraction_percentage
char identity_digest[DIGEST_LEN]
struct vote_microdesc_hash_t * next
char * microdesc_hash_line
uint8_t ed25519_id[ED25519_PUBKEY_LEN]
unsigned int has_ed25519_listing
vote_microdesc_hash_t * microdesc
unsigned int has_measured_bw
int parse_iso_time(const char *cp, time_t *t)
void dump_desc(const char *desc, const char *type)
Header file for unparseable.c.
int strcmpstart(const char *s1, const char *s2)
int fast_mem_is_zero(const char *mem, size_t len)
int tor_digest_is_zero(const char *digest)
void summarize_protover_flags(protover_summary_flags_t *out, const char *protocols, const char *version)
Header file for versions.c.
Microdescriptor-hash voting structure.
Routerstatus (vote entry) structure.
#define MAX_KNOWN_FLAGS_IN_VOTE