aboutsummaryrefslogtreecommitdiff
path: root/src/or/connection_edge.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/connection_edge.c')
-rw-r--r--src/or/connection_edge.c75
1 files changed, 54 insertions, 21 deletions
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 88ce66999..7e9ea109c 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -251,7 +251,7 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection
*(int*)conn->stream_id);
return 0;
}
- if(cell->length-RELAY_HEADER_SIZE >= 5 &&
+ if(cell->length-RELAY_HEADER_SIZE >= 5 &&
*(cell->payload+RELAY_HEADER_SIZE) == END_STREAM_REASON_EXITPOLICY) {
/* No need to close the connection. We'll hold it open while
* we try a new exit node.
@@ -260,9 +260,16 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection
addr = ntohl(*(uint32_t*)(cell->payload+RELAY_HEADER_SIZE+1));
client_dns_set_entry(conn->socks_request->address, addr);
conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
- if(connection_ap_handshake_attach_circuit(conn) < 0)
- circuit_launch_new(); /* Build another circuit to handle this stream */
- return 0;
+ switch(connection_ap_handshake_attach_circuit(conn)) {
+ case -1: /* it will never work */
+ break; /* conn will get closed below */
+ case 0: /* no useful circuits available */
+ if(!circuit_get_newest(conn, 0)) /* is one already on the way? */
+ circuit_launch_new();
+ return 0;
+ case 1: /* it succeeded, great */
+ return 0;
+ }
}
log_fn(LOG_INFO,"end cell (%s) for stream %d. Removing stream.",
connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, cell->length),
@@ -494,19 +501,29 @@ repeat_connection_edge_package_raw_inbuf:
void connection_ap_attach_pending(void)
{
connection_t **carray;
+ connection_t *conn;
int n, i;
get_connection_array(&carray, &n);
for (i = 0; i < n; ++i) {
- if (carray[i]->type != CONN_TYPE_AP ||
- carray[i]->type != AP_CONN_STATE_CIRCUIT_WAIT)
+ conn = carray[i];
+ if (conn->type != CONN_TYPE_AP ||
+ conn->type != AP_CONN_STATE_CIRCUIT_WAIT)
continue;
- if (connection_ap_handshake_attach_circuit(carray[i])<0) {
- if(!circuit_get_newest(carray[i], 0)) {
- /* if there are no acceptable clean or not-very-dirty circs on the way */
- circuit_launch_new();
- }
+ switch(connection_ap_handshake_attach_circuit(conn)) {
+ case -1: /* it will never work */
+ conn->marked_for_close = 1;
+ conn->has_sent_end = 1;
+ break;
+ case 0: /* we need to build another circuit */
+ if(!circuit_get_newest(conn, 0)) {
+ /* if there are no acceptable clean or not-very-dirty circs on the way */
+ circuit_launch_new();
+ }
+ break;
+ case 1: /* it succeeded, great */
+ break;
}
}
}
@@ -563,18 +580,28 @@ static int connection_ap_handshake_process_socks(connection_t *conn) {
} /* else socks handshake is done, continue processing */
conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
- if(connection_ap_handshake_attach_circuit(conn) < 0)
- circuit_launch_new(); /* Build another circuit to handle this stream */
+ switch(connection_ap_handshake_attach_circuit(conn)) {
+ case -1: /* it will never work */
+ return -1;
+ case 0: /* no useful circuits available */
+ if(!circuit_get_newest(conn, 0)) /* is one already on the way? */
+ circuit_launch_new();
+ break;
+ case 1: /* it succeeded, great */
+ break;
+ }
return 0;
}
-/* Try to find a live circuit. If we don't find one, tell 'conn' to
- * stop reading and return 0. Otherwise, associate the CONN_TYPE_AP
- * connection 'conn' with a safe live circuit, start sending a
- * BEGIN cell down the circuit, and return 1.
+/* Try to find a safe live circuit for CONN_TYPE_AP connection conn. If
+ * we don't find one: if conn cannot be handled by any known nodes,
+ * warn and return -1; else tell conn to stop reading and return 0.
+ * Otherwise, associate conn with a safe live circuit, start
+ * sending a BEGIN cell down the circuit, and return 1.
*/
static int connection_ap_handshake_attach_circuit(connection_t *conn) {
circuit_t *circ;
+ uint32_t addr;
assert(conn);
assert(conn->type == CONN_TYPE_AP);
@@ -586,8 +613,14 @@ static int connection_ap_handshake_attach_circuit(connection_t *conn) {
if(!circ) {
log_fn(LOG_INFO,"No safe circuit ready for edge connection; delaying.");
+ addr = client_dns_lookup_entry(conn->socks_request->address);
+ if(router_exit_policy_all_routers_reject(addr, conn->socks_request->port)) {
+ log_fn(LOG_WARN,"No node exists that will handle exit to %s:%d. Rejecting.",
+ conn->socks_request->address, conn->socks_request->port);
+ return -1;
+ }
connection_stop_reading(conn); /* don't read until the connected cell arrives */
- return -1;
+ return 0;
}
connection_start_reading(conn);
@@ -607,7 +640,7 @@ static int connection_ap_handshake_attach_circuit(connection_t *conn) {
connection_ap_handshake_send_begin(conn, circ);
- return 0;
+ return 1;
}
/* deliver the destaddr:destport in a relay cell */
@@ -748,7 +781,7 @@ 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_exit_policy(conn) < 0) {
+ if(router_compare_to_my_exit_policy(conn) < 0) {
log_fn(LOG_INFO,"%s:%d failed exit policy. Closing.", conn->address, conn->port);
connection_edge_end(conn, END_STREAM_REASON_EXITPOLICY, NULL);
return;
@@ -793,7 +826,7 @@ int connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit)
assert(conn->socks_request);
addr = client_dns_lookup_entry(conn->socks_request->address);
- return router_supports_exit_address(addr, conn->port, exit);
+ return router_supports_exit_address(addr, conn->socks_request->port, exit);
}
/* ***** Client DNS code ***** */