mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
more building blocks towards being able to fetch bridge descriptors
svn:r10548
This commit is contained in:
parent
1ae7708ff8
commit
04995f197d
@ -2622,3 +2622,79 @@ getinfo_helper_entry_guards(control_connection_t *conn,
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint32_t addr;
|
||||
uint16_t port;
|
||||
char identity[DIGEST_LEN];
|
||||
} bridge_info_t;
|
||||
|
||||
/** A list of known bridges. */
|
||||
static smartlist_t *bridge_list = NULL;
|
||||
|
||||
/** Initialize the bridge list to empty, creating it if needed. */
|
||||
void
|
||||
clear_bridge_list(void)
|
||||
{
|
||||
if (!bridge_list)
|
||||
bridge_list = smartlist_create();
|
||||
SMARTLIST_FOREACH(bridge_list, bridge_info_t *, b, tor_free(b));
|
||||
smartlist_clear(bridge_list);
|
||||
}
|
||||
|
||||
/** Remember a new bridge at <b>addr</b>:<b>port</b>. If <b>digest</b>
|
||||
* is set, it tells us the identity key too. */
|
||||
void
|
||||
bridge_add_from_config(uint32_t addr, uint16_t port, char *digest)
|
||||
{
|
||||
bridge_info_t *b = tor_malloc_zero(sizeof(bridge_info_t));
|
||||
b->addr = addr;
|
||||
b->port = port;
|
||||
if (digest)
|
||||
memcpy(b->identity, digest, DIGEST_LEN);
|
||||
if (!bridge_list)
|
||||
bridge_list = smartlist_create();
|
||||
smartlist_add(bridge_list, b);
|
||||
}
|
||||
|
||||
/** For each bridge in our list for which we don't currently have a
|
||||
* descriptor, fetch a new copy of its descriptor -- either directly
|
||||
* from the bridge or via a bridge authority. */
|
||||
void
|
||||
learn_bridge_descriptors(void)
|
||||
{
|
||||
char address_buf[INET_NTOA_BUF_LEN+1];
|
||||
struct in_addr in;
|
||||
or_options_t *options = get_options();
|
||||
int num_bridge_auths = get_n_authorities(BRIDGE_AUTHORITY);
|
||||
|
||||
if (!bridge_list)
|
||||
return;
|
||||
|
||||
SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge,
|
||||
{
|
||||
if (router_get_by_digest(bridge->identity))
|
||||
continue; /* we've already got one. great. */
|
||||
in.s_addr = htonl(bridge->addr);
|
||||
tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
|
||||
|
||||
if (tor_digest_is_zero(bridge->identity) ||
|
||||
!options->UpdateBridgesFromAuthority ||
|
||||
!num_bridge_auths) {
|
||||
if (!connection_get_by_type_addr_port_purpose(
|
||||
CONN_TYPE_DIR, bridge->addr, bridge->port,
|
||||
DIR_PURPOSE_FETCH_SERVERDESC)) {
|
||||
/* we need to ask the bridge itself for its descriptor. */
|
||||
directory_initiate_command(address_buf, bridge->addr,
|
||||
bridge->port, 0,
|
||||
1, bridge->identity,
|
||||
DIR_PURPOSE_FETCH_SERVERDESC,
|
||||
ROUTER_PURPOSE_BRIDGE,
|
||||
0, "authority", NULL, 0);
|
||||
}
|
||||
} else {
|
||||
/* we have a digest and we want to ask an authority. */
|
||||
// XXX
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -263,6 +263,7 @@ static config_var_t _option_vars[] = {
|
||||
VAR("TransListenAddress", LINELIST, TransListenAddress, NULL),
|
||||
VAR("TransPort", UINT, TransPort, "0"),
|
||||
VAR("TunnelDirConns", BOOL, TunnelDirConns, "0"),
|
||||
VAR("UpdateBridgesFromAuthority",BOOL,UpdateBridgesFromAuthority,"0"),
|
||||
VAR("UseBridges", BOOL, UseBridges, "0"),
|
||||
VAR("UseEntryGuards", BOOL, UseEntryGuards, "1"),
|
||||
VAR("User", STRING, User, NULL),
|
||||
@ -952,6 +953,7 @@ options_act(or_options_t *old_options)
|
||||
add_default_trusted_dirservers();
|
||||
}
|
||||
|
||||
clear_bridge_list();
|
||||
if (options->Bridges) {
|
||||
for (cl = options->Bridges; cl; cl = cl->next) {
|
||||
if (parse_bridge_line(cl->value, 0)<0) {
|
||||
@ -3606,7 +3608,7 @@ parse_bridge_line(const char *line, int validate_only)
|
||||
log_debug(LD_DIR, "Bridge at %s:%d (%s)", address,
|
||||
(int)port,
|
||||
fingerprint ? fingerprint : "no key listed");
|
||||
// bridge_add_from_config(addr, port, fingerprint ? digest : NULL);
|
||||
bridge_add_from_config(addr, port, fingerprint ? digest : NULL);
|
||||
}
|
||||
|
||||
r = 0;
|
||||
|
@ -177,7 +177,9 @@ directory_post_to_dirservers(uint8_t purpose, authority_type_t type,
|
||||
}
|
||||
post_via_tor = purpose_needs_anonymity(purpose) ||
|
||||
!fascist_firewall_allows_address_dir(ds->addr, ds->dir_port);
|
||||
directory_initiate_command_routerstatus(rs, purpose, post_via_tor,
|
||||
directory_initiate_command_routerstatus(rs, purpose,
|
||||
ROUTER_PURPOSE_GENERAL,
|
||||
post_via_tor,
|
||||
NULL, payload, upload_len);
|
||||
});
|
||||
if (!found) {
|
||||
@ -194,18 +196,18 @@ directory_post_to_dirservers(uint8_t purpose, authority_type_t type,
|
||||
* down, mark them up and try again.
|
||||
*/
|
||||
void
|
||||
directory_get_from_dirserver(uint8_t purpose, const char *resource,
|
||||
directory_get_from_dirserver(uint8_t dir_purpose, const char *resource,
|
||||
int retry_if_no_servers)
|
||||
{
|
||||
routerstatus_t *rs = NULL;
|
||||
or_options_t *options = get_options();
|
||||
int prefer_authority = server_mode(options) && options->DirPort != 0;
|
||||
int directconn = !purpose_needs_anonymity(purpose);
|
||||
int directconn = !purpose_needs_anonymity(dir_purpose);
|
||||
authority_type_t type;
|
||||
|
||||
/* FFFF we could break this switch into its own function, and call
|
||||
* it elsewhere in directory.c. -RD */
|
||||
switch (purpose) {
|
||||
switch (dir_purpose) {
|
||||
case DIR_PURPOSE_FETCH_EXTRAINFO:
|
||||
type = EXTRAINFO_CACHE | V2_AUTHORITY;
|
||||
break;
|
||||
@ -221,7 +223,7 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource,
|
||||
type = HIDSERV_AUTHORITY;
|
||||
break;
|
||||
default:
|
||||
log_warn(LD_BUG, "Unexpected purpose %d", (int)purpose);
|
||||
log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -240,13 +242,13 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource,
|
||||
retry_if_no_servers);
|
||||
if (!rs) {
|
||||
const char *which;
|
||||
if (purpose == DIR_PURPOSE_FETCH_DIR)
|
||||
if (dir_purpose == DIR_PURPOSE_FETCH_DIR)
|
||||
which = "directory";
|
||||
else if (purpose == DIR_PURPOSE_FETCH_RUNNING_LIST)
|
||||
else if (dir_purpose == DIR_PURPOSE_FETCH_RUNNING_LIST)
|
||||
which = "status list";
|
||||
else if (purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
|
||||
else if (dir_purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
|
||||
which = "network status";
|
||||
else // if (purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
|
||||
else // if (dir_purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS)
|
||||
which = "server descriptors";
|
||||
log_info(LD_DIR,
|
||||
"No router found for %s; falling back to dirserver list",
|
||||
@ -260,7 +262,7 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource,
|
||||
}
|
||||
if (!directconn) {
|
||||
/* Never use fascistfirewall; we're going via Tor. */
|
||||
if (purpose == DIR_PURPOSE_FETCH_RENDDESC) {
|
||||
if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
|
||||
/* only ask hidserv authorities, any of them will do */
|
||||
rs = router_pick_trusteddirserver(HIDSERV_AUTHORITY, 0, 0,
|
||||
retry_if_no_servers);
|
||||
@ -275,24 +277,29 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource,
|
||||
}
|
||||
|
||||
if (rs)
|
||||
directory_initiate_command_routerstatus(rs, purpose, !directconn,
|
||||
directory_initiate_command_routerstatus(rs, dir_purpose,
|
||||
ROUTER_PURPOSE_GENERAL,
|
||||
!directconn,
|
||||
resource, NULL, 0);
|
||||
else {
|
||||
log_notice(LD_DIR,
|
||||
"While fetching directory info, "
|
||||
"no running dirservers known. Will try again later. "
|
||||
"(purpose %d)", purpose);
|
||||
if (!purpose_needs_anonymity(purpose)) {
|
||||
"(purpose %d)", dir_purpose);
|
||||
if (!purpose_needs_anonymity(dir_purpose)) {
|
||||
/* remember we tried them all and failed. */
|
||||
directory_all_unreachable(time(NULL));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Launch a new connection to the directory server <b>status</b> to upload or
|
||||
* download a server or rendezvous descriptor. <b>purpose</b> determines what
|
||||
/** Launch a new connection to the directory server <b>status</b> to
|
||||
* upload or download a server or rendezvous
|
||||
* descriptor. <b>dir_purpose</b> determines what
|
||||
* kind of directory connection we're launching, and must be one of
|
||||
* DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}.
|
||||
* DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}. <b>router_purpose</b>
|
||||
* specifies the descriptor purposes we have in mind (currently only
|
||||
* used for FETCH_DIR).
|
||||
*
|
||||
* When uploading, <b>payload</b> and <b>payload_len</b> determine the content
|
||||
* of the HTTP post. Otherwise, <b>payload</b> should be NULL.
|
||||
@ -302,7 +309,8 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource,
|
||||
*/
|
||||
void
|
||||
directory_initiate_command_routerstatus(routerstatus_t *status,
|
||||
uint8_t purpose,
|
||||
uint8_t dir_purpose,
|
||||
uint8_t router_purpose,
|
||||
int anonymized_connection,
|
||||
const char *resource,
|
||||
const char *payload,
|
||||
@ -323,7 +331,8 @@ directory_initiate_command_routerstatus(routerstatus_t *status,
|
||||
status->or_port, status->dir_port,
|
||||
status->version_supports_begindir,
|
||||
status->identity_digest,
|
||||
purpose, anonymized_connection, resource,
|
||||
dir_purpose, router_purpose,
|
||||
anonymized_connection, resource,
|
||||
payload, payload_len);
|
||||
}
|
||||
|
||||
@ -441,8 +450,8 @@ connection_dir_download_routerdesc_failed(dir_connection_t *conn)
|
||||
void
|
||||
directory_initiate_command(const char *address, uint32_t addr,
|
||||
uint16_t or_port, uint16_t dir_port,
|
||||
int supports_begindir,
|
||||
const char *digest, uint8_t purpose,
|
||||
int supports_begindir, const char *digest,
|
||||
uint8_t dir_purpose, uint8_t router_purpose,
|
||||
int anonymized_connection, const char *resource,
|
||||
const char *payload, size_t payload_len)
|
||||
{
|
||||
@ -460,7 +469,7 @@ directory_initiate_command(const char *address, uint32_t addr,
|
||||
log_debug(LD_DIR, "anonymized %d, want_to_tunnel %d.",
|
||||
anonymized_connection, want_to_tunnel);
|
||||
|
||||
switch (purpose) {
|
||||
switch (dir_purpose) {
|
||||
case DIR_PURPOSE_FETCH_DIR:
|
||||
log_debug(LD_DIR,"initiating directory fetch");
|
||||
break;
|
||||
@ -498,7 +507,8 @@ directory_initiate_command(const char *address, uint32_t addr,
|
||||
conn->_base.address = tor_strdup(address);
|
||||
memcpy(conn->identity_digest, digest, DIGEST_LEN);
|
||||
|
||||
conn->_base.purpose = purpose;
|
||||
conn->_base.purpose = dir_purpose;
|
||||
conn->router_purpose = router_purpose;
|
||||
|
||||
/* give it an initial state */
|
||||
conn->_base.state = DIR_CONN_STATE_CONNECTING;
|
||||
@ -524,7 +534,7 @@ directory_initiate_command(const char *address, uint32_t addr,
|
||||
/* fall through */
|
||||
case 0:
|
||||
/* queue the command on the outbuf */
|
||||
directory_send_command(conn, purpose, 1, resource,
|
||||
directory_send_command(conn, dir_purpose, 1, resource,
|
||||
payload, payload_len);
|
||||
connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
|
||||
/* writable indicates finish, readable indicates broken link,
|
||||
@ -557,7 +567,7 @@ directory_initiate_command(const char *address, uint32_t addr,
|
||||
}
|
||||
conn->_base.state = DIR_CONN_STATE_CLIENT_SENDING;
|
||||
/* queue the command on the outbuf */
|
||||
directory_send_command(conn, purpose, 0, resource,
|
||||
directory_send_command(conn, dir_purpose, 0, resource,
|
||||
payload, payload_len);
|
||||
connection_watch_events(TO_CONN(conn), EV_READ | EV_WRITE);
|
||||
connection_start_reading(TO_CONN(linked_conn));
|
||||
@ -1256,7 +1266,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
|
||||
if (was_ei) {
|
||||
router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which);
|
||||
} else {
|
||||
router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which);
|
||||
router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
|
||||
conn->router_purpose);
|
||||
directory_info_has_arrived(now, 0);
|
||||
}
|
||||
}
|
||||
|
24
src/or/or.h
24
src/or/or.h
@ -934,6 +934,9 @@ typedef struct dir_connection_t {
|
||||
DIR_SPOOL_EXTRA_BY_DIGEST, DIR_SPOOL_EXTRA_BY_FP,
|
||||
DIR_SPOOL_CACHED_DIR, DIR_SPOOL_NETWORKSTATUS
|
||||
} dir_spool_src : 3;
|
||||
/** If we're fetching descriptors, what router purpose shall we assign
|
||||
* to them? */
|
||||
uint8_t router_purpose;
|
||||
/** List of fingerprints for networkstatuses or desriptors to be spooled. */
|
||||
smartlist_t *fingerprint_stack;
|
||||
/** A cached_dir_t object that we're currently spooling out */
|
||||
@ -1850,6 +1853,10 @@ typedef struct {
|
||||
int UseBridges; /**< Boolean: should we start all circuits with a bridge? */
|
||||
config_line_t *Bridges; /**< List of bootstrap bridge addresses. */
|
||||
|
||||
/** Boolean: if we know the bridge's digest, should we get new
|
||||
* descriptors from the bridge authorities or from the bridge itself? */
|
||||
int UpdateBridgesFromAuthority;
|
||||
|
||||
int AvoidDiskWrites; /**< Boolean: should we never cache things to disk?
|
||||
* Not used yet. */
|
||||
int ClientOnly; /**< Boolean: should we never evolve into a server role? */
|
||||
@ -2210,6 +2217,10 @@ int getinfo_helper_entry_guards(control_connection_t *conn,
|
||||
const char *question, char **answer);
|
||||
void entry_guards_free_all(void);
|
||||
|
||||
void clear_bridge_list(void);
|
||||
void bridge_add_from_config(uint32_t addr, uint16_t port, char *digest);
|
||||
void learn_bridge_descriptors(void);
|
||||
|
||||
/********************************* circuitlist.c ***********************/
|
||||
|
||||
circuit_t * _circuit_get_global_list(void);
|
||||
@ -2640,10 +2651,11 @@ char *authority_type_to_string(authority_type_t auth);
|
||||
void directory_post_to_dirservers(uint8_t purpose, authority_type_t type,
|
||||
const char *payload,
|
||||
size_t payload_len, size_t extrainfo_len);
|
||||
void directory_get_from_dirserver(uint8_t purpose, const char *resource,
|
||||
void directory_get_from_dirserver(uint8_t dir_purpose, const char *resource,
|
||||
int retry_if_no_servers);
|
||||
void directory_initiate_command_routerstatus(routerstatus_t *status,
|
||||
uint8_t purpose,
|
||||
uint8_t dir_purpose,
|
||||
uint8_t router_purpose,
|
||||
int anonymized_connection,
|
||||
const char *resource,
|
||||
const char *payload,
|
||||
@ -2659,8 +2671,8 @@ int connection_dir_finished_connecting(dir_connection_t *conn);
|
||||
void connection_dir_request_failed(dir_connection_t *conn);
|
||||
void directory_initiate_command(const char *address, uint32_t addr,
|
||||
uint16_t or_port, uint16_t dir_port,
|
||||
int supports_begindir,
|
||||
const char *digest, uint8_t purpose,
|
||||
int supports_begindir, const char *digest,
|
||||
uint8_t dir_purpose, uint8_t router_purpose,
|
||||
int anonymized_connection,
|
||||
const char *resource,
|
||||
const char *payload, size_t payload_len);
|
||||
@ -3202,6 +3214,7 @@ typedef struct trusted_dir_server_t {
|
||||
} trusted_dir_server_t;
|
||||
|
||||
int router_reload_router_list(void);
|
||||
int get_n_authorities(authority_type_t type);
|
||||
int router_reload_networkstatus(void);
|
||||
smartlist_t *router_get_trusted_dir_servers(void);
|
||||
routerstatus_t *router_pick_directory_server(int requireother,
|
||||
@ -3274,7 +3287,8 @@ int router_load_single_router(const char *s, uint8_t purpose,
|
||||
const char **msg);
|
||||
void router_load_routers_from_string(const char *s, const char *eos,
|
||||
saved_location_t saved_location,
|
||||
smartlist_t *requested_fingerprints);
|
||||
smartlist_t *requested_fingerprints,
|
||||
uint8_t purpose);
|
||||
void router_load_extrainfo_from_string(const char *s, const char *eos,
|
||||
saved_location_t saved_location,
|
||||
smartlist_t *requested_fps);
|
||||
|
@ -614,6 +614,7 @@ consider_testing_reachability(int test_or, int test_dir)
|
||||
me->or_port, me->dir_port,
|
||||
0, me->cache_info.identity_digest,
|
||||
DIR_PURPOSE_FETCH_SERVERDESC,
|
||||
ROUTER_PURPOSE_GENERAL,
|
||||
1, "authority", NULL, 0);
|
||||
|
||||
control_event_server_status(LOG_NOTICE,
|
||||
|
@ -109,7 +109,7 @@ static int have_warned_about_new_version = 0;
|
||||
|
||||
/** Return the number of directory authorities whose type matches some bit set
|
||||
* in <b>type</b> */
|
||||
static INLINE int
|
||||
INLINE int
|
||||
get_n_authorities(authority_type_t type)
|
||||
{
|
||||
int n = 0;
|
||||
@ -549,7 +549,8 @@ router_reload_router_list_impl(int extrainfo)
|
||||
else
|
||||
router_load_routers_from_string((*mmap_ptr)->data,
|
||||
(*mmap_ptr)->data+(*mmap_ptr)->size,
|
||||
SAVED_IN_CACHE, NULL);
|
||||
SAVED_IN_CACHE, NULL,
|
||||
ROUTER_PURPOSE_GENERAL);
|
||||
}
|
||||
|
||||
tor_snprintf(fname, fname_len, "%s"PATH_SEPARATOR"%s.new",
|
||||
@ -560,7 +561,8 @@ router_reload_router_list_impl(int extrainfo)
|
||||
if (extrainfo)
|
||||
router_load_extrainfo_from_string(contents, NULL,SAVED_IN_JOURNAL, NULL);
|
||||
else
|
||||
router_load_routers_from_string(contents, NULL, SAVED_IN_JOURNAL, NULL);
|
||||
router_load_routers_from_string(contents, NULL, SAVED_IN_JOURNAL, NULL,
|
||||
ROUTER_PURPOSE_GENERAL);
|
||||
stats->journal_len = (size_t) st.st_size;
|
||||
tor_free(contents);
|
||||
}
|
||||
@ -2788,7 +2790,8 @@ router_load_single_router(const char *s, uint8_t purpose, const char **msg)
|
||||
void
|
||||
router_load_routers_from_string(const char *s, const char *eos,
|
||||
saved_location_t saved_location,
|
||||
smartlist_t *requested_fingerprints)
|
||||
smartlist_t *requested_fingerprints,
|
||||
uint8_t purpose)
|
||||
{
|
||||
smartlist_t *routers = smartlist_create(), *changed = smartlist_create();
|
||||
char fp[HEX_DIGEST_LEN+1];
|
||||
@ -2821,6 +2824,10 @@ router_load_routers_from_string(const char *s, const char *eos,
|
||||
}
|
||||
}
|
||||
|
||||
ri->purpose = purpose;
|
||||
if (purpose != ROUTER_PURPOSE_GENERAL)
|
||||
ri->cache_info.do_not_cache = 1;
|
||||
|
||||
if (router_add_to_routerlist(ri, &msg, from_cache, !from_cache) >= 0)
|
||||
smartlist_add(changed, ri);
|
||||
});
|
||||
@ -3340,6 +3347,10 @@ update_networkstatus_cache_downloads(time_t now)
|
||||
if (connection_get_by_type_addr_port_purpose(
|
||||
CONN_TYPE_DIR, ds->addr, ds->dir_port,
|
||||
DIR_PURPOSE_FETCH_NETWORKSTATUS)) {
|
||||
/* XXX020 the above dir_port won't be accurate if we're
|
||||
* doing a tunneled conn. In that case it should be or_port.
|
||||
* How to guess from here? Maybe make the function less general
|
||||
* and have it know that it's looking for dir conns. -RD */
|
||||
/* We are already fetching this one. */
|
||||
continue;
|
||||
}
|
||||
@ -3348,6 +3359,7 @@ update_networkstatus_cache_downloads(time_t now)
|
||||
strlcat(resource, ".z", sizeof(resource));
|
||||
directory_initiate_command_routerstatus(
|
||||
&ds->fake_status.status, DIR_PURPOSE_FETCH_NETWORKSTATUS,
|
||||
ROUTER_PURPOSE_GENERAL,
|
||||
0, /* Not private */
|
||||
resource,
|
||||
NULL, 0 /* No payload. */);
|
||||
@ -4365,6 +4377,7 @@ initiate_descriptor_downloads(routerstatus_t *source,
|
||||
if (source) {
|
||||
/* We know which authority we want. */
|
||||
directory_initiate_command_routerstatus(source, purpose,
|
||||
ROUTER_PURPOSE_GENERAL,
|
||||
0, /* not private */
|
||||
resource, NULL, 0);
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user