Refactor node lookup APIs to take flags

Right now there's a single warn_if_unnamed flag for
router_get_consensus_status_by_nickname() and
node_get_by_nickname(), that is nearly always 1.  I've turned it
into an 'unsigned' bitfield, and inverted its sense.  I've added the
flags argument to node_get_by_hex_id() too, though it does nothing
there right now.

I've removed the router_get_consensus_status_by_nickname() function,
since it was only used in once place.

This patch changes the warning behavior of GETINFO ns/name/<name>,
since all other name lookups from the controller currently warn.

Later I'm going to add more flags, for ed25519 support.
This commit is contained in:
Nick Mathewson 2017-08-22 19:04:31 -04:00
parent d7a3e336ee
commit 80d3887360
12 changed files with 49 additions and 57 deletions

View File

@ -214,7 +214,7 @@ addressmap_clear_excluded_trackexithosts(const or_options_t *options)
dot--; dot--;
if (*dot == '.') dot++; if (*dot == '.') dot++;
nodename = tor_strndup(dot, len-5-(dot-target));; nodename = tor_strndup(dot, len-5-(dot-target));;
node = node_get_by_nickname(nodename, 0); node = node_get_by_nickname(nodename, NNF_NO_WARN_UNNAMED);
tor_free(nodename); tor_free(nodename);
if (!node || if (!node ||
(allow_nodes && !routerset_contains_node(allow_nodes, node)) || (allow_nodes && !routerset_contains_node(allow_nodes, node)) ||

View File

@ -2119,7 +2119,7 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
} else { } else {
/* XXXX Duplicates checks in connection_ap_handshake_attach_circuit: /* XXXX Duplicates checks in connection_ap_handshake_attach_circuit:
* refactor into a single function. */ * refactor into a single function. */
const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 1); const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 0);
int opt = conn->chosen_exit_optional; int opt = conn->chosen_exit_optional;
if (node && !connection_ap_can_use_exit(conn, node)) { if (node && !connection_ap_can_use_exit(conn, node)) {
log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP, log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
@ -2199,7 +2199,7 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
if (conn->chosen_exit_name) { if (conn->chosen_exit_name) {
const node_t *r; const node_t *r;
int opt = conn->chosen_exit_optional; int opt = conn->chosen_exit_optional;
r = node_get_by_nickname(conn->chosen_exit_name, 1); r = node_get_by_nickname(conn->chosen_exit_name, 0);
if (r && node_has_descriptor(r)) { if (r && node_has_descriptor(r)) {
/* We might want to connect to an IPv6 bridge for loading /* We might want to connect to an IPv6 bridge for loading
descriptors so we use the preferred address rather than descriptors so we use the preferred address rather than
@ -2598,7 +2598,7 @@ connection_ap_handshake_attach_circuit(entry_connection_t *conn)
* open to that exit. See what exit we meant, and whether we can use it. * open to that exit. See what exit we meant, and whether we can use it.
*/ */
if (conn->chosen_exit_name) { if (conn->chosen_exit_name) {
const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 1); const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 0);
int opt = conn->chosen_exit_optional; int opt = conn->chosen_exit_optional;
if (!node && !want_onehop) { if (!node && !want_onehop) {
/* We ran into this warning when trying to extend a circuit to a /* We ran into this warning when trying to extend a circuit to a

View File

@ -1074,7 +1074,8 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info)
if (!entry_conn->chosen_exit_optional && if (!entry_conn->chosen_exit_optional &&
!entry_conn->chosen_exit_retries) !entry_conn->chosen_exit_retries)
continue; continue;
r1 = node_get_by_nickname(entry_conn->chosen_exit_name, 0); r1 = node_get_by_nickname(entry_conn->chosen_exit_name,
NNF_NO_WARN_UNNAMED);
r2 = node_get_by_id(info->identity_digest); r2 = node_get_by_id(info->identity_digest);
if (!r1 || !r2 || r1 != r2) if (!r1 || !r2 || r1 != r2)
continue; continue;
@ -1508,7 +1509,7 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
if (s[1] != '\0') { if (s[1] != '\0') {
/* Looks like a real .exit one. */ /* Looks like a real .exit one. */
conn->chosen_exit_name = tor_strdup(s+1); conn->chosen_exit_name = tor_strdup(s+1);
node = node_get_by_nickname(conn->chosen_exit_name, 1); node = node_get_by_nickname(conn->chosen_exit_name, 0);
if (exit_source == ADDRMAPSRC_TRACKEXIT) { if (exit_source == ADDRMAPSRC_TRACKEXIT) {
/* We 5 tries before it expires the addressmap */ /* We 5 tries before it expires the addressmap */
@ -1529,7 +1530,7 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
* form that means (foo's address).foo.exit. */ * form that means (foo's address).foo.exit. */
conn->chosen_exit_name = tor_strdup(socks->address); conn->chosen_exit_name = tor_strdup(socks->address);
node = node_get_by_nickname(conn->chosen_exit_name, 1); node = node_get_by_nickname(conn->chosen_exit_name, 0);
if (node) { if (node) {
*socks->address = 0; *socks->address = 0;
node_get_address_string(node, socks->address, sizeof(socks->address)); node_get_address_string(node, socks->address, sizeof(socks->address));
@ -3630,7 +3631,7 @@ connection_ap_can_use_exit(const entry_connection_t *conn,
*/ */
if (conn->chosen_exit_name) { if (conn->chosen_exit_name) {
const node_t *chosen_exit = const node_t *chosen_exit =
node_get_by_nickname(conn->chosen_exit_name, 1); node_get_by_nickname(conn->chosen_exit_name, 0);
if (!chosen_exit || tor_memneq(chosen_exit->identity, if (!chosen_exit || tor_memneq(chosen_exit->identity,
exit_node->identity, DIGEST_LEN)) { exit_node->identity, DIGEST_LEN)) {
/* doesn't match */ /* doesn't match */

View File

@ -1886,7 +1886,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
(void) control_conn; (void) control_conn;
if (!strcmpstart(question, "desc/id/")) { if (!strcmpstart(question, "desc/id/")) {
const routerinfo_t *ri = NULL; const routerinfo_t *ri = NULL;
const node_t *node = node_get_by_hex_id(question+strlen("desc/id/")); const node_t *node = node_get_by_hex_id(question+strlen("desc/id/"), 0);
if (node) if (node)
ri = node->ri; ri = node->ri;
if (ri) { if (ri) {
@ -1905,7 +1905,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
/* XXX Setting 'warn_if_unnamed' here is a bit silly -- the /* XXX Setting 'warn_if_unnamed' here is a bit silly -- the
* warning goes to the user, not to the controller. */ * warning goes to the user, not to the controller. */
const node_t *node = const node_t *node =
node_get_by_nickname(question+strlen("desc/name/"), 1); node_get_by_nickname(question+strlen("desc/name/"), 0);
if (node) if (node)
ri = node->ri; ri = node->ri;
if (ri) { if (ri) {
@ -1991,7 +1991,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
return -1; return -1;
} }
} else if (!strcmpstart(question, "md/id/")) { } else if (!strcmpstart(question, "md/id/")) {
const node_t *node = node_get_by_hex_id(question+strlen("md/id/")); const node_t *node = node_get_by_hex_id(question+strlen("md/id/"), 0);
const microdesc_t *md = NULL; const microdesc_t *md = NULL;
if (node) md = node->md; if (node) md = node->md;
if (md && md->body) { if (md && md->body) {
@ -2000,7 +2000,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
} else if (!strcmpstart(question, "md/name/")) { } else if (!strcmpstart(question, "md/name/")) {
/* XXX Setting 'warn_if_unnamed' here is a bit silly -- the /* XXX Setting 'warn_if_unnamed' here is a bit silly -- the
* warning goes to the user, not to the controller. */ * warning goes to the user, not to the controller. */
const node_t *node = node_get_by_nickname(question+strlen("md/name/"), 1); const node_t *node = node_get_by_nickname(question+strlen("md/name/"), 0);
/* XXXX duplicated code */ /* XXXX duplicated code */
const microdesc_t *md = NULL; const microdesc_t *md = NULL;
if (node) md = node->md; if (node) md = node->md;
@ -2013,7 +2013,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
} else if (!strcmpstart(question, "desc-annotations/id/")) { } else if (!strcmpstart(question, "desc-annotations/id/")) {
const routerinfo_t *ri = NULL; const routerinfo_t *ri = NULL;
const node_t *node = const node_t *node =
node_get_by_hex_id(question+strlen("desc-annotations/id/")); node_get_by_hex_id(question+strlen("desc-annotations/id/"), 0);
if (node) if (node)
ri = node->ri; ri = node->ri;
if (ri) { if (ri) {
@ -3394,7 +3394,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
nodes = smartlist_new(); nodes = smartlist_new();
SMARTLIST_FOREACH_BEGIN(router_nicknames, const char *, n) { SMARTLIST_FOREACH_BEGIN(router_nicknames, const char *, n) {
const node_t *node = node_get_by_nickname(n, 1); const node_t *node = node_get_by_nickname(n, 0);
if (!node) { if (!node) {
connection_printf_to_buf(conn, "552 No such router \"%s\"\r\n", n); connection_printf_to_buf(conn, "552 No such router \"%s\"\r\n", n);
goto done; goto done;
@ -4158,7 +4158,7 @@ handle_control_hsfetch(control_connection_t *conn, uint32_t len,
const char *server; const char *server;
server = arg + strlen(opt_server); server = arg + strlen(opt_server);
node = node_get_by_hex_id(server); node = node_get_by_hex_id(server, 0);
if (!node) { if (!node) {
connection_printf_to_buf(conn, "552 Server \"%s\" not found\r\n", connection_printf_to_buf(conn, "552 Server \"%s\" not found\r\n",
server); server);
@ -4239,7 +4239,7 @@ handle_control_hspost(control_connection_t *conn,
SMARTLIST_FOREACH_BEGIN(args, const char *, arg) { SMARTLIST_FOREACH_BEGIN(args, const char *, arg) {
if (!strcasecmpstart(arg, opt_server)) { if (!strcasecmpstart(arg, opt_server)) {
const char *server = arg + strlen(opt_server); const char *server = arg + strlen(opt_server);
const node_t *node = node_get_by_hex_id(server); const node_t *node = node_get_by_hex_id(server, 0);
if (!node || !node->rs) { if (!node || !node->rs) {
connection_printf_to_buf(conn, "552 Server \"%s\" not found\r\n", connection_printf_to_buf(conn, "552 Server \"%s\" not found\r\n",

View File

@ -794,21 +794,6 @@ router_get_consensus_status_by_id(const char *digest)
return router_get_mutable_consensus_status_by_id(digest); return router_get_mutable_consensus_status_by_id(digest);
} }
/** Given a nickname (possibly verbose, possibly a hexadecimal digest), return
* the corresponding routerstatus_t, or NULL if none exists. Warn the
* user if <b>warn_if_unnamed</b> is set, and they have specified a router by
* nickname, but the Named flag isn't set for that router. */
const routerstatus_t *
router_get_consensus_status_by_nickname(const char *nickname,
int warn_if_unnamed)
{
const node_t *node = node_get_by_nickname(nickname, warn_if_unnamed);
if (node)
return node->rs;
else
return NULL;
}
/** Return the identity digest that's mapped to officially by /** Return the identity digest that's mapped to officially by
* <b>nickname</b>. */ * <b>nickname</b>. */
const char * const char *
@ -2555,7 +2540,8 @@ getinfo_helper_networkstatus(control_connection_t *conn,
} }
status = router_get_consensus_status_by_id(d); status = router_get_consensus_status_by_id(d);
} else if (!strcmpstart(question, "ns/name/")) { } else if (!strcmpstart(question, "ns/name/")) {
status = router_get_consensus_status_by_nickname(question+8, 0); const node_t *n = node_get_by_nickname(question+8, 0);
status = n ? n->rs : NULL;
} else if (!strcmpstart(question, "ns/purpose/")) { } else if (!strcmpstart(question, "ns/purpose/")) {
*answer = networkstatus_getinfo_by_purpose(question+11, time(NULL)); *answer = networkstatus_getinfo_by_purpose(question+11, time(NULL));
return *answer ? 0 : -1; return *answer ? 0 : -1;

View File

@ -62,9 +62,6 @@ const routerstatus_t *router_get_consensus_status_by_descriptor_digest(
MOCK_DECL(routerstatus_t *, MOCK_DECL(routerstatus_t *,
router_get_mutable_consensus_status_by_descriptor_digest, router_get_mutable_consensus_status_by_descriptor_digest,
(networkstatus_t *consensus, const char *digest)); (networkstatus_t *consensus, const char *digest));
const routerstatus_t *router_get_consensus_status_by_nickname(
const char *nickname,
int warn_if_unnamed);
const char *networkstatus_get_router_digest_by_nickname(const char *nickname); const char *networkstatus_get_router_digest_by_nickname(const char *nickname);
int networkstatus_nickname_is_unnamed(const char *nickname); int networkstatus_nickname_is_unnamed(const char *nickname);
int we_want_to_fetch_flavor(const or_options_t *options, int flavor); int we_want_to_fetch_flavor(const or_options_t *options, int flavor);

View File

@ -762,14 +762,16 @@ nodelist_get_list,(void))
/** Given a hex-encoded nickname of the format DIGEST, $DIGEST, $DIGEST=name, /** Given a hex-encoded nickname of the format DIGEST, $DIGEST, $DIGEST=name,
* or $DIGEST~name, return the node with the matching identity digest and * or $DIGEST~name, return the node with the matching identity digest and
* nickname (if any). Return NULL if no such node exists, or if <b>hex_id</b> * nickname (if any). Return NULL if no such node exists, or if <b>hex_id</b>
* is not well-formed. */ * is not well-formed. DOCDOC flags */
const node_t * const node_t *
node_get_by_hex_id(const char *hex_id) node_get_by_hex_id(const char *hex_id, unsigned flags)
{ {
char digest_buf[DIGEST_LEN]; char digest_buf[DIGEST_LEN];
char nn_buf[MAX_NICKNAME_LEN+1]; char nn_buf[MAX_NICKNAME_LEN+1];
char nn_char='\0'; char nn_char='\0';
(void) flags; // XXXX
if (hex_digest_nickname_decode(hex_id, digest_buf, &nn_char, nn_buf)==0) { if (hex_digest_nickname_decode(hex_id, digest_buf, &nn_char, nn_buf)==0) {
const node_t *node = node_get_by_id(digest_buf); const node_t *node = node_get_by_id(digest_buf);
if (!node) if (!node)
@ -785,19 +787,21 @@ node_get_by_hex_id(const char *hex_id)
} }
/** Given a nickname (possibly verbose, possibly a hexadecimal digest), return /** Given a nickname (possibly verbose, possibly a hexadecimal digest), return
* the corresponding node_t, or NULL if none exists. Warn the user if * the corresponding node_t, or NULL if none exists. Warn the user if they
* <b>warn_if_unnamed</b> is set, and they have specified a router by * have specified a router by nickname, unless the NNF_NO_WARN_UNNAMED bit is
* nickname, but the Named flag isn't set for that router. */ * set in <b>flags</b>. */
MOCK_IMPL(const node_t *, MOCK_IMPL(const node_t *,
node_get_by_nickname,(const char *nickname, int warn_if_unnamed)) node_get_by_nickname,(const char *nickname, unsigned flags))
{ {
const int warn_if_unnamed = !(flags & NNF_NO_WARN_UNNAMED);
if (!the_nodelist) if (!the_nodelist)
return NULL; return NULL;
/* Handle these cases: DIGEST, $DIGEST, $DIGEST=name, $DIGEST~name. */ /* Handle these cases: DIGEST, $DIGEST, $DIGEST=name, $DIGEST~name. */
{ {
const node_t *node; const node_t *node;
if ((node = node_get_by_hex_id(nickname)) != NULL) if ((node = node_get_by_hex_id(nickname, flags)) != NULL)
return node; return node;
} }
@ -1719,7 +1723,7 @@ nodelist_add_node_and_family(smartlist_t *sl, const node_t *node)
SMARTLIST_FOREACH_BEGIN(declared_family, const char *, name) { SMARTLIST_FOREACH_BEGIN(declared_family, const char *, name) {
const node_t *node2; const node_t *node2;
const smartlist_t *family2; const smartlist_t *family2;
if (!(node2 = node_get_by_nickname(name, 0))) if (!(node2 = node_get_by_nickname(name, NNF_NO_WARN_UNNAMED)))
continue; continue;
if (!(family2 = node_get_declared_family(node2))) if (!(family2 = node_get_declared_family(node2)))
continue; continue;

View File

@ -21,7 +21,11 @@ MOCK_DECL(const node_t *, node_get_by_id, (const char *identity_digest));
node_t *node_get_mutable_by_ed25519_id(const ed25519_public_key_t *ed_id); node_t *node_get_mutable_by_ed25519_id(const ed25519_public_key_t *ed_id);
MOCK_DECL(const node_t *, node_get_by_ed25519_id, MOCK_DECL(const node_t *, node_get_by_ed25519_id,
(const ed25519_public_key_t *ed_id)); (const ed25519_public_key_t *ed_id));
const node_t *node_get_by_hex_id(const char *identity_digest);
#define NNF_NO_WARN_UNNAMED (1u<<0)
const node_t *node_get_by_hex_id(const char *identity_digest,
unsigned flags);
node_t *nodelist_set_routerinfo(routerinfo_t *ri, routerinfo_t **ri_old_out); node_t *nodelist_set_routerinfo(routerinfo_t *ri, routerinfo_t **ri_old_out);
node_t *nodelist_add_microdesc(microdesc_t *md); node_t *nodelist_add_microdesc(microdesc_t *md);
void nodelist_set_consensus(networkstatus_t *ns); void nodelist_set_consensus(networkstatus_t *ns);
@ -35,7 +39,7 @@ void nodelist_free_all(void);
void nodelist_assert_ok(void); void nodelist_assert_ok(void);
MOCK_DECL(const node_t *, node_get_by_nickname, MOCK_DECL(const node_t *, node_get_by_nickname,
(const char *nickname, int warn_if_unnamed)); (const char *nickname, unsigned flags));
void node_get_verbose_nickname(const node_t *node, void node_get_verbose_nickname(const node_t *node,
char *verbose_name_out); char *verbose_name_out);
void node_get_verbose_nickname_by_id(const char *id_digest, void node_get_verbose_nickname_by_id(const char *id_digest,

View File

@ -2112,7 +2112,7 @@ find_rp_for_intro(const rend_intro_cell_t *intro,
if (intro->version == 0 || intro->version == 1) { if (intro->version == 0 || intro->version == 1) {
rp_nickname = (const char *)(intro->u.v0_v1.rp); rp_nickname = (const char *)(intro->u.v0_v1.rp);
node = node_get_by_nickname(rp_nickname, 0); node = node_get_by_nickname(rp_nickname, NNF_NO_WARN_UNNAMED);
if (!node) { if (!node) {
if (err_msg_out) { if (err_msg_out) {
tor_asprintf(&err_msg, tor_asprintf(&err_msg,

View File

@ -2279,7 +2279,7 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e)
if (!strcasecmp(name, options->Nickname)) if (!strcasecmp(name, options->Nickname))
continue; /* Don't list ourself, that's redundant */ continue; /* Don't list ourself, that's redundant */
else else
member = node_get_by_nickname(name, 1); member = node_get_by_nickname(name, 0);
if (!member) { if (!member) {
int is_legal = is_legal_nickname_or_hexdigest(name); int is_legal = is_legal_nickname_or_hexdigest(name);
if (!smartlist_contains_string(warned_nonexistent_family, name) && if (!smartlist_contains_string(warned_nonexistent_family, name) &&

View File

@ -362,7 +362,7 @@ routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset,
/* No routers are specified by type; all are given by name or digest. /* No routers are specified by type; all are given by name or digest.
* we can do a lookup in O(len(routerset)). */ * we can do a lookup in O(len(routerset)). */
SMARTLIST_FOREACH(routerset->list, const char *, name, { SMARTLIST_FOREACH(routerset->list, const char *, name, {
const node_t *node = node_get_by_nickname(name, 1); const node_t *node = node_get_by_nickname(name, 0);
if (node) { if (node) {
if (!running_only || node->is_running) if (!running_only || node->is_running)
if (!routerset_contains_node(excludeset, node)) if (!routerset_contains_node(excludeset, node))

View File

@ -1602,7 +1602,7 @@ NS(test_main)(void *arg)
*/ */
NS_DECL(const node_t *, node_get_by_nickname, NS_DECL(const node_t *, node_get_by_nickname,
(const char *nickname, int warn_if_unused)); (const char *nickname, unsigned flags));
static const char *NS(mock_nickname); static const char *NS(mock_nickname);
static void static void
@ -1632,11 +1632,11 @@ NS(test_main)(void *arg)
} }
const node_t * const node_t *
NS(node_get_by_nickname)(const char *nickname, int warn_if_unused) NS(node_get_by_nickname)(const char *nickname, unsigned flags)
{ {
CALLED(node_get_by_nickname)++; CALLED(node_get_by_nickname)++;
tt_str_op(nickname, OP_EQ, NS(mock_nickname)); tt_str_op(nickname, OP_EQ, NS(mock_nickname));
tt_int_op(warn_if_unused, OP_EQ, 1); tt_uint_op(flags, OP_EQ, 0);
done: done:
return NULL; return NULL;
@ -1651,7 +1651,7 @@ NS(node_get_by_nickname)(const char *nickname, int warn_if_unused)
*/ */
NS_DECL(const node_t *, node_get_by_nickname, NS_DECL(const node_t *, node_get_by_nickname,
(const char *nickname, int warn_if_unused)); (const char *nickname, unsigned flags));
static const char *NS(mock_nickname); static const char *NS(mock_nickname);
static node_t NS(mock_node); static node_t NS(mock_node);
@ -1683,11 +1683,11 @@ NS(test_main)(void *arg)
} }
const node_t * const node_t *
NS(node_get_by_nickname)(const char *nickname, int warn_if_unused) NS(node_get_by_nickname)(const char *nickname, unsigned flags)
{ {
CALLED(node_get_by_nickname)++; CALLED(node_get_by_nickname)++;
tt_str_op(nickname, OP_EQ, NS(mock_nickname)); tt_str_op(nickname, OP_EQ, NS(mock_nickname));
tt_int_op(warn_if_unused, OP_EQ, 1); tt_int_op(flags, OP_EQ, 0);
done: done:
return &NS(mock_node); return &NS(mock_node);
@ -1701,7 +1701,7 @@ NS(node_get_by_nickname)(const char *nickname, int warn_if_unused)
*/ */
NS_DECL(const node_t *, node_get_by_nickname, NS_DECL(const node_t *, node_get_by_nickname,
(const char *nickname, int warn_if_unused)); (const char *nickname, unsigned flags));
static char *NS(mock_nickname); static char *NS(mock_nickname);
static node_t NS(mock_node); static node_t NS(mock_node);
@ -1735,11 +1735,11 @@ NS(test_main)(void *arg)
} }
const node_t * const node_t *
NS(node_get_by_nickname)(const char *nickname, int warn_if_unused) NS(node_get_by_nickname)(const char *nickname, unsigned flags)
{ {
CALLED(node_get_by_nickname)++; CALLED(node_get_by_nickname)++;
tt_str_op(nickname, OP_EQ, NS(mock_nickname)); tt_str_op(nickname, OP_EQ, NS(mock_nickname));
tt_int_op(warn_if_unused, OP_EQ, 1); tt_int_op(flags, OP_EQ, 0);
done: done:
return &NS(mock_node); return &NS(mock_node);