diff options
Diffstat (limited to 'src/or/connection_edge.c')
-rw-r--r-- | src/or/connection_edge.c | 75 |
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 ***** */ |