diff options
author | Roger Dingledine <arma@torproject.org> | 2003-12-19 05:09:51 +0000 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2003-12-19 05:09:51 +0000 |
commit | 45a66c69553b7185a68e516426a99f333f7fe9f6 (patch) | |
tree | f5d1a14336bc264a30ba770662f8e3933b7c735a | |
parent | eb730c41c8a799bc61dfd7d106443fe467921caa (diff) | |
download | tor-45a66c69553b7185a68e516426a99f333f7fe9f6.tar.gz tor-45a66c69553b7185a68e516426a99f333f7fe9f6.zip |
make a relay_header_t struct and pack/unpack funcs
split 7-byte stream_id string into 2-byte recognized and 2-byte stream_id
fix two seg faults in fetch_from_buf_http
fix several lurking seg faults in handling unexpected relay cells
still need to
* clean up relay_crypt
* use relay dummies if there's going to be a conflict with rh.recognized
* check for a conflict when generating stream_ids
svn:r953
-rw-r--r-- | src/or/buffers.c | 4 | ||||
-rw-r--r-- | src/or/circuit.c | 112 | ||||
-rw-r--r-- | src/or/connection.c | 2 | ||||
-rw-r--r-- | src/or/connection_edge.c | 119 | ||||
-rw-r--r-- | src/or/or.h | 45 |
5 files changed, 152 insertions, 130 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c index 56c31b55c3..9a759a7c28 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -375,12 +375,12 @@ int fetch_from_buf_http(buf_t *buf, if(headers_out) { *headers_out = tor_malloc(headerlen+1); memcpy(*headers_out,buf->mem,headerlen); - *headers_out[headerlen] = 0; /* null terminate it */ + (*headers_out)[headerlen] = 0; /* null terminate it */ } if(body_out) { *body_out = tor_malloc(bodylen+1); memcpy(*body_out,buf->mem+headerlen,bodylen); - *body_out[bodylen] = 0; /* null terminate it */ + (*body_out)[bodylen] = 0; /* null terminate it */ } buf_remove_from_front(buf, headerlen+bodylen); return 1; diff --git a/src/or/circuit.c b/src/or/circuit.c index dda3077ecb..7ab9c9e4b5 100644 --- a/src/or/circuit.c +++ b/src/or/circuit.c @@ -6,6 +6,9 @@ extern or_options_t options; /* command-line and config-file options */ +static int relay_crypt(circuit_t *circ, char *in, char cell_direction, + crypt_path_t **layer_hint, char *recognized); +static connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction); static void circuit_free_cpath_node(crypt_path_t *victim); static circ_id_t get_unique_circ_id_by_conn(connection_t *conn, int circ_id_type); @@ -310,11 +313,14 @@ int circuit_stream_is_being_handled(connection_t *conn) { /* update digest from the payload of cell. assign integrity part to cell. */ void relay_set_digest(crypto_digest_env_t *digest, cell_t *cell) { uint32_t integrity; + relay_header_t rh; crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE); crypto_digest_get_digest(digest, (char *)&integrity, 4); log_fn(LOG_DEBUG,"Putting digest of %u into relay cell.",integrity); - SET_CELL_RELAY_INTEGRITY(*cell, integrity); + relay_header_unpack(&rh, cell->payload); + rh.integrity = integrity; + relay_header_pack(cell->payload, &rh); } /* update digest from the payload of cell (with the integrity part set @@ -322,10 +328,14 @@ void relay_set_digest(crypto_digest_env_t *digest, cell_t *cell) { */ int relay_check_digest(crypto_digest_env_t *digest, cell_t *cell) { uint32_t received_integrity, calculated_integrity; + relay_header_t rh; + + relay_header_unpack(&rh, cell->payload); + received_integrity = rh.integrity; + rh.integrity = 0; + relay_header_pack(cell->payload, &rh); - received_integrity = CELL_RELAY_INTEGRITY(*cell); log_fn(LOG_DEBUG,"Reading digest of %u from relay cell.",received_integrity); - SET_CELL_RELAY_INTEGRITY(*cell, 0); crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE); crypto_digest_get_digest(digest, (char *)&calculated_integrity, 4); @@ -346,15 +356,16 @@ int circuit_deliver_relay_cell(cell_t *cell, circuit_t *circ, assert(cell && circ); assert(cell_direction == CELL_DIRECTION_OUT || cell_direction == CELL_DIRECTION_IN); - log_fn(LOG_DEBUG,"direction %d, streamid %d before crypt.", cell_direction, *(int*)(cell->payload+1)); + log_fn(LOG_DEBUG,"direction %d, stream_id %d before crypt.", cell_direction, *(uint16_t*)(cell->payload+1));/*XXX*/ - if(relay_crypt(circ, cell->payload, CELL_PAYLOAD_SIZE, cell_direction, - &layer_hint, &recognized, &conn) < 0) { + if(relay_crypt(circ, cell->payload, cell_direction, + &layer_hint, &recognized) < 0) { log_fn(LOG_WARN,"relay crypt failed. Dropping connection."); return -1; } if(recognized) { + conn = relay_lookup_conn(circ, cell, cell_direction); if(cell_direction == CELL_DIRECTION_OUT) { if(relay_check_digest(circ->n_digest, cell) < 0) { log_fn(LOG_WARN,"outgoing cell failed integrity check. Closing circ."); @@ -400,14 +411,14 @@ int circuit_deliver_relay_cell(cell_t *cell, circuit_t *circ, return 0; } -int relay_crypt(circuit_t *circ, char *in, int inlen, char cell_direction, - crypt_path_t **layer_hint, char *recognized, connection_t **conn) { +static int relay_crypt(circuit_t *circ, char *in, char cell_direction, + crypt_path_t **layer_hint, char *recognized) { crypt_path_t *thishop; - char out[CELL_NETWORK_SIZE]; - - assert(circ && in && recognized && conn); + char out[CELL_PAYLOAD_SIZE]; /* 'in' must be this size too */ + relay_header_t rh; - assert(inlen < CELL_NETWORK_SIZE); + assert(circ && in && recognized); + assert(cell_direction == CELL_DIRECTION_IN || cell_direction == CELL_DIRECTION_OUT); if(cell_direction == CELL_DIRECTION_IN) { if(circ->cpath) { /* we're at the beginning of the circuit. @@ -420,16 +431,17 @@ int relay_crypt(circuit_t *circ, char *in, int inlen, char cell_direction, do { /* Remember: cpath is in forward order, that is, first hop first. */ assert(thishop); - log_fn(LOG_DEBUG,"before decrypt: %d",*(int*)(in+1)); + log_fn(LOG_DEBUG,"before decrypt: %d",*(uint16_t*)(in+1)); /* decrypt */ - if(crypto_cipher_decrypt(thishop->b_crypto, in, inlen, out)) { + if(crypto_cipher_decrypt(thishop->b_crypto, in, CELL_PAYLOAD_SIZE, out)) { log_fn(LOG_WARN,"Error performing onion decryption: %s", crypto_perror()); return -1; } - memcpy(in,out,inlen); - log_fn(LOG_DEBUG,"after decrypt: %d",*(int*)(in+1)); + memcpy(in,out,CELL_PAYLOAD_SIZE); + log_fn(LOG_DEBUG,"after decrypt: %d",*(uint16_t*)(in+1)); - if( (*recognized = relay_check_recognized(circ, cell_direction, in+1, conn))) { + if(*(uint16_t*)(in+1) == 0) { /* XXX */ + *recognized = 1; *layer_hint = thishop; return 0; } @@ -440,20 +452,19 @@ int relay_crypt(circuit_t *circ, char *in, int inlen, char cell_direction, return 0; } else { /* we're in the middle. Just one crypt. */ - log_fn(LOG_DEBUG,"before encrypt: %d",*(int*)(in+1)); - if(crypto_cipher_encrypt(circ->p_crypto, in, inlen, out)) { + log_fn(LOG_DEBUG,"before encrypt: %d",*(uint16_t*)(in+1)); + if(crypto_cipher_encrypt(circ->p_crypto, in, CELL_PAYLOAD_SIZE, out)) { log_fn(LOG_WARN,"Onion encryption failed for circID %u: %s", circ->p_circ_id, crypto_perror()); return -1; } - memcpy(in,out,inlen); - log_fn(LOG_DEBUG,"after encrypt: %d",*(int*)(in+1)); + memcpy(in,out,CELL_PAYLOAD_SIZE); + log_fn(LOG_DEBUG,"after encrypt: %d",*(uint16_t*)(in+1)); log_fn(LOG_DEBUG,"Skipping recognized check, because we're not the OP."); /* don't check for recognized. only the OP can recognize a stream on the way back. */ - } - } else if(cell_direction == CELL_DIRECTION_OUT) { + } else /* cell_direction == CELL_DIRECTION_OUT */ { if(circ->cpath) { /* we're at the beginning of the circuit. We'll want to do layered crypts. */ thishop = *layer_hint; /* we already know which layer, from when we package_raw_inbuf'ed */ @@ -461,69 +472,56 @@ int relay_crypt(circuit_t *circ, char *in, int inlen, char cell_direction, do { assert(thishop); - log_fn(LOG_DEBUG,"before encrypt: %d",*(int*)(in+1)); - if(crypto_cipher_encrypt(thishop->f_crypto, in, inlen, out)) { + log_fn(LOG_DEBUG,"before encrypt: %d",*(uint16_t*)(in+1)); + if(crypto_cipher_encrypt(thishop->f_crypto, in, CELL_PAYLOAD_SIZE, out)) { log_fn(LOG_WARN,"Error performing encryption: %s", crypto_perror()); return -1; } - memcpy(in,out,inlen); - log_fn(LOG_DEBUG,"after encrypt: %d",*(int*)(in+1)); + memcpy(in,out,CELL_PAYLOAD_SIZE); + log_fn(LOG_DEBUG,"after encrypt: %d",*(uint16_t*)(in+1)); 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)) { + if(crypto_cipher_decrypt(circ->n_crypto,in, CELL_PAYLOAD_SIZE, out)) { log_fn(LOG_WARN,"Decryption failed for circID %u: %s", circ->n_circ_id, crypto_perror()); return -1; } - memcpy(in,out,inlen); + memcpy(in,out,CELL_PAYLOAD_SIZE); - if( (*recognized = relay_check_recognized(circ, cell_direction, in+1, conn))) + if(*(uint16_t*)(in+1) == 0) { /* XXX */ + *recognized = 1; return 0; - + } } - } else { - log_fn(LOG_ERR,"unknown cell direction %d.", cell_direction); - assert(0); } - return 0; } -int relay_check_recognized(circuit_t *circ, int cell_direction, char *stream, connection_t **conn) { -/* FIXME can optimize by passing thishop in */ +static connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction) { connection_t *tmpconn; + relay_header_t rh; - if(!memcmp(stream,ZERO_STREAM,STREAM_ID_SIZE)) { - log_fn(LOG_DEBUG,"It's the zero stream. Recognized."); - return 1; /* the zero stream is always recognized */ - } - log_fn(LOG_DEBUG,"not the zero stream."); + relay_header_unpack(&rh, cell->payload); + + if(!rh.stream_id) + return NULL; if(cell_direction == CELL_DIRECTION_OUT) tmpconn = circ->n_streams; else tmpconn = circ->p_streams; - if(!tmpconn) { - log_fn(LOG_DEBUG,"No conns. Not recognized."); - return 0; - } - for( ; tmpconn; tmpconn=tmpconn->next_stream) { - if(!memcmp(stream,tmpconn->stream_id, STREAM_ID_SIZE)) { - log_fn(LOG_DEBUG,"recognized stream %d.", *(int*)stream); - *conn = tmpconn; - return 1; + if(rh.stream_id == tmpconn->stream_id) { + log_fn(LOG_DEBUG,"found conn for stream %d.", rh.stream_id); + return tmpconn; } - log_fn(LOG_DEBUG,"considered stream %d, not it.",*(int*)tmpconn->stream_id); + log_fn(LOG_DEBUG,"considered stream %d, not it.",tmpconn->stream_id); } - - log_fn(LOG_DEBUG,"Didn't recognize on this iteration of decryption."); - return 0; - + return NULL; /* probably a begin relay cell */ } void circuit_resume_edge_reading(circuit_t *circ, int edge_type, crypt_path_t *layer_hint) { @@ -1060,7 +1058,7 @@ int circuit_truncated(circuit_t *circ, crypt_path_t *layer) { for(stream = circ->p_streams; stream; stream=stream->next_stream) { if(stream->cpath_layer == victim) { - log_fn(LOG_INFO, "Marking stream %d for close.", *(int*)stream->stream_id); + log_fn(LOG_INFO, "Marking stream %d for close.", stream->stream_id); /* no need to send 'end' relay cells, * because the other side's already dead */ diff --git a/src/or/connection.c b/src/or/connection.c index aaf01b6b93..c94e30ba36 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -760,7 +760,7 @@ void assert_connection_ok(connection_t *conn, time_t now) } if (conn->type != CONN_TYPE_EXIT && conn->type != CONN_TYPE_AP) { - assert(!conn->stream_id[0]); + assert(!conn->stream_id); assert(!conn->next_stream); assert(!conn->cpath_layer); assert(!conn->package_window); diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index e5c5919549..160c4129f8 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -20,6 +20,22 @@ static void connection_edge_consider_sending_sendme(connection_t *conn); static uint32_t client_dns_lookup_entry(const char *address); static void client_dns_set_entry(const char *address, uint32_t val); +void relay_header_pack(char *dest, const relay_header_t *src) { + *(uint8_t*)(dest) = src->command; + *(uint16_t*)(dest+1) = htons(src->recognized); + *(uint16_t*)(dest+3) = htons(src->stream_id); + *(uint32_t*)(dest+5) = htonl(src->integrity); + *(uint16_t*)(dest+9) = htons(src->length); +} + +void relay_header_unpack(relay_header_t *dest, const char *src) { + dest->command = *(uint8_t*)(src); + dest->recognized = ntohs(*(uint16_t*)(src+1)); + dest->stream_id = ntohs(*(uint16_t*)(src+3)); + dest->integrity = ntohl(*(uint32_t*)(src+5)); + dest->length = ntohs(*(uint16_t*)(src+9)); +} + int connection_edge_process_inbuf(connection_t *conn) { assert(conn); @@ -127,18 +143,16 @@ int connection_edge_end(connection_t *conn, char reason, crypt_path_t *cpath_lay int connection_edge_send_command(connection_t *fromconn, circuit_t *circ, int relay_command, void *payload, int payload_len, crypt_path_t *cpath_layer) { cell_t cell; + relay_header_t rh; int cell_direction; - int is_control_cell=0; if(!circ) { log_fn(LOG_WARN,"no circ. Closing."); return -1; } - if(!fromconn || relay_command == RELAY_COMMAND_BEGIN) /* XXX more */ - is_control_cell = 1; - memset(&cell, 0, sizeof(cell_t)); + cell.command = CELL_RELAY; // if(fromconn && fromconn->type == CONN_TYPE_AP) { if(cpath_layer) { cell.circ_id = circ->n_circ_id; @@ -148,17 +162,14 @@ int connection_edge_send_command(connection_t *fromconn, circuit_t *circ, int re cell_direction = CELL_DIRECTION_IN; } - cell.command = CELL_RELAY; - SET_CELL_RELAY_COMMAND(cell, relay_command); - if(is_control_cell) - SET_CELL_STREAM_ID(cell, ZERO_STREAM); - else - SET_CELL_STREAM_ID(cell, fromconn->stream_id); - - SET_CELL_RELAY_LENGTH(cell, payload_len); - if(payload_len) { - memcpy(cell.payload+RELAY_HEADER_SIZE,payload,payload_len); - } + memset(&rh, 0, sizeof(rh)); + rh.command = relay_command; + if(fromconn) + rh.stream_id = fromconn->stream_id; /* else it's 0 */ + rh.length = payload_len; + relay_header_pack(cell.payload, &rh); + if(payload_len) + memcpy(cell.payload+RELAY_HEADER_SIZE, payload, payload_len); if(cell_direction == CELL_DIRECTION_OUT) /* AP */ relay_set_digest(cpath_layer->f_digest, &cell); @@ -180,14 +191,14 @@ int connection_edge_send_command(connection_t *fromconn, circuit_t *circ, int re * circuit, else 0. */ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection_t *conn, int edge_type, crypt_path_t *layer_hint) { - int relay_command; static int num_seen=0; uint32_t addr; + relay_header_t rh; assert(cell && circ); - relay_command = CELL_RELAY_COMMAND(*cell); -// log_fn(LOG_DEBUG,"command %d stream %d", relay_command, stream_id); + relay_header_unpack(&rh, cell->payload); +// log_fn(LOG_DEBUG,"command %d stream %d", rh.command, rh.stream_id); num_seen++; log_fn(LOG_DEBUG,"Now seen %d relay cells here.", num_seen); @@ -195,9 +206,9 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection * 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) { + if(conn->type == CONN_TYPE_EXIT && rh.command == RELAY_COMMAND_END) { log_fn(LOG_INFO,"Exit got end (%s) before we're connected. Marking for close.", - connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, CELL_RELAY_LENGTH(*cell))); + connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, rh.length)); if(conn->state == EXIT_CONN_STATE_RESOLVING) { log_fn(LOG_INFO,"...and informing resolver we don't want the answer anymore."); dns_cancel_pending_resolve(conn->address, conn); @@ -207,14 +218,14 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection return 0; } else { log_fn(LOG_WARN,"Got an unexpected relay command %d, in state %d (%s). Closing.", - relay_command, conn->state, conn_state_to_string[conn->type][conn->state]); + rh.command, conn->state, conn_state_to_string[conn->type][conn->state]); if(connection_edge_end(conn, END_STREAM_REASON_MISC, conn->cpath_layer) < 0) log_fn(LOG_WARN,"1: I called connection_edge_end redundantly."); return -1; } } - switch(relay_command) { + switch(rh.command) { case RELAY_COMMAND_BEGIN: if(edge_type == EDGE_AP) { log_fn(LOG_WARN,"relay begin request unsupported at AP. Dropping."); @@ -235,12 +246,13 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection log_fn(LOG_WARN,"2: I called connection_edge_end redundantly."); return -1; } - log_fn(LOG_DEBUG,"circ deliver_window now %d.", edge_type == EDGE_AP ? layer_hint->deliver_window : circ->deliver_window); + log_fn(LOG_DEBUG,"circ deliver_window now %d.", edge_type == EDGE_AP ? + layer_hint->deliver_window : circ->deliver_window); circuit_consider_sending_sendme(circ, edge_type, layer_hint); if(!conn) { - log_fn(LOG_INFO,"relay cell dropped, unknown stream %d.",*(int*)conn->stream_id); + log_fn(LOG_INFO,"data cell dropped, unknown stream."); return 0; } @@ -249,19 +261,18 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection return -1; /* somebody's breaking protocol. kill the whole circuit. */ } - stats_n_data_bytes_received += CELL_RELAY_LENGTH(*cell); + stats_n_data_bytes_received += rh.length; connection_write_to_buf(cell->payload + RELAY_HEADER_SIZE, - CELL_RELAY_LENGTH(*cell), conn); + rh.length, conn); connection_edge_consider_sending_sendme(conn); return 0; case RELAY_COMMAND_END: if(!conn) { - log_fn(LOG_INFO,"end cell (%s) dropped, unknown stream %d.", - connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, CELL_RELAY_LENGTH(*cell)), - *(int*)conn->stream_id); + log_fn(LOG_INFO,"end cell (%s) dropped, unknown stream.", + connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, rh.length)); return 0; } - if(CELL_RELAY_LENGTH(*cell) >= 5 && + if(rh.length >= 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. @@ -282,8 +293,8 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection } } log_fn(LOG_INFO,"end cell (%s) for stream %d. Removing stream.", - connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, CELL_RELAY_LENGTH(*cell)), - *(int*)conn->stream_id); + connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, rh.length), + conn->stream_id); #ifdef HALF_OPEN conn->done_sending = 1; @@ -344,11 +355,11 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection return 0; } if(!conn) { - log_fn(LOG_INFO,"connected cell dropped, unknown stream %d.",*(int*)conn->stream_id); + log_fn(LOG_INFO,"connected cell dropped, unknown stream."); return 0; } log_fn(LOG_INFO,"Connected! Notifying application."); - if (CELL_RELAY_LENGTH(*cell) >= 4) { + if (rh.length >= 4) { addr = ntohl(*(uint32_t*)(cell->payload + RELAY_HEADER_SIZE)); client_dns_set_entry(conn->socks_request->address, addr); } @@ -363,12 +374,14 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection if(edge_type == EDGE_AP) { assert(layer_hint); layer_hint->package_window += CIRCWINDOW_INCREMENT; - log_fn(LOG_DEBUG,"circ-level sendme at AP, packagewindow %d.", layer_hint->package_window); + log_fn(LOG_DEBUG,"circ-level sendme at AP, packagewindow %d.", + layer_hint->package_window); circuit_resume_edge_reading(circ, EDGE_AP, layer_hint); } else { assert(!layer_hint); circ->package_window += CIRCWINDOW_INCREMENT; - log_fn(LOG_DEBUG,"circ-level sendme at exit, packagewindow %d.", circ->package_window); + log_fn(LOG_DEBUG,"circ-level sendme at exit, packagewindow %d.", + circ->package_window); circuit_resume_edge_reading(circ, EDGE_EXIT, layer_hint); } return 0; @@ -378,11 +391,8 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection connection_start_reading(conn); connection_edge_package_raw_inbuf(conn); /* handle whatever might still be on the inbuf */ return 0; - default: - log_fn(LOG_WARN,"unknown relay command %d.",relay_command); - return -1; } - assert(0); + log_fn(LOG_WARN,"unknown relay command %d.",rh.command); return -1; } @@ -667,20 +677,19 @@ static void connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t assert(ap_conn->state == AP_CONN_STATE_CIRCUIT_WAIT); assert(ap_conn->socks_request); - crypto_pseudo_rand(STREAM_ID_SIZE, ap_conn->stream_id); - /* FIXME check for collisions */ + crypto_pseudo_rand(sizeof(ap_conn->stream_id), (unsigned char*) &ap_conn->stream_id); + /* XXX check for collisions */ in.s_addr = htonl(client_dns_lookup_entry(ap_conn->socks_request->address)); string_addr = in.s_addr ? inet_ntoa(in) : NULL; - memcpy(payload, ap_conn->stream_id, STREAM_ID_SIZE); - payload_len = STREAM_ID_SIZE + 1 + - snprintf(payload+STREAM_ID_SIZE,CELL_PAYLOAD_SIZE-RELAY_HEADER_SIZE-STREAM_ID_SIZE, - "%s:%d", - string_addr ? string_addr : ap_conn->socks_request->address, - ap_conn->socks_request->port); + snprintf(payload,RELAY_PAYLOAD_SIZE, + "%s:%d", + string_addr ? string_addr : ap_conn->socks_request->address, + ap_conn->socks_request->port); + payload_len = strlen(payload)+1; - log_fn(LOG_DEBUG,"Sending relay cell to begin stream %d.",*(int *)ap_conn->stream_id); + log_fn(LOG_DEBUG,"Sending relay cell to begin stream %d.",ap_conn->stream_id); if(connection_edge_send_command(ap_conn, circ, RELAY_COMMAND_BEGIN, payload, payload_len, ap_conn->cpath_layer) < 0) @@ -734,18 +743,20 @@ static int connection_ap_handshake_socks_reply(connection_t *conn, char *reply, static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) { connection_t *n_stream; + relay_header_t rh; char *colon; + relay_header_unpack(&rh, cell->payload); + /* XXX currently we don't send an end cell back if we drop the * begin because it's malformed. */ - if(!memchr(cell->payload+RELAY_HEADER_SIZE+STREAM_ID_SIZE,0, - CELL_RELAY_LENGTH(*cell)-STREAM_ID_SIZE)) { + if(!memchr(cell->payload+RELAY_HEADER_SIZE, 0, rh.length)) { log_fn(LOG_WARN,"relay begin cell has no \\0. Dropping."); return 0; } - colon = strchr(cell->payload+RELAY_HEADER_SIZE+STREAM_ID_SIZE, ':'); + colon = strchr(cell->payload+RELAY_HEADER_SIZE, ':'); if(!colon) { log_fn(LOG_WARN,"relay begin cell has no colon. Dropping."); return 0; @@ -760,8 +771,8 @@ static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) { log_fn(LOG_DEBUG,"Creating new exit connection."); n_stream = connection_new(CONN_TYPE_EXIT); - memcpy(n_stream->stream_id, cell->payload + RELAY_HEADER_SIZE, STREAM_ID_SIZE); - n_stream->address = tor_strdup(cell->payload + RELAY_HEADER_SIZE + STREAM_ID_SIZE); + n_stream->stream_id = rh.stream_id; + n_stream->address = tor_strdup(cell->payload + RELAY_HEADER_SIZE); n_stream->port = atoi(colon+1); n_stream->state = EXIT_CONN_STATE_RESOLVING; /* leave n_stream->s at -1, because it's not yet valid */ diff --git a/src/or/or.h b/src/or/or.h index 74929fe78f..6eaf7e2f8f 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -235,36 +235,45 @@ typedef uint16_t circ_id_t; /* * Relay payload: * Relay command [1 byte] - * Stream ID [7 bytes] + * Recognized [2 bytes] + * Stream ID [2 bytes] * Partial SHA-1 [4 bytes] * Length [2 bytes] - * Relay payload [495 bytes] + * Relay payload [498 bytes] */ +#if 0 #define CELL_RELAY_COMMAND(c) (*(uint8_t*)((c).payload)) #define SET_CELL_RELAY_COMMAND(c,cmd) (*(uint8_t*)((c).payload) = (cmd)) -#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" +#define CELL_RELAY_RECOGNIZED(c) (ntohs(*(uint16_t*)((c).payload+1))) +#define SET_CELL_RELAY_RECOGNIZED(c,r) (*(uint16_t*)((c).payload+1) = htons(r)) -#define CELL_RELAY_COMMAND_END_REASON(c) (*(uint8_t)((c).payload+1)) +#define STREAM_ID_SIZE 2 +//#define SET_CELL_STREAM_ID(c,id) memcpy((c).payload+1,(id),STREAM_ID_SIZE) +#define CELL_RELAY_STREAM_ID(c) (ntohs(*(uint16_t*)((c).payload+3))) +#define SET_CELL_RELAY_STREAM_ID(c,id) (*(uint16_t*)((c).payload+3) = htons(id)) +#define ZERO_STREAM 0 /* integrity is the first 32 bits (in network order) of a sha-1 of all * cell payloads that are relay cells that have been sent / delivered * to the hop on the * circuit (the integrity is zeroed while doing * each calculation) */ -#define CELL_RELAY_INTEGRITY(c) (ntohl(*(uint32_t*)((c).payload+1+STREAM_ID_SIZE))) -#define SET_CELL_RELAY_INTEGRITY(c,i) (*(uint32_t*)((c).payload+1+STREAM_ID_SIZE) = htonl(i)) +#define CELL_RELAY_INTEGRITY(c) (ntohl(*(uint32_t*)((c).payload+5))) +#define SET_CELL_RELAY_INTEGRITY(c,i) (*(uint32_t*)((c).payload+5) = htonl(i)) /* relay length is how many bytes are used in the cell payload past relay_header_size */ -#define CELL_RELAY_LENGTH(c) (ntohs(*(uint16_t*)((c).payload+1+STREAM_ID_SIZE+4))) -#define SET_CELL_RELAY_LENGTH(c,len) (*(uint16_t*)((c).payload+1+STREAM_ID_SIZE+4) = htons(len)) +#define CELL_RELAY_LENGTH(c) (ntohs(*(uint16_t*)((c).payload+9))) +#define SET_CELL_RELAY_LENGTH(c,len) (*(uint16_t*)((c).payload+9) = htons(len)) +#endif #define CELL_PAYLOAD_SIZE 509 #define CELL_NETWORK_SIZE 512 +#define RELAY_HEADER_SIZE (1+2+2+4+2) +#define RELAY_PAYLOAD_SIZE (CELL_PAYLOAD_SIZE-RELAY_HEADER_SIZE) + /* cell definition */ typedef struct { circ_id_t circ_id; @@ -272,8 +281,13 @@ typedef struct { unsigned char payload[CELL_PAYLOAD_SIZE]; } cell_t; -#define RELAY_HEADER_SIZE (1+STREAM_ID_SIZE+4+2) -#define RELAY_PAYLOAD_SIZE (CELL_PAYLOAD_SIZE-RELAY_HEADER_SIZE) +typedef struct { + uint8_t command; + uint16_t recognized; + uint16_t stream_id; + uint32_t integrity; + uint16_t length; +} relay_header_t; typedef struct buf_t buf_t; typedef struct socks_request_t socks_request_t; @@ -327,7 +341,7 @@ struct connection_t { */ /* Used only by edge connections: */ - char stream_id[STREAM_ID_SIZE]; + uint16_t stream_id; struct connection_t *next_stream; /* points to the next stream at this edge, if any */ struct crypt_path_t *cpath_layer; /* a pointer to which node in the circ this conn exits at */ int package_window; /* how many more relay cells can i send into the circuit? */ @@ -556,9 +570,6 @@ void relay_set_digest(crypto_digest_env_t *digest, cell_t *cell); int relay_check_digest(crypto_digest_env_t *digest, cell_t *cell); 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, crypt_path_t *layer_hint); int circuit_consider_stop_edge_reading(circuit_t *circ, int edge_type, crypt_path_t *layer_hint); @@ -648,6 +659,8 @@ void assert_connection_ok(connection_t *conn, time_t now); /********************************* connection_edge.c ***************************/ +void relay_header_pack(char *dest, const relay_header_t *src); +void relay_header_unpack(relay_header_t *dest, const char *src); int connection_edge_process_inbuf(connection_t *conn); int connection_edge_end(connection_t *conn, char reason, crypt_path_t *cpath_layer); |