diff options
author | Roger Dingledine <arma@torproject.org> | 2007-04-30 11:10:45 +0000 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2007-04-30 11:10:45 +0000 |
commit | 5ba4eaba1cfe1858cc152a9945d0bb6c2d1838b4 (patch) | |
tree | b92b562a0567adea1d6b2855e5ad1243f7aa53fb /src | |
parent | 2711ac2f6265eb981f1f7b5679fecd6af8682c3c (diff) | |
download | tor-5ba4eaba1cfe1858cc152a9945d0bb6c2d1838b4.tar.gz tor-5ba4eaba1cfe1858cc152a9945d0bb6c2d1838b4.zip |
Let the controller specify HOP=%d as an argument to ATTACHSTREAM,
so we can exit from the middle of the circuit.
svn:r10056
Diffstat (limited to 'src')
-rw-r--r-- | src/or/circuitlist.c | 16 | ||||
-rw-r--r-- | src/or/circuituse.c | 24 | ||||
-rw-r--r-- | src/or/connection_edge.c | 13 | ||||
-rw-r--r-- | src/or/control.c | 29 | ||||
-rw-r--r-- | src/or/or.h | 7 |
5 files changed, 68 insertions, 21 deletions
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 73ca7e1fa0..839d2b6dc7 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -844,6 +844,22 @@ circuit_get_cpath_len(origin_circuit_t *circ) return n; } +/** Return the <b>hopnum</b>th hop in <b>circ</b>->cpath, or NULL if there + * aren't that many hops in the list. */ +crypt_path_t * +circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum) +{ + if (circ && circ->cpath) { + crypt_path_t *cpath, *cpath_next = NULL; + for (cpath = circ->cpath; cpath_next != circ->cpath; cpath = cpath_next) { + cpath_next = cpath->next; + if (--hopnum <= 0) + return cpath; + } + } + return NULL; +} + /** Go through the circuitlist; mark-for-close each circuit that starts * at us but has not yet been used. */ void diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 6bfe087100..c2faa109b5 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -1101,7 +1101,8 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, * circ's cpath. */ static void -link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ) +link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ, + crypt_path_t *cpath) { /* add it into the linked list of streams on this circuit */ log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %d.", @@ -1113,10 +1114,14 @@ link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ) /* assert_connection_ok(conn, time(NULL)); */ circ->p_streams = apconn; - tor_assert(circ->cpath); - tor_assert(circ->cpath->prev); - tor_assert(circ->cpath->prev->state == CPATH_STATE_OPEN); - apconn->cpath_layer = circ->cpath->prev; + if (cpath) { /* we were given one; use it */ + apconn->cpath_layer = cpath; + } else { /* use the last hop in the circuit */ + tor_assert(circ->cpath); + tor_assert(circ->cpath->prev); + tor_assert(circ->cpath->prev->state == CPATH_STATE_OPEN); + apconn->cpath_layer = circ->cpath->prev; + } } /** If an exit wasn't specifically chosen, save the history for future @@ -1172,7 +1177,8 @@ consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ) * for connection_ap_handshake_attach_circuit. */ int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn, - origin_circuit_t *circ) + origin_circuit_t *circ, + crypt_path_t *cpath) { tor_assert(conn); tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT || @@ -1186,7 +1192,7 @@ connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn, if (!circ->_base.timestamp_dirty) circ->_base.timestamp_dirty = time(NULL); - link_apconn_to_circ(conn, circ); + link_apconn_to_circ(conn, circ, cpath); tor_assert(conn->socks_request); switch (conn->socks_request->command) { case SOCKS_COMMAND_CONNECT: @@ -1269,7 +1275,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn) circuit_log_path(LOG_INFO,LD_APP|LD_CIRC,circ); /* We have found a suitable circuit for our conn. Hurray. */ - return connection_ap_handshake_attach_chosen_circuit(conn, circ); + return connection_ap_handshake_attach_chosen_circuit(conn, circ, NULL); } else { /* we're a rendezvous conn */ origin_circuit_t *rendcirc=NULL, *introcirc=NULL; @@ -1295,7 +1301,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn) * feasibility, at this point. */ rendcirc->_base.timestamp_dirty = time(NULL); - link_apconn_to_circ(conn, rendcirc); + link_apconn_to_circ(conn, rendcirc, NULL); if (connection_ap_handshake_send_begin(conn) < 0) return 0; /* already marked, let them fade away */ return 1; diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 0e5aa8fd72..035eecafc1 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -1181,7 +1181,8 @@ addressmap_get_mappings(smartlist_t *sl, time_t min_expires, */ int connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, - origin_circuit_t *circ) + origin_circuit_t *circ, + crypt_path_t *cpath) { socks_request_t *socks = conn->socks_request; hostname_type_t addresstype; @@ -1337,8 +1338,8 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, tor_fragile_assert(); } conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT; - if ((circ && - connection_ap_handshake_attach_chosen_circuit(conn, circ) < 0) || + if ((circ && connection_ap_handshake_attach_chosen_circuit( + conn, circ, cpath) < 0) || (!circ && connection_ap_handshake_attach_circuit(conn) < 0)) { connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH); @@ -1583,7 +1584,7 @@ connection_ap_handshake_process_socks(edge_connection_t *conn) conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT; return 0; } - return connection_ap_handshake_rewrite_and_attach(conn, NULL); + return connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL); } /** connection_init_accepted_conn() found a new trans AP conn. @@ -1625,7 +1626,7 @@ connection_ap_process_transparent(edge_connection_t *conn) conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT; return 0; } - return connection_ap_handshake_rewrite_and_attach(conn, NULL); + return connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL); } /** connection_edge_process_inbuf() found a conn in state natd_wait. See if @@ -1704,7 +1705,7 @@ connection_ap_process_natd(edge_connection_t *conn) } conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT; - return connection_ap_handshake_rewrite_and_attach(conn, NULL); + return connection_ap_handshake_rewrite_and_attach(conn, NULL, NULL); } /** Iterate over the two bytes of stream_id until we get one that is not diff --git a/src/or/control.c b/src/or/control.c index beeb1727fb..f965b7035a 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1897,6 +1897,8 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len, origin_circuit_t *circ = NULL; int zero_circ; smartlist_t *args; + crypt_path_t *cpath=NULL; + int hop=0, hop_line_ok=1; (void) len; args = getargs_helper("ATTACHSTREAM", conn, body, 2, -1); @@ -1911,10 +1913,20 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len, } else if (!zero_circ && !(circ = get_circ(smartlist_get(args, 1)))) { connection_printf_to_buf(conn, "552 Unknown circuit \"%s\"\r\n", (char*)smartlist_get(args, 1)); + } else if (circ && smartlist_len(args) > 2) { + char *hopstring = smartlist_get(args, 2); + if (!strcasecmpstart(hopstring, "HOP=")) { + hopstring += strlen("HOP="); + hop = tor_parse_ulong(hopstring, 10, 0, ULONG_MAX, + &hop_line_ok, NULL); + if (!hop_line_ok) { /* broken hop line */ + connection_printf_to_buf(conn, "552 Bad value hop=%s\r\n", hopstring); + } + } } SMARTLIST_FOREACH(args, char *, cp, tor_free(cp)); smartlist_free(args); - if (!ap_conn || (!zero_circ && !circ)) + if (!ap_conn || (!zero_circ && !circ) || !hop_line_ok) return 0; if (ap_conn->_base.state != AP_CONN_STATE_CONTROLLER_WAIT && @@ -1940,16 +1952,25 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len, if (circ && (circ->_base.state != CIRCUIT_STATE_OPEN)) { connection_write_str_to_buf( - "551 Can't attach stream to non-open, origin circuit\r\n", + "551 Can't attach stream to non-open origin circuit\r\n", conn); return 0; } - if (circ && circuit_get_cpath_len(circ) < 2) { + if (circ && (circuit_get_cpath_len(circ)<2 || hop==1)) { connection_write_str_to_buf( "551 Can't attach stream to one-hop circuit.\r\n", conn); return 0; } - if (connection_ap_handshake_rewrite_and_attach(ap_conn, circ) < 0) { + if (circ && hop>0) { + /* find this hop in the circuit, and set cpath */ + cpath = circuit_get_cpath_hop(circ, hop); + if (!cpath) { + connection_printf_to_buf(conn, + "551 Circuit doesn't have %d hops.\r\n", hop); + return 0; + } + } + if (connection_ap_handshake_rewrite_and_attach(ap_conn, circ, cpath) < 0) { connection_write_str_to_buf("551 Unable to attach stream\r\n", conn); return 0; } diff --git a/src/or/or.h b/src/or/or.h index 91f85f3257..18a09560b4 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2085,6 +2085,7 @@ void circuit_expire_all_dirty_circs(void); void _circuit_mark_for_close(circuit_t *circ, int reason, int line, const char *file); int circuit_get_cpath_len(origin_circuit_t *circ); +crypt_path_t *circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum); void circuit_get_all_pending_on_or_conn(smartlist_t *out, or_connection_t *or_conn); int circuit_count_pending_on_or_conn(or_connection_t *or_conn); @@ -2127,7 +2128,8 @@ origin_circuit_t *circuit_launch_by_router(uint8_t purpose, int is_internal); void circuit_reset_failure_count(int timeout); int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn, - origin_circuit_t *circ); + origin_circuit_t *circ, + crypt_path_t *cpath); int connection_ap_handshake_attach_circuit(edge_connection_t *conn); /********************************* command.c ***************************/ @@ -2322,7 +2324,8 @@ const char *addressmap_register_virtual_address(int type, char *new_address); void addressmap_get_mappings(smartlist_t *sl, time_t min_expires, time_t max_expires); int connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, - origin_circuit_t *circ); + origin_circuit_t *circ, + crypt_path_t *cpath); void set_exit_redirects(smartlist_t *lst); typedef enum hostname_type_t { |