aboutsummaryrefslogtreecommitdiff
path: root/src/or/circuituse.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2005-06-29 21:46:55 +0000
committerNick Mathewson <nickm@torproject.org>2005-06-29 21:46:55 +0000
commitec83652357ba4772203e32f02dcc69910b964079 (patch)
treee5a5113d256fac9d34bdecaeaf77134998d570bc /src/or/circuituse.c
parent0505b31933ce386ad0ac11855d3f0a8d0ba17b75 (diff)
downloadtor-ec83652357ba4772203e32f02dcc69910b964079.tar.gz
tor-ec83652357ba4772203e32f02dcc69910b964079.zip
Logic to implement rendezvous/introduction via unknown servers.
- Add a new extend_info_t datatype to hold information needed to extend a circuit (addr,port,keyid,onion_key). Use it in cpath and build_state. Make appropriate functions take or return it instead of routerinfo_t or keyid. - #if 0 needless check in circuit_get_by_edge_conn; if nobody triggers this error in 0.1.0.10, nobody will trigger it. - Implement new hidden service descriptor format, which contains "extend info" for introduction points, along with protocol version list. - Parse new format. - Generate new format - Cache old and new formats alongside each other. - Directories serve "old" format if asked in old way, "newest available" format if asked in new way. - Use new format to find introduction points if possible; otherwise fall back. Keep nickname lists and extendinfo lists in sync. - Tests for new format. - Implement new "v2" INTRODUCE cell format. - Accept new format - Use new format if we have a versioned service descriptor that says the server accepts the new format. - Add documentation for functions and data types. svn:r4506
Diffstat (limited to 'src/or/circuituse.c')
-rw-r--r--src/or/circuituse.c88
1 files changed, 52 insertions, 36 deletions
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 3f19ae0090..55ae45994e 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -74,12 +74,7 @@ circuit_is_acceptable(circuit_t *circ,
* circuit, it's the magical extra bob hop. so just check the nickname
* of the one we meant to finish at.
*/
- exitrouter = router_get_by_digest(circ->build_state->chosen_exit_digest);
-
- if (!exitrouter) {
- log_fn(LOG_INFO,"Skipping broken circ (exit router vanished)");
- return 0; /* this circuit is screwed and doesn't know it yet */
- }
+ exitrouter = build_state_get_exit_router(circ->build_state);
if (!circ->build_state->need_uptime &&
smartlist_string_num_isin(get_options()->LongLivedPorts,
@@ -87,6 +82,11 @@ circuit_is_acceptable(circuit_t *circ,
return 0;
if (purpose == CIRCUIT_PURPOSE_C_GENERAL) {
+ if (!exitrouter) {
+ log_fn(LOG_DEBUG,"Not considering circuit with unknown router.");
+ return 0; /* this circuit is screwed and doesn't know it yet,
+ * or is a rendezvous circuit. */
+ }
if (!connection_ap_can_use_exit(conn, exitrouter)) {
/* can't exit from this router */
return 0;
@@ -296,7 +296,7 @@ circuit_stream_is_being_handled(connection_t *conn, uint16_t port, int min)
circ->purpose == CIRCUIT_PURPOSE_C_GENERAL &&
(!circ->timestamp_dirty ||
circ->timestamp_dirty + get_options()->MaxCircuitDirtiness < now)) {
- exitrouter = router_get_by_digest(circ->build_state->chosen_exit_digest);
+ exitrouter = build_state_get_exit_router(circ->build_state);
if (exitrouter &&
(!need_uptime || circ->build_state->need_uptime)) {
int ok;
@@ -682,7 +682,7 @@ circuit_build_failed(circuit_t *circ)
/* Don't increment failure count, since Alice may have picked
* the rendezvous point maliciously */
log_fn(LOG_INFO,"Couldn't connect to Alice's chosen rend point %s (%s hop failed).",
- circ->build_state->chosen_exit_name,
+ build_state_get_exit_nickname(circ->build_state),
failed_at_last_hop?"last":"non-last");
rend_service_relaunch_rendezvous(circ);
break;
@@ -703,12 +703,34 @@ static int did_circs_fail_last_period = 0;
* success. */
#define MAX_CIRCUIT_FAILURES 5
-/** Launch a new circuit based on our arguments. */
+/** Launch a new circuit; see circuit_launch_by_extend_info for details on
+ * arguments. */
circuit_t *
circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit,
int need_uptime, int need_capacity, int internal)
{
circuit_t *circ;
+ extend_info_t *info = NULL;
+ if (exit)
+ info = extend_info_from_router(exit);
+ circ = circuit_launch_by_extend_info(purpose, info, need_uptime, need_capacity,
+ internal);
+ if (info)
+ extend_info_free(info);
+ return circ;
+}
+
+/** Launch a new circuit with purpose <b>purpose</b> and exit node <b>info</b>
+ * (or NULL to select a random exit node). If <b>need_uptime</b> is true,
+ * choose among routers with high uptime. If <b>need_capacity</b> is true,
+ * choose among routers with high bandwidth. If <b>internal</b> is true, the
+ * last hop need not be an exit node. Return the newly allocated circuit on
+ * success, or NULL on failure. */
+circuit_t *
+circuit_launch_by_extend_info(uint8_t purpose, extend_info_t *info,
+ int need_uptime, int need_capacity, int internal)
+{
+ circuit_t *circ;
if (!has_fetched_directory) {
log_fn(LOG_DEBUG,"Haven't fetched directory yet; canceling circuit launch.");
@@ -721,7 +743,7 @@ circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit,
if ((circ = circuit_get_clean_open(CIRCUIT_PURPOSE_C_GENERAL, need_uptime,
need_capacity, internal))) {
log_fn(LOG_INFO,"Cannibalizing circ '%s' for purpose %d",
- circ->build_state->chosen_exit_name, purpose);
+ build_state_get_exit_nickname(circ->build_state), purpose);
circ->purpose = purpose;
/* reset the birth date of this circ, else expire_building
* will see it and think it's been trying to build since it
@@ -740,8 +762,8 @@ circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit,
case CIRCUIT_PURPOSE_C_INTRODUCING:
case CIRCUIT_PURPOSE_S_CONNECT_REND:
/* need to add a new hop */
- tor_assert(exit);
- if (circuit_extend_to_new_exit(circ, exit) < 0)
+ tor_assert(info);
+ if (circuit_extend_to_new_exit(circ, info) < 0)
return NULL;
break;
default:
@@ -762,11 +784,12 @@ circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit,
}
/* try a circ. if it fails, circuit_mark_for_close will increment n_circuit_failures */
- return circuit_establish_circuit(purpose, exit,
+ return circuit_establish_circuit(purpose, info,
need_uptime, need_capacity, internal);
}
-/** Launch a new circuit and return a pointer to it. Return NULL if you failed. */
+/** Launch a new circuit; see circuit_launch_by_extend_info for details on
+ * arguments. */
circuit_t *
circuit_launch_by_nickname(uint8_t purpose, const char *exit_nickname,
int need_uptime, int need_capacity, int internal)
@@ -867,30 +890,22 @@ circuit_get_open_circ_or_launch(connection_t *conn,
/* is one already on the way? */
circ = circuit_get_best(conn, 0, desired_circuit_purpose);
if (!circ) {
- char *exitname=NULL;
+ extend_info_t *extend_info=NULL;
uint8_t new_circ_purpose;
int is_internal;
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
/* need to pick an intro point */
-try_an_intro_point:
- exitname = rend_client_get_random_intro(conn->rend_query);
- if (!exitname) {
+ extend_info = rend_client_get_random_intro(conn->rend_query);
+ if (!extend_info) {
log_fn(LOG_INFO,"No intro points for '%s': refetching service descriptor.",
safe_str(conn->rend_query));
rend_client_refetch_renddesc(conn->rend_query);
conn->state = AP_CONN_STATE_RENDDESC_WAIT;
return 0;
}
- if (!router_get_by_nickname(exitname)) {
- log_fn(LOG_NOTICE,"Advertised intro point '%s' is not recognized for hidserv address '%s'. Skipping over.",
- exitname, safe_str(conn->rend_query));
- rend_client_remove_intro_point(exitname, conn->rend_query);
- tor_free(exitname);
- goto try_an_intro_point;
- }
log_fn(LOG_INFO,"Chose %s as intro point for %s.",
- exitname, safe_str(conn->rend_query));
+ extend_info->nickname, safe_str(conn->rend_query));
}
/* If we have specified a particular exit node for our
@@ -898,13 +913,13 @@ try_an_intro_point:
*/
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL) {
if (conn->chosen_exit_name) {
- exitname = tor_strdup(conn->chosen_exit_name);
- if (!router_get_by_nickname(exitname)) {
+ routerinfo_t *r;
+ if (!(r = router_get_by_nickname(conn->chosen_exit_name))) {
log_fn(LOG_NOTICE,"Requested exit point '%s' is not known. Closing.",
- exitname);
- tor_free(exitname);
+ conn->chosen_exit_name);
return -1;
}
+ extend_info = extend_info_from_router(r);
}
}
@@ -916,9 +931,10 @@ try_an_intro_point:
new_circ_purpose = desired_circuit_purpose;
is_internal = (new_circ_purpose != CIRCUIT_PURPOSE_C_GENERAL || is_resolve);
- circ = circuit_launch_by_nickname(new_circ_purpose, exitname, need_uptime,
- 1, is_internal);
- tor_free(exitname);
+ circ = circuit_launch_by_extend_info(
+ new_circ_purpose, extend_info, need_uptime, 1, is_internal);
+ if (extend_info)
+ extend_info_free(extend_info);
if (desired_circuit_purpose != CIRCUIT_PURPOSE_C_GENERAL) {
/* help predict this next time */
@@ -989,18 +1005,18 @@ consider_recording_trackhost(connection_t *conn, circuit_t *circ)
}
});
- if (!found_needle)
+ if (!found_needle || !circ->build_state->chosen_exit)
return;
/* Add this exit/hostname pair to the addressmap. */
len = strlen(conn->socks_request->address) + 1 /* '.' */ +
- strlen(circ->build_state->chosen_exit_name) + 1 /* '.' */ +
+ strlen(circ->build_state->chosen_exit->nickname) + 1 /* '.' */ +
strlen("exit") + 1 /* '\0' */;
new_address = tor_malloc(len);
tor_snprintf(new_address, len, "%s.%s.exit",
conn->socks_request->address,
- circ->build_state->chosen_exit_name);
+ circ->build_state->chosen_exit->nickname);
addressmap_register(conn->socks_request->address, new_address,
time(NULL) + options->TrackHostExitsExpire);