summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/or/circuit.c4
-rw-r--r--src/or/connection_edge.c68
-rw-r--r--src/or/rendclient.c2
-rw-r--r--src/or/rendcommon.c8
4 files changed, 63 insertions, 19 deletions
diff --git a/src/or/circuit.c b/src/or/circuit.c
index f47f486a71..c39f8b3171 100644
--- a/src/or/circuit.c
+++ b/src/or/circuit.c
@@ -1534,8 +1534,8 @@ void assert_cpath_layer_ok(const crypt_path_t *cp)
{
assert(cp->f_crypto);
assert(cp->b_crypto);
- assert(cp->addr);
- assert(cp->port);
+// assert(cp->addr); /* these are zero for rendezvous extra-hops */
+// assert(cp->port);
switch(cp->state)
{
case CPATH_STATE_CLOSED:
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 4dd2c3ea97..d98cde62d2 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -11,6 +11,7 @@ extern char *conn_state_to_string[][_CONN_TYPE_MAX+1];
static int connection_ap_handshake_process_socks(connection_t *conn);
static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
+static int connection_exit_set_rendezvous_addr_port(connection_t *conn);
static void connection_edge_consider_sending_sendme(connection_t *conn);
static uint32_t client_dns_lookup_entry(const char *address);
@@ -144,8 +145,9 @@ int connection_edge_end(connection_t *conn, char reason, crypt_path_t *cpath_lay
payload[0] = reason;
if(reason == END_STREAM_REASON_EXITPOLICY) {
+ /* this is safe even for rend circs, because they never fail
+ * because of exitpolicy */
set_uint32(payload+1, htonl(conn->addr));
-// *(uint32_t *)(payload+1) = htonl(conn->addr);
payload_len += 4;
}
@@ -281,7 +283,8 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
log_fn(LOG_INFO,"Got a relay-level padding cell. Dropping.");
return 0;
case RELAY_COMMAND_BEGIN:
- if(edge_type == EDGE_AP) {
+ if (edge_type == EDGE_AP &&
+ circ->purpose != CIRCUIT_PURPOSE_S_REND_JOINED) {
log_fn(LOG_WARN,"relay begin request unsupported at AP. Dropping.");
return 0;
}
@@ -479,10 +482,16 @@ int connection_edge_finished_flushing(connection_t *conn) {
if(connection_wants_to_flush(conn)) /* in case there are any queued relay cells */
connection_start_writing(conn);
/* deliver a 'connected' relay cell back through the circuit. */
- *(uint32_t*)connected_payload = htonl(conn->addr);
- if(connection_edge_send_command(conn, circuit_get_by_conn(conn),
- RELAY_COMMAND_CONNECTED, connected_payload, 4, NULL) < 0)
- return 0; /* circuit is closed, don't continue */
+ if(*conn->rend_query) { /* rendezvous stream */
+ if(connection_edge_send_command(conn, circuit_get_by_conn(conn),
+ RELAY_COMMAND_CONNECTED, NULL, 0, conn->cpath_layer) < 0)
+ return 0; /* circuit is closed, don't continue */
+ } else {
+ *(uint32_t*)connected_payload = htonl(conn->addr);
+ if(connection_edge_send_command(conn, circuit_get_by_conn(conn),
+ RELAY_COMMAND_CONNECTED, connected_payload, 4, conn->cpath_layer) < 0)
+ return 0; /* circuit is closed, don't continue */
+ }
assert(conn->package_window > 0);
return connection_edge_process_inbuf(conn); /* in case the server has written anything */
case AP_CONN_STATE_OPEN:
@@ -1108,9 +1117,7 @@ static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) {
n_stream = connection_new(CONN_TYPE_EXIT);
n_stream->stream_id = rh.stream_id;
- n_stream->address = tor_strdup(cell->payload + RELAY_HEADER_SIZE);
n_stream->port = atoi(colon+1);
- n_stream->state = EXIT_CONN_STATE_RESOLVING;
/* leave n_stream->s at -1, because it's not yet valid */
n_stream->package_window = STREAMWINDOW_START;
n_stream->deliver_window = STREAMWINDOW_START;
@@ -1124,6 +1131,22 @@ static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) {
n_stream->next_stream = circ->n_streams;
circ->n_streams = n_stream;
+ if(circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED) {
+ n_stream->address = tor_strdup("(rendezvous)");
+ strcpy(n_stream->rend_query, "yes"); /* XXX kludge */
+ if(connection_exit_set_rendezvous_addr_port(n_stream) < 0) {
+ log_fn(LOG_WARN,"Didn't find rendezvous service (port %d)",n_stream->port);
+ connection_mark_for_close(n_stream,0 /* XXX */);
+ return 0;
+ }
+ n_stream->state = EXIT_CONN_STATE_CONNECTING;
+ n_stream->cpath_layer = circ->cpath->prev; /* link it */
+ connection_exit_connect(n_stream);
+ return 0;
+ }
+ n_stream->address = tor_strdup(cell->payload + RELAY_HEADER_SIZE);
+ n_stream->state = EXIT_CONN_STATE_RESOLVING;
+
/* send it off to the gethostbyname farm */
switch(dns_resolve(n_stream)) {
case 1: /* resolve worked */
@@ -1145,7 +1168,8 @@ static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) {
void connection_exit_connect(connection_t *conn) {
unsigned char connected_payload[4];
- if(router_compare_to_my_exit_policy(conn) == ADDR_POLICY_REJECTED) {
+ if (!*conn->rend_query &&
+ router_compare_to_my_exit_policy(conn) == ADDR_POLICY_REJECTED) {
log_fn(LOG_INFO,"%s:%d failed exit policy. Closing.", conn->address, conn->port);
connection_mark_for_close(conn, END_STREAM_REASON_EXITPOLICY);
return;
@@ -1176,9 +1200,29 @@ void connection_exit_connect(connection_t *conn) {
connection_watch_events(conn, POLLIN);
/* also, deliver a 'connected' cell back through the circuit. */
- *(uint32_t*)connected_payload = htonl(conn->addr);
- connection_edge_send_command(conn, circuit_get_by_conn(conn), RELAY_COMMAND_CONNECTED,
- connected_payload, 4, NULL);
+ if(*conn->rend_query) { /* rendezvous stream */
+ /* don't send an address back! */
+ connection_edge_send_command(conn, circuit_get_by_conn(conn), RELAY_COMMAND_CONNECTED,
+ NULL, 0, conn->cpath_layer);
+ } else { /* normal stream */
+ *(uint32_t*)connected_payload = htonl(conn->addr);
+ connection_edge_send_command(conn, circuit_get_by_conn(conn), RELAY_COMMAND_CONNECTED,
+ connected_payload, 4, conn->cpath_layer);
+ }
+}
+
+/* This is a beginning rendezvous stream. Look up conn->port,
+ * and assign the actual conn->addr and conn->port. Return -1
+ * if failure, or 0 for success.
+ */
+static int
+connection_exit_set_rendezvous_addr_port(connection_t *conn) {
+
+ /* XXX fill me in */
+
+ conn->addr = 0x7F000001u; /* 127.0.0.1, host order */
+
+ return 0;
}
int connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit)
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 86f9b34faf..ec50465791 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -148,7 +148,7 @@ rend_client_rendcirc_is_open(circuit_t *circ)
connection_ap_attach_pending();
}
-/* Called when we recieve a RENDEZVOUS_ESTABLISHED cell; changes the state of
+/* Called when we receive a RENDEZVOUS_ESTABLISHED cell; changes the state of
* the circuit to C_REND_READY.
*/
int
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index d0bc78d9d6..fd8fb8357b 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -4,7 +4,7 @@
#include "or.h"
-/* Free the storage held by held by 'desc'.
+/* Free the storage held by 'desc'.
*/
void rend_service_descriptor_free(rend_service_descriptor_t *desc)
{
@@ -20,8 +20,8 @@ void rend_service_descriptor_free(rend_service_descriptor_t *desc)
tor_free(desc);
}
-/* Encode a service descriptor for 'desc', and sign it with 'key'. Stores
- * the descriptor in *str_out, and sets *len_out to its length.
+/* Encode a service descriptor for 'desc', and sign it with 'key'. Store
+ * the descriptor in *str_out, and set *len_out to its length.
*/
int
rend_encode_service_descriptor(rend_service_descriptor_t *desc,
@@ -146,7 +146,7 @@ int rend_get_service_id(crypto_pk_env_t *pk, char *out)
typedef struct rend_cache_entry_t {
int len; /* Length of desc */
char *desc; /* Service descriptor */
- rend_service_descriptor_t *parsed; /* Parsed vvalue of 'desc' */
+ rend_service_descriptor_t *parsed; /* Parsed value of 'desc' */
} rend_cache_entry_t;
static strmap_t *rend_cache = NULL;