diff options
author | Roger Dingledine <arma@torproject.org> | 2003-05-02 21:29:25 +0000 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2003-05-02 21:29:25 +0000 |
commit | 96759a609e65edf0ba48471242a94b63023fba3c (patch) | |
tree | dd8c0837888ccd5cd28ae009b1d1427a70f596db /src/or | |
parent | bb75b142187798b3599b76d53e1faf581676d30a (diff) | |
download | tor-96759a609e65edf0ba48471242a94b63023fba3c.tar.gz tor-96759a609e65edf0ba48471242a94b63023fba3c.zip |
streams are now 8 bytes, and are recognized by intermediate hops
the OP only crypts the appropriate number of times depending on which
layer (hop on the path) it's for/from.
svn:r262
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/circuit.c | 154 | ||||
-rw-r--r-- | src/or/command.c | 4 | ||||
-rw-r--r-- | src/or/connection.c | 8 | ||||
-rw-r--r-- | src/or/connection_ap.c | 23 | ||||
-rw-r--r-- | src/or/connection_edge.c | 35 | ||||
-rw-r--r-- | src/or/connection_exit.c | 10 | ||||
-rw-r--r-- | src/or/onion.c | 5 | ||||
-rw-r--r-- | src/or/or.h | 38 |
8 files changed, 168 insertions, 109 deletions
diff --git a/src/or/circuit.c b/src/or/circuit.c index e2d1c0d248..81b117dc90 100644 --- a/src/or/circuit.c +++ b/src/or/circuit.c @@ -281,7 +281,8 @@ circuit_t *circuit_get_newest_ap(void) { return bestcirc; } -int circuit_deliver_relay_cell_from_edge(cell_t *cell, circuit_t *circ, char edge_type) { +int circuit_deliver_relay_cell_from_edge(cell_t *cell, circuit_t *circ, + char edge_type, crypt_path_t *layer_hint) { int cell_direction; static int numsent_ap=0, numsent_exit=0; @@ -293,7 +294,7 @@ int circuit_deliver_relay_cell_from_edge(cell_t *cell, circuit_t *circ, char edg log(LOG_DEBUG,"circuit_deliver_relay_cell_from_edge(): now sent %d relay cells from ap", numsent_ap); if(circ->p_receive_circwindow <= 0) { log(LOG_DEBUG,"circuit_deliver_relay_cell_from_edge(): pwindow 0, queueing for later."); - circ->relay_queue = relay_queue_add(circ->relay_queue, cell); + circ->relay_queue = relay_queue_add(circ->relay_queue, cell, layer_hint); return 0; } circ->p_receive_circwindow--; @@ -304,13 +305,13 @@ int circuit_deliver_relay_cell_from_edge(cell_t *cell, circuit_t *circ, char edg log(LOG_DEBUG,"circuit_deliver_relay_cell_from_edge(): now sent %d relay cells from exit", numsent_exit); if(circ->n_receive_circwindow <= 0) { log(LOG_DEBUG,"circuit_deliver_relay_cell_from_edge(): nwindow 0, queueing for later."); - circ->relay_queue = relay_queue_add(circ->relay_queue, cell); + circ->relay_queue = relay_queue_add(circ->relay_queue, cell, layer_hint); return 0; } circ->n_receive_circwindow--; } - if(circuit_deliver_relay_cell(cell, circ, cell_direction) < 0) { + if(circuit_deliver_relay_cell(cell, circ, cell_direction, layer_hint) < 0) { return -1; } @@ -318,113 +319,168 @@ int circuit_deliver_relay_cell_from_edge(cell_t *cell, circuit_t *circ, char edg return 0; } -int circuit_deliver_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction) { - connection_t *conn; +int circuit_deliver_relay_cell(cell_t *cell, circuit_t *circ, + int cell_direction, crypt_path_t *layer_hint) { + connection_t *conn=NULL; + char recognized=0; + char buf[256]; assert(cell && circ); assert(cell_direction == CELL_DIRECTION_OUT || cell_direction == CELL_DIRECTION_IN); - if(cell_direction == CELL_DIRECTION_OUT) - conn = circ->n_conn; - else - conn = circ->p_conn; - /* first crypt cell->length */ - if(circuit_crypt(circ, &(cell->length), 1, cell_direction) < 0) { - log(LOG_DEBUG,"circuit_deliver_relay_cell(): length crypt failed. Dropping connection."); - return -1; - } + buf[0] = cell->length; + memcpy(buf+1, cell->payload, CELL_PAYLOAD_SIZE); - /* then crypt the payload */ - if(circuit_crypt(circ, (char *)&(cell->payload), CELL_PAYLOAD_SIZE, cell_direction) < 0) { - log(LOG_DEBUG,"circuit_deliver_relay_cell(): payload crypt failed. Dropping connection."); + log(LOG_DEBUG,"circuit_deliver_relay_cell(): streamid %d before crypt.", *(int*)(cell->payload+1)); + + if(relay_crypt(circ, buf, 1+CELL_PAYLOAD_SIZE, cell_direction, layer_hint, &recognized, &conn) < 0) { + log(LOG_DEBUG,"circuit_deliver_relay_cell(): relay crypt failed. Dropping connection."); return -1; } - if(cell_direction == CELL_DIRECTION_OUT && (!conn || conn->type == CONN_TYPE_EXIT)) { - log(LOG_DEBUG,"circuit_deliver_relay_cell(): Sending to exit."); - return connection_edge_process_relay_cell(cell, circ, EDGE_EXIT); + cell->length = buf[0]; + memcpy(cell->payload, buf+1, CELL_PAYLOAD_SIZE); + + if(recognized) { + if(cell_direction == CELL_DIRECTION_OUT) { + log(LOG_DEBUG,"circuit_deliver_relay_cell(): Sending to exit."); + return connection_edge_process_relay_cell(cell, circ, conn, EDGE_EXIT); + } + if(cell_direction == CELL_DIRECTION_IN) { + log(LOG_DEBUG,"circuit_deliver_relay_cell(): Sending to AP."); + return connection_edge_process_relay_cell(cell, circ, conn, EDGE_AP); + } } - if(cell_direction == CELL_DIRECTION_IN && (!conn || conn->type == CONN_TYPE_AP)) { - log(LOG_DEBUG,"circuit_deliver_relay_cell(): Sending to AP."); - return connection_edge_process_relay_cell(cell, circ, EDGE_AP); + + /* not recognized. pass it on. */ + if(cell_direction == CELL_DIRECTION_OUT) + conn = circ->n_conn; + else + conn = circ->p_conn; + + if(!conn || !connection_speaks_cells(conn)) { + log(LOG_INFO,"circuit_deliver_relay_cell(): Didn't recognize cell (%d), but circ stops here! Dropping.", *(int *)(cell->payload+1)); + return 0; } - /* else send it as a cell */ - assert(conn); - //log(LOG_DEBUG,"circuit_deliver_relay_cell(): Sending to connection."); + return connection_write_cell_to_buf(cell, conn); } -int circuit_crypt(circuit_t *circ, char *in, int inlen, char cell_direction) { - char *out; +int relay_crypt(circuit_t *circ, char *in, int inlen, char cell_direction, + crypt_path_t *layer_hint, char *recognized, connection_t **conn) { crypt_path_t *thishop; + char out[256]; - assert(circ && in); + assert(circ && in && recognized && conn); - out = (char *)malloc(inlen); - if(!out) - return -1; + assert(inlen < 256); if(cell_direction == CELL_DIRECTION_IN) { if(circ->cpath) { /* we're at the beginning of the circuit. We'll want to do layered crypts. */ thishop = circ->cpath; - /* Remember: cpath is in forward order, that is, first hop first. */ - do { + do { /* Remember: cpath is in forward order, that is, first hop first. */ assert(thishop); + /* decrypt */ if(crypto_cipher_decrypt(thishop->b_crypto, in, inlen, out)) { log(LOG_ERR,"Error performing decryption:%s",crypto_perror()); - free(out); return -1; } - - /* copy ciphertext back to buf */ memcpy(in,out,inlen); + + if( (*recognized = relay_check_recognized(circ, cell_direction, in+2, conn))) + return 0; + thishop = thishop->next; } while(thishop != circ->cpath); + log(LOG_INFO,"relay_crypt(): in-cell at OP not recognized. Killing circuit."); + return -1; } else { /* we're in the middle. Just one crypt. */ - if(crypto_cipher_encrypt(circ->p_crypto,in, inlen, out)) { + + if(crypto_cipher_encrypt(circ->p_crypto, in, inlen, out)) { log(LOG_ERR,"circuit_encrypt(): Encryption failed for ACI : %u (%s).", circ->p_aci, crypto_perror()); - free(out); return -1; } memcpy(in,out,inlen); + + /* don't check for recognized. only the OP can recognize a stream on the way back. */ + } } else if(cell_direction == CELL_DIRECTION_OUT) { if(circ->cpath) { /* we're at the beginning of the circuit. We'll want to do layered crypts. */ - thishop = circ->cpath->prev; + + thishop = layer_hint; /* we already know which layer, from when we package_raw_inbuf'ed */ /* moving from last to first hop */ do { assert(thishop); + /* encrypt */ - if(crypto_cipher_encrypt(thishop->f_crypto, in, inlen, (unsigned char *)out)) { + if(crypto_cipher_encrypt(thishop->f_crypto, in, inlen, out)) { log(LOG_ERR,"Error performing encryption:%s",crypto_perror()); - free(out); return -1; } - - /* copy ciphertext back to buf */ memcpy(in,out,inlen); + thishop = thishop->prev; } while(thishop != circ->cpath->prev); } else { /* we're in the middle. Just one crypt. */ + if(crypto_cipher_decrypt(circ->n_crypto,in, inlen, out)) { log(LOG_ERR,"circuit_crypt(): Decryption failed for ACI : %u (%s).", circ->n_aci, crypto_perror()); - free(out); return -1; } memcpy(in,out,inlen); + + if( (*recognized = relay_check_recognized(circ, cell_direction, in+2, conn))) + return 0; + } } else { log(LOG_ERR,"circuit_crypt(): unknown cell direction %d.", cell_direction); assert(0); } - free(out); return 0; } +int relay_check_recognized(circuit_t *circ, int cell_direction, char *stream, connection_t **conn) { +/* FIXME can optimize by passing thishop in */ + connection_t *tmpconn; + + log(LOG_DEBUG,"relay_check_recognized(): entering"); + if(!memcmp(stream,ZERO_STREAM,STREAM_ID_SIZE)) + return 1; /* the zero stream is always recognized */ + + if(cell_direction == CELL_DIRECTION_OUT) + tmpconn = circ->n_conn; + else + tmpconn = circ->p_conn; + + log(LOG_DEBUG,"relay_check_recognized(): not the zero stream."); + if(!tmpconn) + return 0; /* no conns? don't recognize it */ + + while(tmpconn && tmpconn->type == CONN_TYPE_OR) { + log(LOG_DEBUG,"relay_check_recognized(): skipping over an OR conn"); + tmpconn = tmpconn->next_stream; + } + + for( ; tmpconn; tmpconn=tmpconn->next_stream) { + if(!memcmp(stream,tmpconn->stream_id, STREAM_ID_SIZE)) { + log(LOG_DEBUG,"relay_check_recognized(): recognized stream %d.", *(int*)stream); + *conn = tmpconn; + return 1; + } + log(LOG_DEBUG,"relay_check_recognized(): considered stream %d, not it.",*(int*)tmpconn->stream_id); + } + + log(LOG_DEBUG,"relay_check_recognized(): Didn't recognize. Giving up."); + return 0; + +} + void circuit_resume_edge_reading(circuit_t *circ, int edge_type) { connection_t *conn; struct relay_queue_t *tmpd; @@ -438,7 +494,7 @@ void circuit_resume_edge_reading(circuit_t *circ, int edge_type) { circ->n_receive_circwindow--; assert(circ->n_receive_circwindow >= 0); - if(circuit_deliver_relay_cell(circ->relay_queue->cell, circ, CELL_DIRECTION_IN) < 0) { + if(circuit_deliver_relay_cell(circ->relay_queue->cell, circ, CELL_DIRECTION_IN, circ->relay_queue->layer_hint) < 0) { circuit_close(circ); return; } @@ -446,7 +502,7 @@ void circuit_resume_edge_reading(circuit_t *circ, int edge_type) { circ->p_receive_circwindow--; assert(circ->p_receive_circwindow >= 0); - if(circuit_deliver_relay_cell(circ->relay_queue->cell, circ, CELL_DIRECTION_OUT) < 0) { + if(circuit_deliver_relay_cell(circ->relay_queue->cell, circ, CELL_DIRECTION_OUT, circ->relay_queue->layer_hint) < 0) { circuit_close(circ); return; } diff --git a/src/or/command.c b/src/or/command.c index 503b95fe94..d589e71b1b 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -241,14 +241,14 @@ void command_process_relay_cell(cell_t *cell, connection_t *conn) { if(cell->aci == circ->p_aci) { /* it's an outgoing cell */ cell->aci = circ->n_aci; /* switch it */ - if(circuit_deliver_relay_cell(cell, circ, CELL_DIRECTION_OUT) < 0) { + if(circuit_deliver_relay_cell(cell, circ, CELL_DIRECTION_OUT, conn->cpath_layer) < 0) { log(LOG_INFO,"command_process_relay_cell(): circuit_deliver_relay_cell (forward) failed. Closing."); circuit_close(circ); return; } } else { /* it's an ingoing cell */ cell->aci = circ->p_aci; /* switch it */ - if(circuit_deliver_relay_cell(cell, circ, CELL_DIRECTION_IN) < 0) { + if(circuit_deliver_relay_cell(cell, circ, CELL_DIRECTION_IN, NULL) < 0) { log(LOG_DEBUG,"command_process_relay_cell(): circuit_deliver_relay_cell (backward) failed. Closing."); circuit_close(circ); return; diff --git a/src/or/connection.c b/src/or/connection.c index f7c2ebc0f0..5b29d2120f 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -706,7 +706,7 @@ repeat_connection_package_raw_inbuf: if(conn->type == CONN_TYPE_EXIT) { cell.aci = circ->p_aci; - if(circuit_deliver_relay_cell_from_edge(&cell, circ, EDGE_EXIT) < 0) { + if(circuit_deliver_relay_cell_from_edge(&cell, circ, EDGE_EXIT, NULL) < 0) { log(LOG_DEBUG,"connection_package_raw_inbuf(): circuit_deliver_relay_cell_from_edge (backward) failed. Closing."); circuit_close(circ); return 0; @@ -721,7 +721,7 @@ repeat_connection_package_raw_inbuf: } else { /* send it forward. we're an AP */ assert(conn->type == CONN_TYPE_AP); cell.aci = circ->n_aci; - if(circuit_deliver_relay_cell_from_edge(&cell, circ, EDGE_AP) < 0) { + if(circuit_deliver_relay_cell_from_edge(&cell, circ, EDGE_AP, conn->cpath_layer) < 0) { log(LOG_DEBUG,"connection_package_raw_inbuf(): circuit_deliver_relay_cell_from_edge (forward) failed. Closing."); circuit_close(circ); return 0; @@ -763,7 +763,7 @@ int connection_consider_sending_sendme(connection_t *conn, int edge_type) { log(LOG_DEBUG,"connection_consider_sending_sendme(): Outbuf %d, Queueing stream sendme back.", conn->outbuf_flushlen); conn->p_receive_streamwindow += STREAMWINDOW_INCREMENT; cell.aci = circ->p_aci; - if(circuit_deliver_relay_cell_from_edge(&cell, circ, edge_type) < 0) { + if(circuit_deliver_relay_cell_from_edge(&cell, circ, edge_type, NULL) < 0) { log(LOG_DEBUG,"connection_consider_sending_sendme(): circuit_deliver_relay_cell_from_edge (backward) failed. Closing."); circuit_close(circ); return 0; @@ -775,7 +775,7 @@ int connection_consider_sending_sendme(connection_t *conn, int edge_type) { log(LOG_DEBUG,"connection_consider_sending_sendme(): Outbuf %d, Queueing stream sendme forward.", conn->outbuf_flushlen); conn->n_receive_streamwindow += STREAMWINDOW_INCREMENT; cell.aci = circ->n_aci; - if(circuit_deliver_relay_cell_from_edge(&cell, circ, edge_type) < 0) { + if(circuit_deliver_relay_cell_from_edge(&cell, circ, edge_type, conn->cpath_layer) < 0) { log(LOG_DEBUG,"connection_consider_sending_sendme(): circuit_deliver_relay_cell_from_edge (forward) failed. Closing."); circuit_close(circ); return 0; diff --git a/src/or/connection_ap.c b/src/or/connection_ap.c index ec8c05f0a0..4cb97affe3 100644 --- a/src/or/connection_ap.c +++ b/src/or/connection_ap.c @@ -108,6 +108,10 @@ int ap_handshake_process_socks(connection_t *conn) { conn->next_stream = circ->p_conn; circ->p_conn = conn; + assert(circ->cpath && circ->cpath->prev); + assert(circ->cpath->prev->state == CPATH_STATE_OPEN); + conn->cpath_layer = circ->cpath->prev; + if(ap_handshake_send_begin(conn, circ) < 0) { circuit_close(circ); return -1; @@ -118,23 +122,24 @@ int ap_handshake_process_socks(connection_t *conn) { int ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ) { cell_t cell; - uint16_t stream_id; memset(&cell, 0, sizeof(cell_t)); /* deliver the dest_addr in a relay cell */ cell.command = CELL_RELAY; cell.aci = circ->n_aci; SET_CELL_RELAY_COMMAND(cell, RELAY_COMMAND_BEGIN); - if (CRYPTO_PSEUDO_RAND_INT(stream_id)) + if(crypto_pseudo_rand(STREAM_ID_SIZE, ap_conn->stream_id) < 0) return -1; - SET_CELL_STREAM_ID(cell, stream_id); /* FIXME check for collisions */ - ap_conn->stream_id = stream_id; - - snprintf(cell.payload+4, CELL_PAYLOAD_SIZE-4, "%s:%d", ap_conn->dest_addr, ap_conn->dest_port); - cell.length = strlen(cell.payload+RELAY_HEADER_SIZE)+1+RELAY_HEADER_SIZE; - log(LOG_DEBUG,"ap_handshake_send_begin(): Sending relay cell to begin stream %d.", ap_conn->stream_id); - if(circuit_deliver_relay_cell_from_edge(&cell, circ, EDGE_AP) < 0) { + SET_CELL_STREAM_ID(cell, ZERO_STREAM); + + memcpy(cell.payload+RELAY_HEADER_SIZE, ap_conn->stream_id, STREAM_ID_SIZE); + cell.length = + snprintf(cell.payload+RELAY_HEADER_SIZE+STREAM_ID_SIZE, CELL_PAYLOAD_SIZE-RELAY_HEADER_SIZE-STREAM_ID_SIZE, + "%s:%d", ap_conn->dest_addr, ap_conn->dest_port) + + 1 + STREAM_ID_SIZE + RELAY_HEADER_SIZE; + log(LOG_DEBUG,"ap_handshake_send_begin(): Sending relay cell (id %d) to begin stream %d.", *(int *)(cell.payload+1),*(int *)ap_conn->stream_id); + if(circuit_deliver_relay_cell_from_edge(&cell, circ, EDGE_AP, ap_conn->cpath_layer) < 0) { log(LOG_DEBUG,"ap_handshake_send_begin(): failed to deliver begin cell. Closing."); return -1; } diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index b5a342a53d..1f00391370 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -31,7 +31,7 @@ int connection_edge_process_inbuf(connection_t *conn) { SET_CELL_STREAM_ID(cell, conn->stream_id); cell.aci = circ->n_aci; - if (circuit_deliver_relay_cell_from_edge(&cell, circ, conn->type) < 0) { + if (circuit_deliver_relay_cell_from_edge(&cell, circ, conn->type, conn->cpath_layer) < 0) { log(LOG_DEBUG,"connection_edge_process_inbuf: circuit_deliver_relay_cell_from_edge failed. Closing"); circuit_close(circ); } @@ -82,18 +82,16 @@ int connection_edge_send_command(connection_t *conn, circuit_t *circ, int relay_ cell.length = RELAY_HEADER_SIZE; log(LOG_INFO,"connection_edge_send_command(): delivering %d cell %s.", relay_command, conn->type == CONN_TYPE_AP ? "forward" : "backward"); - if(circuit_deliver_relay_cell_from_edge(&cell, circ, conn->type) < 0) { - log(LOG_DEBUG,"connection_edge_send_command(): circuit_deliver_relay_cell failed. Closing."); + if(circuit_deliver_relay_cell_from_edge(&cell, circ, conn->type, conn->cpath_layer) < 0) { + log(LOG_DEBUG,"connection_edge_send_command(): circuit_deliver_relay_cell_from_edge failed. Closing."); circuit_close(circ); return 0; } return 0; } -int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, int edge_type) { - connection_t *conn; +int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection_t *conn, int edge_type) { int relay_command; - int stream_id; static int num_seen=0; /* an incoming relay cell has arrived */ @@ -101,23 +99,14 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, int edge_t assert(cell && circ); relay_command = CELL_RELAY_COMMAND(*cell); - stream_id = CELL_STREAM_ID(*cell); - log(LOG_DEBUG,"connection_edge_process_relay_cell(): command %d stream %d", relay_command, stream_id); +// log(LOG_DEBUG,"connection_edge_process_relay_cell(): command %d stream %d", relay_command, stream_id); num_seen++; log(LOG_DEBUG,"connection_edge_process_relay_cell(): Now seen %d relay cells here.", num_seen); circuit_consider_sending_sendme(circ, edge_type); - if(edge_type == EDGE_AP) - conn = circ->p_conn; - else - conn = circ->n_conn; - - for( ; conn && conn->stream_id != stream_id; conn = conn->next_stream) ; - - /* now conn is either NULL, in which case we don't recognize the stream_id, or - * it is set, in which case cell is talking about this conn. - */ + /* either conn is NULL, in which case we've got a control cell, or else + * conn points to the recognized stream. */ if(conn && conn->state != AP_CONN_STATE_OPEN && conn->state != EXIT_CONN_STATE_OPEN) { if(conn->type == CONN_TYPE_EXIT && relay_command == RELAY_COMMAND_END) { @@ -143,7 +132,7 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, int edge_t } case RELAY_COMMAND_DATA: if(!conn) { - log(LOG_DEBUG,"connection_edge_process_relay_cell(): relay cell dropped, unknown stream %d.",stream_id); + log(LOG_DEBUG,"connection_edge_process_relay_cell(): relay cell dropped, unknown stream %d.",*(int*)conn->stream_id); return 0; } if((edge_type == EDGE_AP && --conn->n_receive_streamwindow < 0) || @@ -172,10 +161,10 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, int edge_t return 0; case RELAY_COMMAND_END: if(!conn) { - log(LOG_DEBUG,"connection_edge_process_relay_cell(): end cell dropped, unknown stream %d.",stream_id); + log(LOG_DEBUG,"connection_edge_process_relay_cell(): end cell dropped, unknown stream %d.",*(int*)conn->stream_id); return 0; } - log(LOG_DEBUG,"connection_edge_process_relay_cell(): end cell for stream %d. Removing stream.",stream_id); + log(LOG_DEBUG,"connection_edge_process_relay_cell(): end cell for stream %d. Removing stream.",*(int*)conn->stream_id); /* go through and identify who points to conn. remove conn from the list. */ #if 0 @@ -199,7 +188,7 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, int edge_t return 0; } if(!conn) { - log(LOG_DEBUG,"connection_edge_process_relay_cell(): connected cell dropped, unknown stream %d.",stream_id); + log(LOG_DEBUG,"connection_edge_process_relay_cell(): connected cell dropped, unknown stream %d.",*(int*)conn->stream_id); break; } log(LOG_DEBUG,"connection_edge_process_relay_cell(): Connected! Notifying application."); @@ -209,7 +198,7 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, int edge_t break; case RELAY_COMMAND_SENDME: if(!conn) { - log(LOG_DEBUG,"connection_edge_process_relay_cell(): sendme cell dropped, unknown stream %d.",stream_id); + log(LOG_DEBUG,"connection_edge_process_relay_cell(): sendme cell dropped, unknown stream %d.",*(int*)conn->stream_id); return 0; } if(edge_type == EDGE_AP) diff --git a/src/or/connection_exit.c b/src/or/connection_exit.c index f63bf634ff..0720598f82 100644 --- a/src/or/connection_exit.c +++ b/src/or/connection_exit.c @@ -8,11 +8,11 @@ int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) { connection_t *n_conn; char *colon; - if(!memchr(cell->payload + RELAY_HEADER_SIZE,0,cell->length - RELAY_HEADER_SIZE)) { + if(!memchr(cell->payload+RELAY_HEADER_SIZE+STREAM_ID_SIZE,0,cell->length-RELAY_HEADER_SIZE-STREAM_ID_SIZE)) { log(LOG_WARNING,"connection_exit_begin_conn(): relay begin cell has no \\0. Dropping."); return 0; } - colon = strchr(cell->payload + RELAY_HEADER_SIZE, ':'); + colon = strchr(cell->payload+RELAY_HEADER_SIZE+STREAM_ID_SIZE, ':'); if(!colon) { log(LOG_WARNING,"connection_exit_begin_conn(): relay begin cell has no colon. Dropping."); return 0; @@ -31,10 +31,8 @@ int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) { return 0; } -// cell->payload[0] = 0; - n_conn->stream_id = CELL_STREAM_ID(*cell); - - n_conn->address = strdup(cell->payload + RELAY_HEADER_SIZE); + memcpy(n_conn->stream_id, cell->payload + RELAY_HEADER_SIZE, STREAM_ID_SIZE); + n_conn->address = strdup(cell->payload + RELAY_HEADER_SIZE + STREAM_ID_SIZE); n_conn->port = atoi(colon+1); n_conn->state = EXIT_CONN_STATE_RESOLVING; n_conn->receiver_bucket = -1; /* edge connections don't do receiver buckets */ diff --git a/src/or/onion.c b/src/or/onion.c index fc50279c7a..87c42ee2fc 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -141,13 +141,14 @@ void onion_pending_remove(circuit_t *circ) { } -struct relay_queue_t *relay_queue_add(struct relay_queue_t *list, cell_t *cell) { +struct relay_queue_t *relay_queue_add(struct relay_queue_t *list, cell_t *cell, crypt_path_t *layer_hint) { struct relay_queue_t *tmpd, *newd; newd = malloc(sizeof(struct relay_queue_t)); memset(newd, 0, sizeof(struct relay_queue_t)); newd->cell = malloc(sizeof(cell_t)); memcpy(newd->cell, cell, sizeof(cell_t)); + newd->layer_hint = layer_hint; if(!list) { return newd; @@ -167,7 +168,7 @@ void onion_pending_relay_add(circuit_t *circ, cell_t *cell) { for(tmpo=ol_list; tmpo; tmpo=tmpo->next) { if(tmpo->circ == circ) { - tmpo->relay_cells = relay_queue_add(tmpo->relay_cells, cell); + tmpo->relay_cells = relay_queue_add(tmpo->relay_cells, cell, NULL); return; } } diff --git a/src/or/or.h b/src/or/or.h index 54bfbe2248..3dab7ad9f1 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -128,7 +128,7 @@ #define RELAY_COMMAND_CONNECTED 4 #define RELAY_COMMAND_SENDME 5 -#define RELAY_HEADER_SIZE 4 +#define RELAY_HEADER_SIZE 8 #define RELAY_STATE_RESOLVING @@ -195,15 +195,17 @@ typedef uint16_t aci_t; typedef struct { aci_t aci; /* Anonymous Connection Identifier */ unsigned char command; - unsigned char length; /* of payload if relay cell, else value of sendme */ + unsigned char length; /* of payload if relay cell */ uint32_t seq; /* sequence number */ unsigned char payload[CELL_PAYLOAD_SIZE]; } cell_t; #define CELL_RELAY_COMMAND(c) (*(uint8_t*)((c).payload)) #define SET_CELL_RELAY_COMMAND(c,cmd) (*(uint8_t*)((c).payload) = (cmd)) -#define CELL_STREAM_ID(c) ntohs(*(uint16_t*)((c).payload+2)) -#define SET_CELL_STREAM_ID(c,id) (*(uint16_t*)((c).payload+2) = htons(id)) +#define STREAM_ID_SIZE 7 +#define SET_CELL_STREAM_ID(c,id) memcpy((c).payload+1,(id),STREAM_ID_SIZE) + +#define ZERO_STREAM "\0\0\0\0\0\0\0\0" #define SOCKS4_REQUEST_GRANTED 90 #define SOCKS4_REQUEST_REJECT 91 @@ -265,8 +267,9 @@ struct connection_t { uint16_t port; /* used by exit and ap: */ - uint16_t stream_id; + char stream_id[STREAM_ID_SIZE]; struct connection_t *next_stream; + struct crypt_path_t *cpath_layer; /* a pointer to which node in the circ this conn exits at */ int n_receive_streamwindow; int p_receive_streamwindow; int done_sending; @@ -335,7 +338,7 @@ typedef struct { void *next; } routerinfo_t; -typedef struct { +struct crypt_path_t { char digest2[20]; /* second SHA output for onion_layer_t.keyseed */ char digest3[20]; /* third SHA output for onion_layer_t.keyseed */ @@ -347,13 +350,16 @@ typedef struct { #define CPATH_STATE_CLOSED 0 #define CPATH_STATE_AWAITING_KEY 1 #define CPATH_STATE_OPEN 2 - void *next; - void *prev; /* doubly linked list */ + struct crypt_path_t *next; + struct crypt_path_t *prev; /* doubly linked list */ + +}; -} crypt_path_t; +typedef struct crypt_path_t crypt_path_t; struct relay_queue_t { cell_t *cell; + crypt_path_t *layer_hint; struct relay_queue_t *next; }; @@ -506,9 +512,13 @@ circuit_t *circuit_get_by_conn(connection_t *conn); circuit_t *circuit_get_newest_ap(void); circuit_t *circuit_enumerate_by_naddr_nport(circuit_t *start, uint32_t naddr, uint16_t nport); -int circuit_deliver_relay_cell_from_edge(cell_t *cell, circuit_t *circ, char edge_type); -int circuit_deliver_relay_cell(cell_t *cell, circuit_t *circ, int crypt_type); -int circuit_crypt(circuit_t *circ, char *in, int inlen, char crypt_type); +int circuit_deliver_relay_cell_from_edge(cell_t *cell, circuit_t *circ, + char edge_type, crypt_path_t *layer_hint); +int circuit_deliver_relay_cell(cell_t *cell, circuit_t *circ, + int cell_direction, crypt_path_t *layer_hint); +int relay_crypt(circuit_t *circ, char *in, int inlen, char cell_direction, + crypt_path_t *layer_hint, char *recognized, connection_t **conn); +int relay_check_recognized(circuit_t *circ, int cell_direction, char *stream, connection_t **conn); void circuit_resume_edge_reading(circuit_t *circ, int edge_type); int circuit_consider_stop_edge_reading(circuit_t *circ, int edge_type); @@ -645,7 +655,7 @@ int connection_ap_handle_listener_read(connection_t *conn); int connection_edge_process_inbuf(connection_t *conn); int connection_edge_send_command(connection_t *conn, circuit_t *circ, int relay_command); -int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, int edge_type); +int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection_t *conn, int edge_type); int connection_edge_finished_flushing(connection_t *conn); /********************************* connection_exit.c ***************************/ @@ -753,7 +763,7 @@ int onion_pending_add(circuit_t *circ); int onion_pending_check(void); void onion_pending_process_one(void); void onion_pending_remove(circuit_t *circ); -struct relay_queue_t *relay_queue_add(struct relay_queue_t *list, cell_t *cell); +struct relay_queue_t *relay_queue_add(struct relay_queue_t *list, cell_t *cell, crypt_path_t *layer_hint); void onion_pending_relay_add(circuit_t *circ, cell_t *cell); /* uses a weighted coin with weight cw to choose a route length */ |