mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-20 10:12:15 +01:00
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
This commit is contained in:
parent
bb75b14218
commit
96759a609e
152
src/or/circuit.c
152
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);
|
||||
|
||||
buf[0] = cell->length;
|
||||
memcpy(buf+1, cell->payload, CELL_PAYLOAD_SIZE);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* not recognized. pass it on. */
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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.");
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
/* 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)) {
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
SET_CELL_STREAM_ID(cell, ZERO_STREAM);
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
38
src/or/or.h
38
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user