mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
Checkpoint in-progress fixes:
Add 'testing' circuit purpose, for reachability testing. Notice when our IP changes, and reset stats. Try to pull down a directory via Tor to see if our DirPort is working. Try to extend a circuit back to us to see if our ORPort is working. Only publish a descriptor if they're both reachable. These mostly work, and I'd better get them in before I cause conflicts. svn:r3703
This commit is contained in:
parent
8efb2a957d
commit
a1f1fa6ab2
@ -753,6 +753,8 @@ static int new_route_len(double cw, uint8_t purpose, smartlist_t *routers) {
|
|||||||
#else
|
#else
|
||||||
if (purpose == CIRCUIT_PURPOSE_C_GENERAL)
|
if (purpose == CIRCUIT_PURPOSE_C_GENERAL)
|
||||||
routelen = 3;
|
routelen = 3;
|
||||||
|
else if (purpose == CIRCUIT_PURPOSE_TESTING)
|
||||||
|
routelen = 3;
|
||||||
else if (purpose == CIRCUIT_PURPOSE_C_INTRODUCING)
|
else if (purpose == CIRCUIT_PURPOSE_C_INTRODUCING)
|
||||||
routelen = 4;
|
routelen = 4;
|
||||||
else if (purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND)
|
else if (purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND)
|
||||||
|
@ -541,6 +541,31 @@ circuit_expire_old_circuits(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A testing circuit has completed. Take whatever stats we want. */
|
||||||
|
static void
|
||||||
|
circuit_testing_opened(circuit_t *circ) {
|
||||||
|
|
||||||
|
/* For now, we only use testing circuits to see if our ORPort is
|
||||||
|
reachable. So, if this circuit ends at us, remember that. */
|
||||||
|
routerinfo_t *exit = router_get_by_digest(circ->build_state->chosen_exit_digest);
|
||||||
|
if(exit && router_is_me(exit)) {
|
||||||
|
log_fn(LOG_NOTICE,"Your ORPort is reachable from the outside. Excellent.");
|
||||||
|
router_orport_found_reachable();
|
||||||
|
}
|
||||||
|
circuit_mark_for_close(circ);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A testing circuit has failed to build. Take whatever stats we want. */
|
||||||
|
static void
|
||||||
|
circuit_testing_failed(circuit_t *circ, int at_last_hop) {
|
||||||
|
routerinfo_t *me = router_get_my_routerinfo();
|
||||||
|
|
||||||
|
if (!at_last_hop)
|
||||||
|
circuit_launch_by_identity(CIRCUIT_PURPOSE_TESTING, me->identity_digest, 0, 0, 1);
|
||||||
|
else
|
||||||
|
log_fn(LOG_NOTICE,"The testing circuit has failed. Guess you're not reachable yet.");
|
||||||
|
}
|
||||||
|
|
||||||
/** The circuit <b>circ</b> has just become open. Take the next
|
/** The circuit <b>circ</b> has just become open. Take the next
|
||||||
* step: for rendezvous circuits, we pass circ to the appropriate
|
* step: for rendezvous circuits, we pass circ to the appropriate
|
||||||
* function in rendclient or rendservice. For general circuits, we
|
* function in rendclient or rendservice. For general circuits, we
|
||||||
@ -572,6 +597,9 @@ void circuit_has_opened(circuit_t *circ) {
|
|||||||
/* at Bob, connecting to rend point */
|
/* at Bob, connecting to rend point */
|
||||||
rend_service_rendezvous_has_opened(circ);
|
rend_service_rendezvous_has_opened(circ);
|
||||||
break;
|
break;
|
||||||
|
case CIRCUIT_PURPOSE_TESTING:
|
||||||
|
circuit_testing_opened(circ);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
log_fn(LOG_ERR,"unhandled purpose %d",circ->purpose);
|
log_fn(LOG_ERR,"unhandled purpose %d",circ->purpose);
|
||||||
tor_assert(0);
|
tor_assert(0);
|
||||||
@ -603,6 +631,9 @@ void circuit_build_failed(circuit_t *circ) {
|
|||||||
circuit_increment_failure_count();
|
circuit_increment_failure_count();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CIRCUIT_PURPOSE_TESTING:
|
||||||
|
circuit_testing_failed(circ, failed_at_last_hop);
|
||||||
|
break;
|
||||||
case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
|
case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
|
||||||
/* at Bob, waiting for introductions */
|
/* at Bob, waiting for introductions */
|
||||||
if (circ->state != CIRCUIT_STATE_OPEN) {
|
if (circ->state != CIRCUIT_STATE_OPEN) {
|
||||||
@ -666,7 +697,8 @@ circuit_launch_by_identity(uint8_t purpose, const char *exit_digest,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (purpose != CIRCUIT_PURPOSE_C_GENERAL) {
|
if (purpose != CIRCUIT_PURPOSE_C_GENERAL &&
|
||||||
|
purpose != CIRCUIT_PURPOSE_TESTING) {
|
||||||
/* see if there are appropriate circs available to cannibalize. */
|
/* see if there are appropriate circs available to cannibalize. */
|
||||||
if ((circ = circuit_get_clean_open(CIRCUIT_PURPOSE_C_GENERAL, need_uptime,
|
if ((circ = circuit_get_clean_open(CIRCUIT_PURPOSE_C_GENERAL, need_uptime,
|
||||||
need_capacity, internal))) {
|
need_capacity, internal))) {
|
||||||
|
@ -933,6 +933,7 @@ resolve_my_address(const char *address, uint32_t *addr)
|
|||||||
char hostname[256];
|
char hostname[256];
|
||||||
int explicit_ip=1;
|
int explicit_ip=1;
|
||||||
char tmpbuf[INET_NTOA_BUF_LEN];
|
char tmpbuf[INET_NTOA_BUF_LEN];
|
||||||
|
static uint32_t old_addr=0;
|
||||||
|
|
||||||
tor_assert(addr);
|
tor_assert(addr);
|
||||||
|
|
||||||
@ -972,6 +973,11 @@ resolve_my_address(const char *address, uint32_t *addr)
|
|||||||
|
|
||||||
log_fn(LOG_DEBUG, "Resolved Address to %s.", tmpbuf);
|
log_fn(LOG_DEBUG, "Resolved Address to %s.", tmpbuf);
|
||||||
*addr = ntohl(in.s_addr);
|
*addr = ntohl(in.s_addr);
|
||||||
|
if (old_addr && old_addr != *addr) {
|
||||||
|
log_fn(LOG_NOTICE,"Your IP seems to have changed. Updating.");
|
||||||
|
server_has_changed_ip();
|
||||||
|
}
|
||||||
|
old_addr = *addr;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,19 +28,20 @@ const char directory_c_id[] = "$Id$";
|
|||||||
* connection_finished_connecting() in connection.c
|
* connection_finished_connecting() in connection.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
void
|
||||||
directory_initiate_command_router(routerinfo_t *router, uint8_t purpose,
|
directory_initiate_command_router(routerinfo_t *router, uint8_t purpose,
|
||||||
const char *resource,
|
int private_connection, const char *resource,
|
||||||
const char *payload, size_t payload_len);
|
const char *payload, size_t payload_len);
|
||||||
static void
|
static void
|
||||||
directory_initiate_command_trusted_dir(trusted_dir_server_t *dirserv,
|
directory_initiate_command_trusted_dir(trusted_dir_server_t *dirserv,
|
||||||
uint8_t purpose, const char *resource,
|
uint8_t purpose, int private_connection,
|
||||||
|
const char *resource,
|
||||||
const char *payload, size_t payload_len);
|
const char *payload, size_t payload_len);
|
||||||
static void
|
static void
|
||||||
directory_initiate_command(const char *address, uint32_t addr, uint16_t port,
|
directory_initiate_command(const char *address, uint32_t addr, uint16_t port,
|
||||||
const char *platform,
|
const char *platform,
|
||||||
const char *digest, uint8_t purpose,
|
const char *digest, uint8_t purpose,
|
||||||
const char *resource,
|
int private_connection, const char *resource,
|
||||||
const char *payload, size_t payload_len);
|
const char *payload, size_t payload_len);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -111,6 +112,14 @@ int dir_policy_permits_address(uint32_t addr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int purpose_is_private(uint8_t purpose) {
|
||||||
|
if (purpose == DIR_PURPOSE_FETCH_DIR ||
|
||||||
|
purpose == DIR_PURPOSE_UPLOAD_DIR ||
|
||||||
|
purpose == DIR_PURPOSE_FETCH_RUNNING_LIST)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/** Start a connection to every known directory server, using
|
/** Start a connection to every known directory server, using
|
||||||
* connection purpose 'purpose' and uploading the payload 'payload'
|
* connection purpose 'purpose' and uploading the payload 'payload'
|
||||||
* (length 'payload_len'). The purpose should be one of
|
* (length 'payload_len'). The purpose should be one of
|
||||||
@ -137,8 +146,8 @@ directory_post_to_dirservers(uint8_t purpose, const char *payload,
|
|||||||
if (!smartlist_string_num_isin(get_options()->FirewallPorts, ds->dir_port))
|
if (!smartlist_string_num_isin(get_options()->FirewallPorts, ds->dir_port))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
directory_initiate_command_trusted_dir(ds, purpose, NULL,
|
directory_initiate_command_trusted_dir(ds, purpose, purpose_is_private(purpose),
|
||||||
payload, payload_len);
|
NULL, payload, payload_len);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +168,7 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource,
|
|||||||
int directconn = purpose == DIR_PURPOSE_FETCH_DIR ||
|
int directconn = purpose == DIR_PURPOSE_FETCH_DIR ||
|
||||||
purpose == DIR_PURPOSE_FETCH_RUNNING_LIST;
|
purpose == DIR_PURPOSE_FETCH_RUNNING_LIST;
|
||||||
int fetch_fresh_first = advertised_server_mode();
|
int fetch_fresh_first = advertised_server_mode();
|
||||||
|
int priv = purpose_is_private(purpose);
|
||||||
|
|
||||||
if (directconn) {
|
if (directconn) {
|
||||||
if (fetch_fresh_first) {
|
if (fetch_fresh_first) {
|
||||||
@ -186,9 +196,9 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (r)
|
if (r)
|
||||||
directory_initiate_command_router(r, purpose, resource, NULL, 0);
|
directory_initiate_command_router(r, purpose, priv, resource, NULL, 0);
|
||||||
else if (ds)
|
else if (ds)
|
||||||
directory_initiate_command_trusted_dir(ds, purpose, resource, NULL, 0);
|
directory_initiate_command_trusted_dir(ds, purpose, priv, resource, NULL, 0);
|
||||||
else {
|
else {
|
||||||
log_fn(LOG_NOTICE,"No running dirservers known. Not trying. (purpose %d)",
|
log_fn(LOG_NOTICE,"No running dirservers known. Not trying. (purpose %d)",
|
||||||
purpose);
|
purpose);
|
||||||
@ -210,25 +220,28 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource,
|
|||||||
* When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
|
* When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
|
||||||
* want to fetch.
|
* want to fetch.
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
directory_initiate_command_router(routerinfo_t *router, uint8_t purpose,
|
directory_initiate_command_router(routerinfo_t *router, uint8_t purpose,
|
||||||
const char *resource,
|
int private_connection, const char *resource,
|
||||||
const char *payload, size_t payload_len)
|
const char *payload, size_t payload_len)
|
||||||
{
|
{
|
||||||
directory_initiate_command(router->address, router->addr, router->dir_port,
|
directory_initiate_command(router->address, router->addr, router->dir_port,
|
||||||
router->platform, router->identity_digest,
|
router->platform, router->identity_digest,
|
||||||
purpose, resource, payload, payload_len);
|
purpose, private_connection, resource,
|
||||||
|
payload, payload_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** As directory_initiate_command_router, but send the command to a trusted
|
/** As directory_initiate_command_router, but send the command to a trusted
|
||||||
* directory server <b>dirserv</b>. **/
|
* directory server <b>dirserv</b>. **/
|
||||||
static void
|
static void
|
||||||
directory_initiate_command_trusted_dir(trusted_dir_server_t *dirserv,
|
directory_initiate_command_trusted_dir(trusted_dir_server_t *dirserv,
|
||||||
uint8_t purpose, const char *resource,
|
uint8_t purpose, int private_connection,
|
||||||
|
const char *resource,
|
||||||
const char *payload, size_t payload_len)
|
const char *payload, size_t payload_len)
|
||||||
{
|
{
|
||||||
directory_initiate_command(dirserv->address, dirserv->addr,dirserv->dir_port,
|
directory_initiate_command(dirserv->address, dirserv->addr,dirserv->dir_port,
|
||||||
NULL, dirserv->digest, purpose, resource, payload, payload_len);
|
NULL, dirserv->digest, purpose, private_connection, resource,
|
||||||
|
payload, payload_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Called when we are unable to complete our connection to a
|
/** Called when we are unable to complete our connection to a
|
||||||
@ -256,7 +269,7 @@ static void
|
|||||||
directory_initiate_command(const char *address, uint32_t addr,
|
directory_initiate_command(const char *address, uint32_t addr,
|
||||||
uint16_t dir_port, const char *platform,
|
uint16_t dir_port, const char *platform,
|
||||||
const char *digest, uint8_t purpose,
|
const char *digest, uint8_t purpose,
|
||||||
const char *resource,
|
int private_connection, const char *resource,
|
||||||
const char *payload, size_t payload_len)
|
const char *payload, size_t payload_len)
|
||||||
{
|
{
|
||||||
connection_t *conn;
|
connection_t *conn;
|
||||||
@ -292,17 +305,7 @@ directory_initiate_command(const char *address, uint32_t addr,
|
|||||||
/* set up conn so it's got all the data we need to remember */
|
/* set up conn so it's got all the data we need to remember */
|
||||||
conn->addr = addr;
|
conn->addr = addr;
|
||||||
conn->port = dir_port;
|
conn->port = dir_port;
|
||||||
|
|
||||||
if (get_options()->HttpProxy) {
|
|
||||||
addr = get_options()->HttpProxyAddr;
|
|
||||||
dir_port = get_options()->HttpProxyPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
conn->address = tor_strdup(address);
|
conn->address = tor_strdup(address);
|
||||||
/* conn->nickname = tor_strdup(router->nickname); */
|
|
||||||
/* tor_assert(router->identity_pkey); */
|
|
||||||
/* conn->identity_pkey = crypto_pk_dup_key(router->identity_pkey); */
|
|
||||||
/* crypto_pk_get_digest(conn->identity_pkey, conn->identity_digest); */
|
|
||||||
memcpy(conn->identity_digest, digest, DIGEST_LEN);
|
memcpy(conn->identity_digest, digest, DIGEST_LEN);
|
||||||
|
|
||||||
conn->purpose = purpose;
|
conn->purpose = purpose;
|
||||||
@ -310,10 +313,14 @@ directory_initiate_command(const char *address, uint32_t addr,
|
|||||||
/* give it an initial state */
|
/* give it an initial state */
|
||||||
conn->state = DIR_CONN_STATE_CONNECTING;
|
conn->state = DIR_CONN_STATE_CONNECTING;
|
||||||
|
|
||||||
if (purpose == DIR_PURPOSE_FETCH_DIR ||
|
if (!private_connection) {
|
||||||
purpose == DIR_PURPOSE_UPLOAD_DIR ||
|
|
||||||
purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
|
|
||||||
/* then we want to connect directly */
|
/* then we want to connect directly */
|
||||||
|
|
||||||
|
if (get_options()->HttpProxy) {
|
||||||
|
addr = get_options()->HttpProxyAddr;
|
||||||
|
dir_port = get_options()->HttpProxyPort;
|
||||||
|
}
|
||||||
|
|
||||||
switch (connection_connect(conn, conn->address, addr, dir_port)) {
|
switch (connection_connect(conn, conn->address, addr, dir_port)) {
|
||||||
case -1:
|
case -1:
|
||||||
connection_dir_connect_failed(conn);
|
connection_dir_connect_failed(conn);
|
||||||
@ -703,7 +710,8 @@ connection_dir_client_reached_eof(connection_t *conn)
|
|||||||
} else {
|
} else {
|
||||||
log_fn(LOG_INFO,"updated routers.");
|
log_fn(LOG_INFO,"updated routers.");
|
||||||
}
|
}
|
||||||
directory_has_arrived(time(NULL)); /* do things we've been waiting to do */
|
/* do things we've been waiting to do */
|
||||||
|
directory_has_arrived(time(NULL), conn->identity_digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conn->purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
|
if (conn->purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
|
||||||
|
112
src/or/main.c
112
src/or/main.c
@ -263,7 +263,6 @@ void connection_watch_events(connection_t *conn, short events) {
|
|||||||
|
|
||||||
/** Return true iff <b>conn</b> is listening for read events. */
|
/** Return true iff <b>conn</b> is listening for read events. */
|
||||||
int connection_is_reading(connection_t *conn) {
|
int connection_is_reading(connection_t *conn) {
|
||||||
int r;
|
|
||||||
tor_assert(conn);
|
tor_assert(conn);
|
||||||
|
|
||||||
return conn->read_event && event_pending(conn->read_event, EV_READ, NULL);
|
return conn->read_event && event_pending(conn->read_event, EV_READ, NULL);
|
||||||
@ -578,8 +577,10 @@ void directory_all_unreachable(time_t now) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This function is called whenever we successfully pull down a directory */
|
/** This function is called whenever we successfully pull down a directory.
|
||||||
void directory_has_arrived(time_t now) {
|
* If <b>identity_digest</b> is defined, it contains the digest of the
|
||||||
|
* router that just gave us this directory. */
|
||||||
|
void directory_has_arrived(time_t now, char *identity_digest) {
|
||||||
or_options_t *options = get_options();
|
or_options_t *options = get_options();
|
||||||
|
|
||||||
log_fn(LOG_INFO, "A directory has arrived.");
|
log_fn(LOG_INFO, "A directory has arrived.");
|
||||||
@ -597,14 +598,26 @@ void directory_has_arrived(time_t now) {
|
|||||||
if (!time_to_fetch_running_routers)
|
if (!time_to_fetch_running_routers)
|
||||||
time_to_fetch_running_routers = now + options->StatusFetchPeriod;
|
time_to_fetch_running_routers = now + options->StatusFetchPeriod;
|
||||||
|
|
||||||
|
if (identity_digest) { /* if this is us, then our dirport is reachable */
|
||||||
|
routerinfo_t *router = router_get_by_digest(identity_digest);
|
||||||
|
if (!router) // XXX
|
||||||
|
log_fn(LOG_WARN,"Roger, router_get_by_digest doesn't find me.");
|
||||||
|
if (router && router_is_me(router)) {
|
||||||
|
log_fn(LOG_NOTICE,"Your DirPort is reachable from the outside. Excellent.");
|
||||||
|
router_dirport_found_reachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (server_mode(options) &&
|
if (server_mode(options) &&
|
||||||
!we_are_hibernating()) { /* connect to the appropriate routers */
|
!we_are_hibernating()) { /* connect to the appropriate routers */
|
||||||
router_retry_connections();
|
router_retry_connections();
|
||||||
|
if (identity_digest) /* we got a fresh directory */
|
||||||
|
consider_testing_reachability();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Perform regular maintenance tasks for a single connection. This
|
/** Perform regular maintenance tasks for a single connection. This
|
||||||
* function gets run once per second per connection by run_housekeeping.
|
* function gets run once per second per connection by run_scheduled_events.
|
||||||
*/
|
*/
|
||||||
static void run_connection_housekeeping(int i, time_t now) {
|
static void run_connection_housekeeping(int i, time_t now) {
|
||||||
cell_t cell;
|
cell_t cell;
|
||||||
@ -648,81 +661,6 @@ static void run_connection_housekeeping(int i, time_t now) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MIN_BW_TO_PUBLISH_DESC 5000 /* 5000 bytes/s sustained */
|
|
||||||
#define MIN_UPTIME_TO_PUBLISH_DESC (30*60) /* half an hour */
|
|
||||||
|
|
||||||
/** Decide if we're a publishable server or just a client. We are a server if:
|
|
||||||
* - We have the AuthoritativeDirectory option set.
|
|
||||||
* or
|
|
||||||
* - We don't have the ClientOnly option set; and
|
|
||||||
* - We have ORPort set; and
|
|
||||||
* - We have been up for at least MIN_UPTIME_TO_PUBLISH_DESC seconds; and
|
|
||||||
* - We have processed some suitable minimum bandwidth recently; and
|
|
||||||
* - We believe we are reachable from the outside.
|
|
||||||
*/
|
|
||||||
static int decide_if_publishable_server(time_t now) {
|
|
||||||
int bw;
|
|
||||||
or_options_t *options = get_options();
|
|
||||||
|
|
||||||
bw = rep_hist_bandwidth_assess();
|
|
||||||
router_set_bandwidth_capacity(bw);
|
|
||||||
|
|
||||||
if (options->ClientOnly)
|
|
||||||
return 0;
|
|
||||||
if (!options->ORPort)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* XXX for now, you're only a server if you're a server */
|
|
||||||
return server_mode(options);
|
|
||||||
|
|
||||||
/* here, determine if we're reachable */
|
|
||||||
if (0) { /* we've recently failed to reach our IP/ORPort from the outside */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bw < MIN_BW_TO_PUBLISH_DESC)
|
|
||||||
return 0;
|
|
||||||
if (options->AuthoritativeDir)
|
|
||||||
return 1;
|
|
||||||
if (stats_n_seconds_working < MIN_UPTIME_TO_PUBLISH_DESC)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return true iff we believe ourselves to be an authoritative
|
|
||||||
* directory server.
|
|
||||||
*/
|
|
||||||
int authdir_mode(or_options_t *options) {
|
|
||||||
return options->AuthoritativeDir != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return true iff we try to stay connected to all ORs at once.
|
|
||||||
*/
|
|
||||||
int clique_mode(or_options_t *options) {
|
|
||||||
return authdir_mode(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return true iff we are trying to be a server.
|
|
||||||
*/
|
|
||||||
int server_mode(or_options_t *options) {
|
|
||||||
return (options->ORPort != 0 || options->ORBindAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Remember if we've advertised ourselves to the dirservers. */
|
|
||||||
static int server_is_advertised=0;
|
|
||||||
|
|
||||||
/** Return true iff we have published our descriptor lately.
|
|
||||||
*/
|
|
||||||
int advertised_server_mode(void) {
|
|
||||||
return server_is_advertised;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return true iff we are trying to be a socks proxy. */
|
|
||||||
int proxy_mode(or_options_t *options) {
|
|
||||||
return (options->SocksPort != 0 || options->SocksBindAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Perform regular maintenance tasks. This function gets run once per
|
/** Perform regular maintenance tasks. This function gets run once per
|
||||||
* second by prepare_for_poll.
|
* second by prepare_for_poll.
|
||||||
*/
|
*/
|
||||||
@ -810,13 +748,7 @@ static void run_scheduled_events(time_t now) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (time_to_force_upload_descriptor < now) {
|
if (time_to_force_upload_descriptor < now) {
|
||||||
if (decide_if_publishable_server(now)) {
|
consider_publishable_server(now, 1);
|
||||||
server_is_advertised = 1;
|
|
||||||
router_rebuild_descriptor(1);
|
|
||||||
router_upload_dir_desc_to_dirservers(1);
|
|
||||||
} else {
|
|
||||||
server_is_advertised = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
rend_cache_clean(); /* this should go elsewhere? */
|
rend_cache_clean(); /* this should go elsewhere? */
|
||||||
|
|
||||||
@ -827,13 +759,7 @@ static void run_scheduled_events(time_t now) {
|
|||||||
* one is inaccurate. */
|
* one is inaccurate. */
|
||||||
if (time_to_check_descriptor < now) {
|
if (time_to_check_descriptor < now) {
|
||||||
time_to_check_descriptor = now + CHECK_DESCRIPTOR_INTERVAL;
|
time_to_check_descriptor = now + CHECK_DESCRIPTOR_INTERVAL;
|
||||||
if (decide_if_publishable_server(now)) {
|
consider_publishable_server(now, 0);
|
||||||
server_is_advertised=1;
|
|
||||||
router_rebuild_descriptor(0);
|
|
||||||
router_upload_dir_desc_to_dirservers(0);
|
|
||||||
} else {
|
|
||||||
server_is_advertised=0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 3a. Every second, we examine pending circuits and prune the
|
/** 3a. Every second, we examine pending circuits and prune the
|
||||||
|
34
src/or/or.h
34
src/or/or.h
@ -381,7 +381,9 @@ typedef enum {
|
|||||||
#define CIRCUIT_PURPOSE_S_CONNECT_REND 15
|
#define CIRCUIT_PURPOSE_S_CONNECT_REND 15
|
||||||
/** Hidden-service-side circuit purpose: at Bob, rendezvous established. */
|
/** Hidden-service-side circuit purpose: at Bob, rendezvous established. */
|
||||||
#define CIRCUIT_PURPOSE_S_REND_JOINED 16
|
#define CIRCUIT_PURPOSE_S_REND_JOINED 16
|
||||||
#define _CIRCUIT_PURPOSE_MAX 16
|
/** A testing circuit; not meant to be used for actual traffic. */
|
||||||
|
#define CIRCUIT_PURPOSE_TESTING 17
|
||||||
|
#define _CIRCUIT_PURPOSE_MAX 17
|
||||||
|
|
||||||
/** True iff the circuit purpose <b>p</b> is for a circuit at the OP
|
/** True iff the circuit purpose <b>p</b> is for a circuit at the OP
|
||||||
* that this OP has originated. */
|
* that this OP has originated. */
|
||||||
@ -1378,6 +1380,10 @@ void directory_post_to_dirservers(uint8_t purpose, const char *payload,
|
|||||||
size_t payload_len);
|
size_t payload_len);
|
||||||
void directory_get_from_dirserver(uint8_t purpose, const char *resource,
|
void directory_get_from_dirserver(uint8_t purpose, const char *resource,
|
||||||
int retry_if_no_servers);
|
int retry_if_no_servers);
|
||||||
|
void directory_initiate_command_router(routerinfo_t *router, uint8_t purpose,
|
||||||
|
int private_connection, const char *resource,
|
||||||
|
const char *payload, size_t payload_len);
|
||||||
|
|
||||||
int parse_http_response(const char *headers, int *code, time_t *date,
|
int parse_http_response(const char *headers, int *code, time_t *date,
|
||||||
int *compression);
|
int *compression);
|
||||||
|
|
||||||
@ -1455,13 +1461,7 @@ void connection_stop_writing(connection_t *conn);
|
|||||||
void connection_start_writing(connection_t *conn);
|
void connection_start_writing(connection_t *conn);
|
||||||
|
|
||||||
void directory_all_unreachable(time_t now);
|
void directory_all_unreachable(time_t now);
|
||||||
void directory_has_arrived(time_t now);
|
void directory_has_arrived(time_t now, char *identity_digest);
|
||||||
|
|
||||||
int authdir_mode(or_options_t *options);
|
|
||||||
int clique_mode(or_options_t *options);
|
|
||||||
int server_mode(or_options_t *options);
|
|
||||||
int advertised_server_mode(void);
|
|
||||||
int proxy_mode(or_options_t *options);
|
|
||||||
|
|
||||||
int control_signal_act(int the_signal);
|
int control_signal_act(int the_signal);
|
||||||
void handle_signals(int is_parent);
|
void handle_signals(int is_parent);
|
||||||
@ -1624,11 +1624,21 @@ void set_identity_key(crypto_pk_env_t *k);
|
|||||||
crypto_pk_env_t *get_identity_key(void);
|
crypto_pk_env_t *get_identity_key(void);
|
||||||
int identity_key_is_set(void);
|
int identity_key_is_set(void);
|
||||||
void dup_onion_keys(crypto_pk_env_t **key, crypto_pk_env_t **last);
|
void dup_onion_keys(crypto_pk_env_t **key, crypto_pk_env_t **last);
|
||||||
int init_keys(void);
|
|
||||||
crypto_pk_env_t *init_key_from_file(const char *fname);
|
|
||||||
void rotate_onion_key(void);
|
void rotate_onion_key(void);
|
||||||
void router_set_bandwidth_capacity(int bw);
|
crypto_pk_env_t *init_key_from_file(const char *fname);
|
||||||
int router_get_bandwidth_capacity(void);
|
int init_keys(void);
|
||||||
|
|
||||||
|
void consider_testing_reachability(void);
|
||||||
|
void router_orport_found_reachable(void);
|
||||||
|
void router_dirport_found_reachable(void);
|
||||||
|
void server_has_changed_ip(void);
|
||||||
|
void consider_publishable_server(time_t now, int force);
|
||||||
|
|
||||||
|
int authdir_mode(or_options_t *options);
|
||||||
|
int clique_mode(or_options_t *options);
|
||||||
|
int server_mode(or_options_t *options);
|
||||||
|
int advertised_server_mode(void);
|
||||||
|
int proxy_mode(or_options_t *options);
|
||||||
|
|
||||||
void router_retry_connections(void);
|
void router_retry_connections(void);
|
||||||
int router_is_clique_mode(routerinfo_t *router);
|
int router_is_clique_mode(routerinfo_t *router);
|
||||||
|
129
src/or/router.c
129
src/or/router.c
@ -143,19 +143,6 @@ void rotate_onion_key(void)
|
|||||||
log_fn(LOG_WARN, "Couldn't rotate onion key.");
|
log_fn(LOG_WARN, "Couldn't rotate onion key.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The latest calculated bandwidth usage for our node. */
|
|
||||||
static int bw_capacity = 0;
|
|
||||||
/** Tuck <b>bw</b> away so we can produce it when somebody
|
|
||||||
* calls router_get_bandwidth_capacity() below.
|
|
||||||
*/
|
|
||||||
void router_set_bandwidth_capacity(int bw) {
|
|
||||||
bw_capacity = bw;
|
|
||||||
}
|
|
||||||
/** Return the value we tucked away above, or zero by default. */
|
|
||||||
int router_get_bandwidth_capacity(void) {
|
|
||||||
return bw_capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read an RSA secret key key from a file that was once named fname_old,
|
/* Read an RSA secret key key from a file that was once named fname_old,
|
||||||
* but is now named fname_new. Rename the file from old to new as needed.
|
* but is now named fname_new. Rename the file from old to new as needed.
|
||||||
*/
|
*/
|
||||||
@ -382,6 +369,120 @@ int init_keys(void) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Keep track of whether we should upload our server descriptor,
|
||||||
|
* and what type of server we are.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Whether we can reach our ORPort from the outside. */
|
||||||
|
static int can_reach_or_port = 0;
|
||||||
|
/** Whether we can reach our DirPort from the outside. */
|
||||||
|
static int can_reach_dir_port = 0;
|
||||||
|
|
||||||
|
void consider_testing_reachability(void) {
|
||||||
|
routerinfo_t *me = router_get_my_routerinfo();
|
||||||
|
|
||||||
|
if (!can_reach_or_port) {
|
||||||
|
circuit_launch_by_identity(CIRCUIT_PURPOSE_TESTING, me->identity_digest, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!can_reach_dir_port && me->dir_port) {
|
||||||
|
if (me) {
|
||||||
|
directory_initiate_command_router(me, DIR_PURPOSE_FETCH_DIR, 1, NULL, NULL, 0);
|
||||||
|
} else {
|
||||||
|
log_fn(LOG_NOTICE,"Delaying checking DirPort reachability; can't build descriptor.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Annotate that we found our ORPort reachable. */
|
||||||
|
void router_orport_found_reachable(void) {
|
||||||
|
can_reach_or_port = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Annotate that we found our DirPort reachable. */
|
||||||
|
void router_dirport_found_reachable(void) {
|
||||||
|
can_reach_dir_port = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Our router has just moved to a new IP. Reset stats. */
|
||||||
|
void server_has_changed_ip(void) {
|
||||||
|
stats_n_seconds_working = 0;
|
||||||
|
can_reach_or_port = 0;
|
||||||
|
can_reach_dir_port = 0;
|
||||||
|
mark_my_descriptor_dirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return true iff we believe ourselves to be an authoritative
|
||||||
|
* directory server.
|
||||||
|
*/
|
||||||
|
int authdir_mode(or_options_t *options) {
|
||||||
|
return options->AuthoritativeDir != 0;
|
||||||
|
}
|
||||||
|
/** Return true iff we try to stay connected to all ORs at once.
|
||||||
|
*/
|
||||||
|
int clique_mode(or_options_t *options) {
|
||||||
|
return authdir_mode(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return true iff we are trying to be a server.
|
||||||
|
*/
|
||||||
|
int server_mode(or_options_t *options) {
|
||||||
|
return (options->ORPort != 0 || options->ORBindAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Remember if we've advertised ourselves to the dirservers. */
|
||||||
|
static int server_is_advertised=0;
|
||||||
|
|
||||||
|
/** Return true iff we have published our descriptor lately.
|
||||||
|
*/
|
||||||
|
int advertised_server_mode(void) {
|
||||||
|
return server_is_advertised;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_server_advertised(int s) {
|
||||||
|
server_is_advertised = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return true iff we are trying to be a socks proxy. */
|
||||||
|
int proxy_mode(or_options_t *options) {
|
||||||
|
return (options->SocksPort != 0 || options->SocksBindAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Decide if we're a publishable server or just a client. We are a server if:
|
||||||
|
* - We have the AuthoritativeDirectory option set.
|
||||||
|
* or
|
||||||
|
* - We don't have the ClientOnly option set; and
|
||||||
|
* - We have ORPort set; and
|
||||||
|
* - We believe we are reachable from the outside.
|
||||||
|
*/
|
||||||
|
static int decide_if_publishable_server(time_t now) {
|
||||||
|
or_options_t *options = get_options();
|
||||||
|
|
||||||
|
if (options->ClientOnly)
|
||||||
|
return 0;
|
||||||
|
if (!server_mode(options))
|
||||||
|
return 0;
|
||||||
|
if (options->AuthoritativeDir)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!can_reach_or_port)
|
||||||
|
return 0;
|
||||||
|
if (options->DirPort && !can_reach_dir_port)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void consider_publishable_server(time_t now, int force) {
|
||||||
|
if (decide_if_publishable_server(now)) {
|
||||||
|
set_server_advertised(1);
|
||||||
|
router_rebuild_descriptor(force);
|
||||||
|
router_upload_dir_desc_to_dirservers(force);
|
||||||
|
} else {
|
||||||
|
set_server_advertised(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clique maintenance
|
* Clique maintenance
|
||||||
*/
|
*/
|
||||||
@ -568,7 +669,7 @@ int router_rebuild_descriptor(int force) {
|
|||||||
ri->platform = tor_strdup(platform);
|
ri->platform = tor_strdup(platform);
|
||||||
ri->bandwidthrate = (int)options->BandwidthRate;
|
ri->bandwidthrate = (int)options->BandwidthRate;
|
||||||
ri->bandwidthburst = (int)options->BandwidthBurst;
|
ri->bandwidthburst = (int)options->BandwidthBurst;
|
||||||
ri->bandwidthcapacity = hibernating ? 0 : router_get_bandwidth_capacity();
|
ri->bandwidthcapacity = hibernating ? 0 : rep_hist_bandwidth_assess();
|
||||||
router_add_exit_policy_from_config(ri);
|
router_add_exit_policy_from_config(ri);
|
||||||
if (desc_routerinfo) /* inherit values */
|
if (desc_routerinfo) /* inherit values */
|
||||||
ri->is_verified = desc_routerinfo->is_verified;
|
ri->is_verified = desc_routerinfo->is_verified;
|
||||||
|
@ -66,7 +66,7 @@ int router_reload_router_list(void)
|
|||||||
if (routerlist &&
|
if (routerlist &&
|
||||||
((routerlist->published_on > time(NULL) - MIN_ONION_KEY_LIFETIME/2)
|
((routerlist->published_on > time(NULL) - MIN_ONION_KEY_LIFETIME/2)
|
||||||
|| is_recent)) {
|
|| is_recent)) {
|
||||||
directory_has_arrived(st.st_mtime); /* do things we've been waiting to do */
|
directory_has_arrived(st.st_mtime, NULL); /* do things we've been waiting to do */
|
||||||
}
|
}
|
||||||
tor_free(s);
|
tor_free(s);
|
||||||
}
|
}
|
||||||
@ -634,11 +634,11 @@ routerinfo_t *router_get_by_digest(const char *digest) {
|
|||||||
routerinfo_t *router;
|
routerinfo_t *router;
|
||||||
|
|
||||||
tor_assert(digest);
|
tor_assert(digest);
|
||||||
if (!routerlist) return NULL;
|
|
||||||
if (server_mode(get_options()) &&
|
if (server_mode(get_options()) &&
|
||||||
(router = router_get_my_routerinfo()) &&
|
(router = router_get_my_routerinfo()) &&
|
||||||
!memcmp(digest, router->identity_digest, DIGEST_LEN))
|
!memcmp(digest, router->identity_digest, DIGEST_LEN))
|
||||||
return router;
|
return router;
|
||||||
|
if (!routerlist) return NULL;
|
||||||
|
|
||||||
for (i=0;i<smartlist_len(routerlist->routers);i++) {
|
for (i=0;i<smartlist_len(routerlist->routers);i++) {
|
||||||
router = smartlist_get(routerlist->routers, i);
|
router = smartlist_get(routerlist->routers, i);
|
||||||
|
Loading…
Reference in New Issue
Block a user