mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 13:53:31 +01:00
Let the controller specify HOP=%d as an argument to ATTACHSTREAM,
so we can exit from the middle of the circuit. svn:r10056
This commit is contained in:
parent
2711ac2f62
commit
5ba4eaba1c
10
ChangeLog
10
ChangeLog
@ -60,12 +60,16 @@ Changes in version 0.2.0.1-alpha - 2007-??-??
|
||||
documents; authorities do not yet cache them.) [Partially implements
|
||||
proposal 104.]
|
||||
|
||||
o Minor features (other):
|
||||
- Correctly report Windows 95 OSR2 and Windows 98 SE.
|
||||
- More unit tests.
|
||||
o Minor features (controller):
|
||||
- Add a new config option __DisablePredictedCircuits designed for
|
||||
use by the controller, when we don't want Tor to build any circuits
|
||||
preemptively.
|
||||
- Let the controller specify HOP=%d as an argument to ATTACHSTREAM,
|
||||
so we can exit from the middle of the circuit.
|
||||
|
||||
o Minor features (other):
|
||||
- Correctly report Windows 95 OSR2 and Windows 98 SE.
|
||||
- More unit tests.
|
||||
|
||||
o Removed features:
|
||||
- Removed support for the old binary "version 0" controller protocol.
|
||||
|
@ -535,7 +535,7 @@ $Id$
|
||||
3.13. ATTACHSTREAM
|
||||
|
||||
Sent from the client to the server. The syntax is:
|
||||
"ATTACHSTREAM" SP StreamID SP CircuitID CRLF
|
||||
"ATTACHSTREAM" SP StreamID SP CircuitID ["HOP=" HopNum] CRLF
|
||||
|
||||
This message informs the server that the specified stream should be
|
||||
associated with the specified circuit. Each stream may be associated with
|
||||
@ -547,6 +547,9 @@ $Id$
|
||||
If the circuit ID is 0, responsibility for attaching the given stream is
|
||||
returned to Tor.
|
||||
|
||||
If HOP=HopNum is specified, Tor will choose the HopNumth hop in the
|
||||
circuit as the exit node, rather than the last node in the circuit.
|
||||
|
||||
Tor responds with "250 OK" if it can attach the stream, 552 if the circuit
|
||||
or stream didn't exist, or 551 if the stream couldn't be attached for
|
||||
another reason.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user