diff options
Diffstat (limited to 'src/or/relay.c')
-rw-r--r-- | src/or/relay.c | 62 |
1 files changed, 36 insertions, 26 deletions
diff --git a/src/or/relay.c b/src/or/relay.c index f923ae59a3..8ec5142e7f 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -138,6 +138,8 @@ relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in, * connection_edge. * - Else connection_or_write_cell_to_buf to the conn on the other * side of the circuit. + * + * Return -reason on failure. */ int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction) @@ -145,6 +147,7 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction) connection_t *conn=NULL; crypt_path_t *layer_hint=NULL; char recognized=0; + int reason; tor_assert(cell); tor_assert(circ); @@ -163,20 +166,21 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction) if (cell_direction == CELL_DIRECTION_OUT) { ++stats_n_relay_cells_delivered; debug(LD_OR,"Sending away from origin."); - if (connection_edge_process_relay_cell(cell, circ, conn, NULL) < 0) { + if ((reason=connection_edge_process_relay_cell(cell, circ, conn, NULL)) + < 0) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "connection_edge_process_relay_cell (away from origin) " "failed."); - return -1; + return reason; } } if (cell_direction == CELL_DIRECTION_IN) { ++stats_n_relay_cells_delivered; debug(LD_OR,"Sending to origin."); - if (connection_edge_process_relay_cell(cell, circ, conn, - layer_hint) < 0) { + if ((reason = connection_edge_process_relay_cell(cell, circ, conn, + layer_hint)) < 0) { warn(LD_OR,"connection_edge_process_relay_cell (at origin) failed."); - return -1; + return reason; } } return 0; @@ -197,19 +201,19 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction) tor_assert(circ->rend_splice->purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED); cell->circ_id = circ->rend_splice->p_circ_id; - if (circuit_receive_relay_cell(cell, circ->rend_splice, - CELL_DIRECTION_IN) < 0) { + if ((reason = circuit_receive_relay_cell(cell, circ->rend_splice, + CELL_DIRECTION_IN)) < 0) { warn(LD_REND, "Error relaying cell across rendezvous; closing " "circuits"); /* XXXX Do this here, or just return -1? */ - circuit_mark_for_close(circ); - return -1; + circuit_mark_for_close(circ, -reason); + return reason; } return 0; } log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Didn't recognize cell, but circ stops here! Closing circ."); - return -1; + return -END_CIRC_REASON_TORPROTOCOL; } debug(LD_OR,"Passing on unrecognized cell."); @@ -489,7 +493,7 @@ connection_edge_send_command(connection_t *fromconn, circuit_t *circ, if (circuit_package_relay_cell(&cell, circ, cell_direction, cpath_layer) < 0) { warn(LD_BUG,"circuit_package_relay_cell failed. Closing."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL); return -1; } return 0; @@ -655,7 +659,7 @@ connection_edge_process_end_not_open( warn(LD_PROTOCOL, "Got an end because of %s, but we're not an AP. Closing.", connection_edge_end_reason_str(reason)); - return -1; + return - END_CIRC_REASON_TORPROTOCOL; } info(LD_APP,"Address '%s' refused due to '%s'. Considering retrying.", safe_str(conn->socks_request->address), @@ -848,7 +852,7 @@ connection_edge_process_relay_cell_not_open( * If <b>layer_hint</b> is defined, then we're the origin of the * circuit, and it specifies the hop that packaged <b>cell</b>. * - * Return -1 if you want to warn and tear down the circuit, else 0. + * Return -reason if you want to warn and tear down the circuit, else 0. */ static int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, @@ -858,6 +862,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, static int num_seen=0; relay_header_t rh; unsigned domain = layer_hint?LD_APP:LD_EXIT; + int reason; tor_assert(cell); tor_assert(circ); @@ -869,7 +874,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, if (rh.length > RELAY_PAYLOAD_SIZE) { warn(LD_PROTOCOL, "Relay cell length field too long. Closing circuit."); - return -1; + return - END_CIRC_REASON_TORPROTOCOL; } /* either conn is NULL, in which case we've got a control cell, or else @@ -904,7 +909,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL, conn->cpath_layer); connection_mark_for_close(conn); - return -1; + return -END_CIRC_REASON_TORPROTOCOL; } debug(domain,"circ deliver_window now %d.", layer_hint ? layer_hint->deliver_window : circ->deliver_window); @@ -919,7 +924,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, if (--conn->deliver_window < 0) { /* is it below 0 after decrement? */ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "(relay data) conn deliver_window below 0. Killing."); - return -1; /* somebody's breaking protocol. kill the whole circuit. */ + return -END_CIRC_REASON_TORPROTOCOL; } stats_n_data_bytes_received += rh.length; @@ -974,14 +979,14 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, return 0; } debug(domain,"Got an extended cell! Yay."); - if (circuit_finish_handshake(circ, CELL_CREATED, - cell->payload+RELAY_HEADER_SIZE) < 0) { + if ((reason = circuit_finish_handshake(circ, CELL_CREATED, + cell->payload+RELAY_HEADER_SIZE)) < 0) { warn(domain,"circuit_finish_handshake failed."); - return -1; + return reason; } - if (circuit_send_next_onion_skin(circ)<0) { + if ((reason=circuit_send_next_onion_skin(circ))<0) { info(domain,"circuit_send_next_onion_skin() failed."); - return -1; + return reason; } return 0; case RELAY_COMMAND_TRUNCATE: @@ -990,12 +995,17 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, return 0; } if (circ->n_conn) { - connection_send_destroy(circ->n_circ_id, circ->n_conn); + uint8_t reason = *(uint8_t*)(cell->payload + RELAY_HEADER_SIZE); + connection_or_send_destroy(circ->n_circ_id, circ->n_conn, reason); circuit_set_circid_orconn(circ, 0, NULL, N_CONN_CHANGED); } debug(LD_EXIT, "Processed 'truncate', replying."); - connection_edge_send_command(NULL, circ, RELAY_COMMAND_TRUNCATED, - NULL, 0, NULL); + { + char payload[1]; + payload[0] = (char)END_CIRC_REASON_REQUESTED; + connection_edge_send_command(NULL, circ, RELAY_COMMAND_TRUNCATED, + payload, sizeof(payload), NULL); + } return 0; case RELAY_COMMAND_TRUNCATED: if (!layer_hint) { @@ -1008,7 +1018,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, if (conn) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "'connected' unsupported while open. Closing circ."); - return -1; + return -END_CIRC_REASON_TORPROTOCOL; } info(domain,"'connected' received, no conn attached anymore. Ignoring."); return 0; @@ -1055,7 +1065,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, case RELAY_COMMAND_RESOLVED: if (conn) { warn(domain,"'resolved' unsupported while open. Closing circ."); - return -1; + return -END_CIRC_REASON_TORPROTOCOL; } info(domain,"'resolved' received, no conn attached anymore. Ignoring."); return 0; |