#include "microdesc.h"
#include "networkstatus.h"
#include "nodelist.h"
+#include "protover.h"
#include "relay.h"
#include "router.h"
#include "routerlist.h"
tor_free(ns->client_versions);
tor_free(ns->server_versions);
+ tor_free(ns->recommended_client_protocols);
+ tor_free(ns->recommended_relay_protocols);
+ tor_free(ns->required_client_protocols);
+ tor_free(ns->required_relay_protocols);
+
if (ns->known_flags) {
SMARTLIST_FOREACH(ns->known_flags, char *, c, tor_free(c));
smartlist_free(ns->known_flags);
return 0;
}
+/** Check whether the networkstatus <b>ns</b> lists any protocol
+ * versions as "required" or "recommended" that we do not support. If
+ * so, set *<b>warning_out</b> to a newly allocated string describing
+ * the problem.
+ *
+ * Return 1 if we should exit, 0 if we should not. */
+int
+networkstatus_check_required_protocols(const networkstatus_t *ns,
+ int client_mode,
+ char **warning_out)
+{
+ const char *func = client_mode ? "client" : "relay";
+ const char *required, *recommended;
+ char *missing = NULL;
+
+ tor_assert(warning_out);
+
+ if (client_mode) {
+ required = ns->required_client_protocols;
+ recommended = ns->recommended_client_protocols;
+ } else {
+ required = ns->required_relay_protocols;
+ recommended = ns->recommended_relay_protocols;
+ }
+
+ if (!protover_all_supported(required, &missing)) {
+ tor_asprintf(warning_out, "At least one protocol listed as required in "
+ "the consensus is not supported by this version of Tor. "
+ "You should upgrade. This version of Tor will not work as a "
+ "%s on the Tor network. The missing protocols are: %s",
+ func, missing);
+ tor_free(missing);
+ return 1;
+ }
+
+ if (! protover_all_supported(recommended, &missing)) {
+ tor_asprintf(warning_out, "At least one protocol listed as recommended in "
+ "the consensus is not supported by this version of Tor. "
+ "You should upgrade. This version of Tor will eventually "
+ "stop working as a %s on the Tor network. The missing "
+ "protocols are: %s",
+ func, missing);
+ tor_free(missing);
+ }
+
+ tor_assert_nonfatal(missing == NULL);
+
+ return 0;
+}
+
/** Free all storage held locally in this module. */
void
networkstatus_free_all(void)
document_signature_t *document_signature_dup(const document_signature_t *sig);
void networkstatus_free_all(void);
int networkstatus_get_weight_scale_param(networkstatus_t *ns);
+int networkstatus_check_required_protocols(const networkstatus_t *ns,
+ int client_mode,
+ char **warning_out);
#ifdef NETWORKSTATUS_PRIVATE
STATIC void vote_routerstatus_free(vote_routerstatus_t *rs);
* voter has no opinion. */
char *client_versions;
char *server_versions;
+
+ /** Lists of subprotocol versions which are _recommended_ for relays and
+ * clients, or which are _require_ for relays and clients. Tor shouldn't
+ * make any more network connections if a required protocol is missing.
+ */
+ char *recommended_relay_protocols;
+ char *recommended_client_protocols;
+ char *required_relay_protocols;
+ char *required_client_protocols;
+
/** List of flags that this vote/consensus applies to routers. If a flag is
* not listed here, the voter has no opinion on what its value should be. */
smartlist_t *known_flags;
K_DIR_OPTIONS,
K_CLIENT_VERSIONS,
K_SERVER_VERSIONS,
+ K_RECOMMENDED_CLIENT_PROTOCOLS,
+ K_RECOMMENDED_RELAY_PROTOCOLS,
+ K_REQUIRED_CLIENT_PROTOCOLS,
+ K_REQUIRED_RELAY_PROTOCOLS,
K_OR_ADDRESS,
K_ID,
K_P,
T01("shared-rand-previous-value", K_PREVIOUS_SRV,EQ(2), NO_OBJ ),
T01("shared-rand-current-value", K_CURRENT_SRV, EQ(2), NO_OBJ ),
T0N("package", K_PACKAGE, CONCAT_ARGS, NO_OBJ ),
+ T01("recommended-client-protocols", K_RECOMMENDED_CLIENT_PROTOCOLS,
+ CONCAT_ARGS, NO_OBJ ),
+ T01("recommended-relay-protocols", K_RECOMMENDED_RELAY_PROTOCOLS,
+ CONCAT_ARGS, NO_OBJ ),
+ T01("required-client-protocols", K_REQUIRED_CLIENT_PROTOCOLS,
+ CONCAT_ARGS, NO_OBJ ),
+ T01("required-relay-protocols", K_REQUIRED_RELAY_PROTOCOLS,
+ CONCAT_ARGS, NO_OBJ ),
CERTIFICATE_MEMBERS
T01("shared-rand-previous-value", K_PREVIOUS_SRV, EQ(2), NO_OBJ ),
T01("shared-rand-current-value", K_CURRENT_SRV, EQ(2), NO_OBJ ),
+ T01("recommended-client-protocols", K_RECOMMENDED_CLIENT_PROTOCOLS,
+ CONCAT_ARGS, NO_OBJ ),
+ T01("recommended-relay-protocols", K_RECOMMENDED_RELAY_PROTOCOLS,
+ CONCAT_ARGS, NO_OBJ ),
+ T01("required-client-protocols", K_REQUIRED_CLIENT_PROTOCOLS,
+ CONCAT_ARGS, NO_OBJ ),
+ T01("required-relay-protocols", K_REQUIRED_RELAY_PROTOCOLS,
+ CONCAT_ARGS, NO_OBJ ),
+
END_OF_TABLE
};
}
}
+ if ((tok = find_opt_by_keyword(tokens, K_RECOMMENDED_CLIENT_PROTOCOLS)))
+ ns->recommended_client_protocols = tor_strdup(tok->args[0]);
+ if ((tok = find_opt_by_keyword(tokens, K_RECOMMENDED_RELAY_PROTOCOLS)))
+ ns->recommended_relay_protocols = tor_strdup(tok->args[0]);
+ if ((tok = find_opt_by_keyword(tokens, K_REQUIRED_CLIENT_PROTOCOLS)))
+ ns->required_client_protocols = tor_strdup(tok->args[0]);
+ if ((tok = find_opt_by_keyword(tokens, K_REQUIRED_RELAY_PROTOCOLS)))
+ ns->required_relay_protocols = tor_strdup(tok->args[0]);
+
tok = find_by_keyword(tokens, K_VALID_AFTER);
if (parse_iso_time(tok->args[0], &ns->valid_after))
goto err;