mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 13:13:44 +01:00
Implement node-based router family code
Also, make the NodeFamily option into a list of routersets. This lets us git rid of router_in_nickname_list (or whatever it was called) without porting it to work with nodes, and also lets people specify country codes and IP ranges in NodeFamily
This commit is contained in:
parent
45f1e4d5ee
commit
f9ea242aca
4
doc/nodefamily_routerset
Normal file
4
doc/nodefamily_routerset
Normal file
@ -0,0 +1,4 @@
|
||||
o Minor features
|
||||
- The NodeFamily option -- which let you declare that you want to
|
||||
consider nodes to be part of a family whether they list themselves
|
||||
that way or not -- now allows IP address ranges and country codes.
|
@ -571,7 +571,8 @@ The following options are useful only for clients (that is, if
|
||||
constitute a "family" of similar or co-administered servers, so never use
|
||||
any two of them in the same circuit. Defining a NodeFamily is only needed
|
||||
when a server doesn't list the family itself (with MyFamily). This option
|
||||
can be used multiple times.
|
||||
can be used multiple times. In addition to nodes, you can also list
|
||||
IP address and ranges and country codes in {curly braces}.
|
||||
|
||||
**EnforceDistinctSubnets** **0**|**1**::
|
||||
If 1, Tor will not put two servers whose IP addresses are "too close" on
|
||||
|
@ -691,6 +691,11 @@ or_options_free(or_options_t *options)
|
||||
return;
|
||||
|
||||
routerset_free(options->_ExcludeExitNodesUnion);
|
||||
if (options->NodeFamilySets) {
|
||||
SMARTLIST_FOREACH(options->NodeFamilySets, routerset_t *,
|
||||
rs, routerset_free(rs));
|
||||
smartlist_free(options->NodeFamilySets);
|
||||
}
|
||||
config_free(&options_format, options);
|
||||
}
|
||||
|
||||
@ -3084,6 +3089,18 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeNodes);
|
||||
}
|
||||
|
||||
if (options->NodeFamilies) {
|
||||
options->NodeFamilySets = smartlist_create();
|
||||
for (cl = options->NodeFamilies; cl; cl = cl->next) {
|
||||
routerset_t *rs = routerset_new();
|
||||
if (routerset_parse(rs, cl->value, cl->key) == 0) {
|
||||
smartlist_add(options->NodeFamilySets, rs);
|
||||
} else {
|
||||
routerset_free(rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options->ExcludeNodes && options->StrictNodes) {
|
||||
COMPLAIN("You have asked to exclude certain relays from all positions "
|
||||
"in your circuits. Expect hidden services and other Tor "
|
||||
@ -3549,8 +3566,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
if (check_nickname_list(options->MyFamily, "MyFamily", msg))
|
||||
return -1;
|
||||
for (cl = options->NodeFamilies; cl; cl = cl->next) {
|
||||
if (check_nickname_list(cl->value, "NodeFamily", msg))
|
||||
routerset_t *rs = routerset_new();
|
||||
if (routerset_parse(rs, cl->value, cl->key)) {
|
||||
routerset_free(rs);
|
||||
return -1;
|
||||
}
|
||||
routerset_free(rs);
|
||||
}
|
||||
|
||||
if (validate_addr_policies(options, msg) < 0)
|
||||
|
@ -698,6 +698,19 @@ node_is_me(const node_t *node)
|
||||
return router_digest_is_me(node->identity);
|
||||
}
|
||||
|
||||
/** Return <b>node</b> declared family (as a list of names), or NULL if
|
||||
* the node didn't declare a family. */
|
||||
const smartlist_t *
|
||||
node_get_declared_family(const node_t *node)
|
||||
{
|
||||
if (node->ri && node->ri->declared_family)
|
||||
return node->ri->declared_family;
|
||||
else if (node->md && node->md->family)
|
||||
return node->md->family;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* KILLTHIS XXXX NM -- it's a dummy to keep UNIMPLEMENTED_NODELIST()
|
||||
* working */
|
||||
int unimplemented_nodelist_truth = 1;
|
||||
|
@ -45,6 +45,7 @@ const char *node_get_platform(const node_t *node);
|
||||
void node_get_address_string(const node_t *node, char *cp, size_t len);
|
||||
long node_get_declared_uptime(const node_t *node);
|
||||
time_t node_get_published_on(const node_t *node);
|
||||
const smartlist_t *node_get_declared_family(const node_t *node);
|
||||
|
||||
smartlist_t *nodelist_get_list(void);
|
||||
|
||||
|
@ -2725,7 +2725,8 @@ typedef struct {
|
||||
|
||||
char *MyFamily; /**< Declared family for this OR. */
|
||||
config_line_t *NodeFamilies; /**< List of config lines for
|
||||
* node families */
|
||||
* node families */
|
||||
smartlist_t *NodeFamilySets; /**< List of parsed NodeFamilies values. */
|
||||
config_line_t *AuthDirBadDir; /**< Address policy for descriptors to
|
||||
* mark as bad dir mirrors. */
|
||||
config_line_t *AuthDirBadExit; /**< Address policy for descriptors to
|
||||
|
@ -46,6 +46,8 @@ static const routerstatus_t *router_pick_trusteddirserver_impl(
|
||||
static void mark_all_trusteddirservers_up(void);
|
||||
static int router_nickname_matches(const routerinfo_t *router,
|
||||
const char *nickname);
|
||||
static int node_nickname_matches(const node_t *router,
|
||||
const char *nickname);
|
||||
static void trusted_dir_server_free(trusted_dir_server_t *ds);
|
||||
static int signed_desc_digest_is_recognized(signed_descriptor_t *desc);
|
||||
static void update_router_have_minimum_dir_info(void);
|
||||
@ -1300,72 +1302,70 @@ router_reset_status_download_failures(void)
|
||||
mark_all_trusteddirservers_up();
|
||||
}
|
||||
|
||||
/** Return true iff router1 and router2 have the same /16 network. */
|
||||
/** Return true iff router1 and router2 have similar enough network addresses
|
||||
* that we should treat them as being in the same family */
|
||||
static INLINE int
|
||||
routers_in_same_network_family(const routerinfo_t *r1, const routerinfo_t *r2)
|
||||
addrs_in_same_network_family(const tor_addr_t *a1,
|
||||
const tor_addr_t *a2)
|
||||
{
|
||||
return (r1->addr & 0xffff0000) == (r2->addr & 0xffff0000);
|
||||
/* XXXX MOVE ? */
|
||||
return 0 == tor_addr_compare_masked(a1, a2, 16, CMP_SEMANTIC);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/** Look through the routerlist and identify routers that
|
||||
* advertise the same /16 network address as <b>router</b>.
|
||||
* Add each of them to <b>sl</b>.
|
||||
*/
|
||||
static void
|
||||
routerlist_add_network_family(smartlist_t *sl, const routerinfo_t *router)
|
||||
{
|
||||
SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, r,
|
||||
{
|
||||
if (router != r && routers_in_same_network_family(router, r))
|
||||
smartlist_add(sl, r);
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Add all the family of <b>router</b> to the smartlist <b>sl</b>.
|
||||
* This is used to make sure we don't pick siblings in a single path,
|
||||
* or pick more than one relay from a family for our entry guard list.
|
||||
*/
|
||||
void
|
||||
nodelist_add_node_family(smartlist_t *sl, const node_t *router)
|
||||
nodelist_add_node_family(smartlist_t *sl, const node_t *node)
|
||||
{
|
||||
/* XXXX MOVE */
|
||||
#if 0
|
||||
const routerinfo_t *r;
|
||||
config_line_t *cl;
|
||||
const smartlist_t *all_nodes = nodelist_get_list();
|
||||
const smartlist_t *declared_family = node_get_declared_family(node);
|
||||
or_options_t *options = get_options();
|
||||
|
||||
/* First, add any routers with similar network addresses. */
|
||||
if (options->EnforceDistinctSubnets)
|
||||
routerlist_add_network_family(sl, router);
|
||||
/* First, add any nodes with similar network addresses. */
|
||||
if (options->EnforceDistinctSubnets) {
|
||||
tor_addr_t node_addr;
|
||||
node_get_addr(node, &node_addr);
|
||||
|
||||
if (router->declared_family) {
|
||||
/* Add every r such that router declares familyness with r, and r
|
||||
SMARTLIST_FOREACH_BEGIN(all_nodes, const node_t *, node2) {
|
||||
tor_addr_t a;
|
||||
node_get_addr(node2, &a);
|
||||
if (addrs_in_same_network_family(&a, &node_addr))
|
||||
smartlist_add(sl, (void*)node2);
|
||||
} SMARTLIST_FOREACH_END(node);
|
||||
}
|
||||
|
||||
/* Now, add all nodes in the declared_family of this node, if they
|
||||
* also declare this node to be in their family. */
|
||||
if (declared_family) {
|
||||
/* Add every r such that router declares familyness with node, and node
|
||||
* declares familyhood with router. */
|
||||
SMARTLIST_FOREACH_BEGIN(router->declared_family, const char *, n) {
|
||||
if (!(r = router_get_by_nickname(n, 0)))
|
||||
continue;
|
||||
if (!r->declared_family)
|
||||
continue;
|
||||
SMARTLIST_FOREACH(r->declared_family, const char *, n2,
|
||||
{
|
||||
if (router_nickname_matches(router, n2))
|
||||
smartlist_add(sl, (void*)r);
|
||||
});
|
||||
} SMARTLIST_FOREACH_END(n);
|
||||
SMARTLIST_FOREACH_BEGIN(declared_family, const char *, name) {
|
||||
const node_t *node2;
|
||||
const smartlist_t *family2;
|
||||
if (!(node2 = node_get_by_nickname(name, 0)))
|
||||
continue;
|
||||
if (!(family2 = node_get_declared_family(node2)))
|
||||
continue;
|
||||
SMARTLIST_FOREACH(family2, const char *, name2, {
|
||||
if (node_nickname_matches(node, name2)) {
|
||||
smartlist_add(sl, (void*)node2);
|
||||
break;
|
||||
}
|
||||
});
|
||||
} SMARTLIST_FOREACH_END(name);
|
||||
}
|
||||
|
||||
/* If the user declared any families locally, honor those too. */
|
||||
for (cl = options->NodeFamilies; cl; cl = cl->next) {
|
||||
if (router_nickname_is_in_list(router, cl->value)) {
|
||||
add_nickname_list_to_smartlist(sl, cl->value, 0);
|
||||
}
|
||||
if (options->NodeFamilySets) {
|
||||
SMARTLIST_FOREACH(options->NodeFamilySets, const routerset_t *, rs, {
|
||||
if (routerset_contains_node(rs, node)) {
|
||||
routerset_get_all_nodes(sl, rs, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
#endif
|
||||
(void)sl;
|
||||
(void)router;
|
||||
UNIMPLEMENTED_NODELIST();
|
||||
}
|
||||
|
||||
/** Given a <b>router</b>, add every node_t in its family to <b>sl</b>.
|
||||
@ -1376,19 +1376,28 @@ nodelist_add_node_family(smartlist_t *sl, const node_t *router)
|
||||
static void
|
||||
routerlist_add_nodes_in_family(smartlist_t *sl, const routerinfo_t *router)
|
||||
{
|
||||
(void)router;
|
||||
(void)sl;
|
||||
UNIMPLEMENTED_NODELIST();
|
||||
/* XXXX MOVE ? */
|
||||
node_t fake_node;
|
||||
const node_t *node = node_get_by_id(router->cache_info.identity_digest);;
|
||||
if (node == NULL) {
|
||||
memset(&fake_node, 0, sizeof(fake_node));
|
||||
fake_node.ri = (routerinfo_t *)router;
|
||||
memcpy(fake_node.identity, router->cache_info.identity_digest, DIGEST_LEN);
|
||||
node = &fake_node;
|
||||
}
|
||||
nodelist_add_node_family(sl, &fake_node);
|
||||
}
|
||||
|
||||
/** Return true iff r is named by some nickname in <b>lst</b>. */
|
||||
/** Return true iff <b>node</b> is named by some nickname in <b>lst</b>. */
|
||||
static INLINE int
|
||||
router_in_nickname_smartlist(smartlist_t *lst, const routerinfo_t *r)
|
||||
node_in_nickname_smartlist(const smartlist_t *lst, const node_t *node)
|
||||
{
|
||||
/* XXXX MOVE */
|
||||
if (!lst) return 0;
|
||||
SMARTLIST_FOREACH(lst, const char *, name,
|
||||
if (router_nickname_matches(r, name))
|
||||
return 1;);
|
||||
SMARTLIST_FOREACH(lst, const char *, name, {
|
||||
if (node_nickname_matches(node, name))
|
||||
return 1;
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1397,27 +1406,38 @@ router_in_nickname_smartlist(smartlist_t *lst, const routerinfo_t *r)
|
||||
int
|
||||
nodes_in_same_family(const node_t *node1, const node_t *node2)
|
||||
{
|
||||
#if 0
|
||||
/* XXXX MOVE */
|
||||
or_options_t *options = get_options();
|
||||
config_line_t *cl;
|
||||
|
||||
if (options->EnforceDistinctSubnets &&
|
||||
nodes_in_same_network_family(node1,node2))
|
||||
return 1;
|
||||
|
||||
if (router_in_nickname_smartlist(r1->declared_family, r2) &&
|
||||
router_in_nickname_smartlist(r2->declared_family, r1))
|
||||
return 1;
|
||||
|
||||
for (cl = options->NodeFamilies; cl; cl = cl->next) {
|
||||
if (router_nickname_is_in_list(r1, cl->value) &&
|
||||
router_nickname_is_in_list(r2, cl->value))
|
||||
/* Are they in the same family because of their addresses? */
|
||||
if (options->EnforceDistinctSubnets) {
|
||||
tor_addr_t a1, a2;
|
||||
node_get_addr(node1, &a1);
|
||||
node_get_addr(node2, &a2);
|
||||
if (addrs_in_same_network_family(&a1, &a2))
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
(void)node1;
|
||||
(void)node2;
|
||||
UNIMPLEMENTED_NODELIST();
|
||||
|
||||
/* Are they in the same family because the agree they are? */
|
||||
{
|
||||
const smartlist_t *f1, *f2;
|
||||
f1 = node_get_declared_family(node1);
|
||||
f2 = node_get_declared_family(node2);
|
||||
if (f1 && f2 &&
|
||||
node_in_nickname_smartlist(f1, node2) &&
|
||||
node_in_nickname_smartlist(f2, node1))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Are they in the same option because the user says they are? */
|
||||
if (options->NodeFamilySets) {
|
||||
SMARTLIST_FOREACH(options->NodeFamilySets, const routerset_t *, rs, {
|
||||
if (routerset_contains_node(rs, node1) &&
|
||||
routerset_contains_node(rs, node2))
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1431,7 +1451,7 @@ nodes_in_same_family(const node_t *node1, const node_t *node2)
|
||||
static void
|
||||
add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
|
||||
int must_be_running)
|
||||
{ /*XXXX MOVE */
|
||||
{ /*XXXX MOVE or Kill. */
|
||||
/*XXXX this is only used in one place. Can we kill it?*/
|
||||
const node_t *node;
|
||||
const routerinfo_t *router;
|
||||
@ -2301,6 +2321,22 @@ router_nickname_matches(const routerinfo_t *router, const char *nickname)
|
||||
return router_hex_digest_matches(router, nickname);
|
||||
}
|
||||
|
||||
/** Return true if <b>node</b>'s nickname matches <b>nickname</b>
|
||||
* (case-insensitive), or if <b>node's</b> identity key digest
|
||||
* matches a hexadecimal value stored in <b>nickname</b>. Return
|
||||
* false otherwise. */
|
||||
static int
|
||||
node_nickname_matches(const node_t *node, const char *nickname)
|
||||
{
|
||||
const char *n = node_get_nickname(node);
|
||||
if (n && nickname[0]!='$' && !strcasecmp(n, nickname))
|
||||
return 1;
|
||||
return hex_digest_nickname_matches(nickname,
|
||||
node->identity,
|
||||
n,
|
||||
node_is_named(node));
|
||||
}
|
||||
|
||||
/** Return the router in our routerlist whose (case-insensitive)
|
||||
* nickname or (case-sensitive) hexadecimal key digest is
|
||||
* <b>nickname</b>. Return NULL if no such router is known.
|
||||
|
Loading…
Reference in New Issue
Block a user