diff options
-rw-r--r-- | src/or/circuit.c | 39 | ||||
-rw-r--r-- | src/or/command.c | 10 | ||||
-rw-r--r-- | src/or/connection_edge.c | 50 | ||||
-rw-r--r-- | src/or/connection_or.c | 8 | ||||
-rw-r--r-- | src/or/onion.c | 1 | ||||
-rw-r--r-- | src/or/or.h | 44 |
6 files changed, 74 insertions, 78 deletions
diff --git a/src/or/circuit.c b/src/or/circuit.c index fa5883ec1e..7a7cc13b63 100644 --- a/src/or/circuit.c +++ b/src/or/circuit.c @@ -303,24 +303,18 @@ 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[1+CELL_PAYLOAD_SIZE]; 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_fn(LOG_DEBUG,"direction %d, streamid %d before crypt.", cell_direction, *(int*)(cell->payload+1)); - if(relay_crypt(circ, buf, 1+CELL_PAYLOAD_SIZE, cell_direction, &layer_hint, &recognized, &conn) < 0) { + if(relay_crypt(circ, cell->payload, CELL_PAYLOAD_SIZE, cell_direction, + &layer_hint, &recognized, &conn) < 0) { log_fn(LOG_WARN,"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) { #if 0 @@ -374,11 +368,11 @@ int circuit_deliver_relay_cell(cell_t *cell, circuit_t *circ, 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]; + char out[CELL_NETWORK_SIZE]; assert(circ && in && recognized && conn); - assert(inlen < 256); + assert(inlen < CELL_NETWORK_SIZE); if(cell_direction == CELL_DIRECTION_IN) { if(circ->cpath) { /* we're at the beginning of the circuit. @@ -391,16 +385,16 @@ 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+2)); + log_fn(LOG_DEBUG,"before decrypt: %d",*(int*)(in+1)); /* decrypt */ if(crypto_cipher_decrypt(thishop->b_crypto, in, inlen, 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+2)); + log_fn(LOG_DEBUG,"after decrypt: %d",*(int*)(in+1)); - if( (*recognized = relay_check_recognized(circ, cell_direction, in+2, conn))) { + if( (*recognized = relay_check_recognized(circ, cell_direction, in+1, conn))) { *layer_hint = thishop; return 0; } @@ -411,14 +405,14 @@ 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+2)); + log_fn(LOG_DEBUG,"before encrypt: %d",*(int*)(in+1)); if(crypto_cipher_encrypt(circ->p_crypto, in, inlen, 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+2)); + log_fn(LOG_DEBUG,"after encrypt: %d",*(int*)(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. */ @@ -432,13 +426,13 @@ 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+2)); + log_fn(LOG_DEBUG,"before encrypt: %d",*(int*)(in+1)); if(crypto_cipher_encrypt(thishop->f_crypto, in, inlen, 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+2)); + log_fn(LOG_DEBUG,"after encrypt: %d",*(int*)(in+1)); thishop = thishop->prev; } while(thishop != circ->cpath->prev); @@ -451,7 +445,7 @@ int relay_crypt(circuit_t *circ, char *in, int inlen, char cell_direction, } memcpy(in,out,inlen); - if( (*recognized = relay_check_recognized(circ, cell_direction, in+2, conn))) + if( (*recognized = relay_check_recognized(circ, cell_direction, in+1, conn))) return 0; } @@ -556,8 +550,8 @@ int circuit_consider_sending_sendme(circuit_t *circ, int edge_type, crypt_path_t cell.command = CELL_RELAY; SET_CELL_RELAY_COMMAND(cell, RELAY_COMMAND_SENDME); SET_CELL_STREAM_ID(cell, ZERO_STREAM); + SET_CELL_RELAY_LENGTH(cell, 0); - cell.length = RELAY_HEADER_SIZE; if(edge_type == EDGE_AP) { /* i'm the AP */ cell.circ_id = circ->n_circ_id; while(layer_hint->deliver_window < CIRCWINDOW_START-CIRCWINDOW_INCREMENT) { @@ -862,7 +856,6 @@ int circuit_send_next_onion_skin(circuit_t *circ) { memset(&cell, 0, sizeof(cell_t)); cell.command = CELL_CREATE; cell.circ_id = circ->n_circ_id; - cell.length = ONIONSKIN_CHALLENGE_LEN; if(onion_skin_create(circ->n_conn->onion_pkey, &(circ->cpath->handshake_state), cell.payload) < 0) { log_fn(LOG_WARN,"onion_skin_create (first hop) failed."); @@ -899,11 +892,12 @@ int circuit_send_next_onion_skin(circuit_t *circ) { cell.circ_id = circ->n_circ_id; SET_CELL_RELAY_COMMAND(cell, RELAY_COMMAND_EXTEND); SET_CELL_STREAM_ID(cell, ZERO_STREAM); + SET_CELL_RELAY_LENGTH(cell, 6+ONIONSKIN_CHALLENGE_LEN); - cell.length = RELAY_HEADER_SIZE + 6 + ONIONSKIN_CHALLENGE_LEN; *(uint32_t*)(cell.payload+RELAY_HEADER_SIZE) = htonl(hop->addr); *(uint16_t*)(cell.payload+RELAY_HEADER_SIZE+4) = htons(hop->port); - if(onion_skin_create(router->onion_pkey, &(hop->handshake_state), cell.payload+RELAY_HEADER_SIZE+6) < 0) { + if(onion_skin_create(router->onion_pkey, &(hop->handshake_state), + cell.payload+RELAY_HEADER_SIZE+6) < 0) { log_fn(LOG_WARN,"onion_skin_create failed."); return -1; } @@ -971,7 +965,6 @@ int circuit_extend(cell_t *cell, circuit_t *circ) { memset(&newcell, 0, sizeof(cell_t)); newcell.command = CELL_CREATE; newcell.circ_id = circ->n_circ_id; - newcell.length = ONIONSKIN_CHALLENGE_LEN; memcpy(newcell.payload, cell->payload+RELAY_HEADER_SIZE+6, ONIONSKIN_CHALLENGE_LEN); diff --git a/src/or/command.c b/src/or/command.c index ed0a8d04d0..8935fcb082 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -103,13 +103,8 @@ static void command_process_create_cell(cell_t *cell, connection_t *conn) { circ = circuit_new(cell->circ_id, conn); circ->state = CIRCUIT_STATE_ONIONSKIN_PENDING; - if(cell->length != ONIONSKIN_CHALLENGE_LEN) { - log_fn(LOG_WARN,"Bad cell length %d. Dropping.", cell->length); - circuit_close(circ); - return; - } - memcpy(circ->onionskin,cell->payload,cell->length); + memcpy(circ->onionskin, cell->payload, ONIONSKIN_CHALLENGE_LEN); /* hand it off to the cpuworkers, and then return */ if(assign_to_cpuworker(NULL, CPUWORKER_TASK_ONION, circ) < 0) { @@ -135,7 +130,6 @@ static void command_process_created_cell(cell_t *cell, connection_t *conn) { circuit_close(circ); return; } - assert(cell->length == ONIONSKIN_REPLY_LEN); if(circ->cpath) { /* we're the OP. Handshake this. */ log_fn(LOG_DEBUG,"at OP. Finishing handshake."); @@ -153,7 +147,7 @@ static void command_process_created_cell(cell_t *cell, connection_t *conn) { } else { /* pack it into an extended relay cell, and send it. */ log_fn(LOG_INFO,"Converting created cell to extended relay cell, sending."); connection_edge_send_command(NULL, circ, RELAY_COMMAND_EXTENDED, - cell->payload, cell->length, NULL); + cell->payload, ONIONSKIN_REPLY_LEN, NULL); } } diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 32b7c688bc..4d6be11068 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -75,7 +75,7 @@ int connection_edge_process_inbuf(connection_t *conn) { return 0; } -char *connection_edge_end_reason(char *payload, unsigned char length) { +static char *connection_edge_end_reason(char *payload, uint16_t length) { if(length < 1) { log_fn(LOG_WARN,"End cell arrived with length 0. Should be at least 1."); return "MALFORMED"; @@ -155,7 +155,7 @@ int connection_edge_send_command(connection_t *fromconn, circuit_t *circ, int re else SET_CELL_STREAM_ID(cell, fromconn->stream_id); - cell.length = RELAY_HEADER_SIZE + payload_len; + SET_CELL_RELAY_LENGTH(cell, payload_len); if(payload_len) { memcpy(cell.payload+RELAY_HEADER_SIZE,payload,payload_len); } @@ -191,7 +191,7 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection 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) { 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->length)); + connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, CELL_RELAY_LENGTH(*cell))); 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); @@ -248,19 +248,19 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection } // printf("New text for buf (%d bytes): '%s'", cell->length - RELAY_HEADER_SIZE, cell->payload + RELAY_HEADER_SIZE); - stats_n_data_bytes_received += (cell->length - RELAY_HEADER_SIZE); + stats_n_data_bytes_received += CELL_RELAY_LENGTH(*cell); connection_write_to_buf(cell->payload + RELAY_HEADER_SIZE, - cell->length - RELAY_HEADER_SIZE, conn); + CELL_RELAY_LENGTH(*cell), 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->length), + connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, CELL_RELAY_LENGTH(*cell)), *(int*)conn->stream_id); return 0; } - if(cell->length-RELAY_HEADER_SIZE >= 5 && + if(CELL_RELAY_LENGTH(*cell) >= 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. @@ -281,7 +281,7 @@ 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->length), + connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, CELL_RELAY_LENGTH(*cell)), *(int*)conn->stream_id); #ifdef HALF_OPEN @@ -347,7 +347,7 @@ int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection return 0; } log_fn(LOG_INFO,"Connected! Notifying application."); - if (cell->length-RELAY_HEADER_SIZE == 4) { + if (CELL_RELAY_LENGTH(*cell) >= 4) { addr = ntohl(*(uint32_t*)(cell->payload + RELAY_HEADER_SIZE)); client_dns_set_entry(conn->socks_request->address, addr); } @@ -444,45 +444,45 @@ int connection_edge_package_raw_inbuf(connection_t *conn) { int amount_to_process, length; char payload[CELL_PAYLOAD_SIZE]; circuit_t *circ; - + assert(conn); assert(!connection_speaks_cells(conn)); - + repeat_connection_edge_package_raw_inbuf: - + circ = circuit_get_by_conn(conn); if(!circ) { log_fn(LOG_INFO,"conn has no circuits! Closing."); return -1; } - + if(circuit_consider_stop_edge_reading(circ, conn->type, conn->cpath_layer)) return 0; - + if(conn->package_window <= 0) { log_fn(LOG_WARN,"called with package_window %d. Tell Roger.", conn->package_window); connection_stop_reading(conn); return 0; } - + amount_to_process = buf_datalen(conn->inbuf); - + if(!amount_to_process) return 0; - - if(amount_to_process > CELL_PAYLOAD_SIZE - RELAY_HEADER_SIZE) { - length = CELL_PAYLOAD_SIZE - RELAY_HEADER_SIZE; + + if(amount_to_process > RELAY_PAYLOAD_SIZE) { + length = RELAY_PAYLOAD_SIZE; } else { length = amount_to_process; } stats_n_data_bytes_packaged += length; stats_n_data_cells_packaged += 1; - + connection_fetch_from_buf(payload, length, conn); - log_fn(LOG_DEBUG,"(%d) Packaging %d bytes (%d waiting).",conn->s,length, + log_fn(LOG_DEBUG,"(%d) Packaging %d bytes (%d waiting).", conn->s, length, (int)buf_datalen(conn->inbuf)); - + if(connection_edge_send_command(conn, circ, RELAY_COMMAND_DATA, payload, length, conn->cpath_layer) < 0) return 0; /* circuit is closed, don't continue */ @@ -495,7 +495,7 @@ repeat_connection_edge_package_raw_inbuf: assert(conn->cpath_layer->package_window > 0); conn->cpath_layer->package_window--; } - + if(--conn->package_window <= 0) { /* is it 0 after decrement? */ connection_stop_reading(conn); log_fn(LOG_DEBUG,"conn->package_window reached 0."); @@ -503,7 +503,7 @@ repeat_connection_edge_package_raw_inbuf: return 0; /* don't process the inbuf any more */ } log_fn(LOG_DEBUG,"conn->package_window is now %d",conn->package_window); - + /* handle more if there's more, or return 0 if there isn't */ goto repeat_connection_edge_package_raw_inbuf; } @@ -740,7 +740,7 @@ static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ) { */ if(!memchr(cell->payload+RELAY_HEADER_SIZE+STREAM_ID_SIZE,0, - cell->length-RELAY_HEADER_SIZE-STREAM_ID_SIZE)) { + CELL_RELAY_LENGTH(*cell)-STREAM_ID_SIZE)) { log_fn(LOG_WARN,"relay begin cell has no \\0. Dropping."); return 0; } diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 212453411b..e516913877 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -14,17 +14,13 @@ static int connection_or_process_cell_from_inbuf(connection_t *conn); static void cell_pack(char *dest, const cell_t *src) { *(uint16_t*)dest = htons(src->circ_id); *(uint8_t*)(dest+2) = src->command; - *(uint8_t*)(dest+3) = src->length; - *(uint32_t*)(dest+4) = 0; /* Reserved */ - memcpy(dest+8, src->payload, CELL_PAYLOAD_SIZE); + memcpy(dest+3, src->payload, CELL_PAYLOAD_SIZE); } static void cell_unpack(cell_t *dest, const char *src) { dest->circ_id = ntohs(*(uint16_t*)(src)); dest->command = *(uint8_t*)(src+2); - dest->length = *(uint8_t*)(src+3); - dest->seq = ntohl(*(uint32_t*)(src+4)); - memcpy(dest->payload, src+8, CELL_PAYLOAD_SIZE); + memcpy(dest->payload, src+3, CELL_PAYLOAD_SIZE); } /**************************************************************/ diff --git a/src/or/onion.c b/src/or/onion.c index 0923741d92..5c52dd6295 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -124,7 +124,6 @@ int onionskin_answer(circuit_t *circ, unsigned char *payload, unsigned char *key memset(&cell, 0, sizeof(cell_t)); cell.command = CELL_CREATED; cell.circ_id = circ->p_circ_id; - cell.length = ONIONSKIN_REPLY_LEN; circ->state = CIRCUIT_STATE_OPEN; diff --git a/src/or/or.h b/src/or/or.h index 7cab9f17be..0b63ccf286 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -190,8 +190,6 @@ #define RELAY_COMMAND_TRUNCATED 9 #define RELAY_COMMAND_DROP 10 -#define RELAY_HEADER_SIZE 8 - #define END_STREAM_REASON_MISC 1 #define END_STREAM_REASON_RESOLVEFAILED 2 #define END_STREAM_REASON_CONNECTFAILED 3 @@ -225,9 +223,6 @@ #define CELL_RELAY 3 #define CELL_DESTROY 4 -#define CELL_PAYLOAD_SIZE 248 -#define CELL_NETWORK_SIZE 256 - /* legal characters in a filename */ #define CONFIG_LEGAL_FILENAME_CHARACTERS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_/" /* legal characters in a nickname */ @@ -237,27 +232,45 @@ typedef uint16_t circ_id_t; -/* cell definition */ -typedef struct { - circ_id_t circ_id; - unsigned char command; - unsigned char length; /* of payload if relay cell */ - uint32_t seq; /* sequence number */ +/* + * Relay payload: + * Relay command [1 byte] + * Stream ID [7 bytes] + * Partial SHA-1 [4 bytes] + * Length [2 bytes] + * Relay payload [495 bytes] + */ - 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 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_COMMAND_END_REASON(c) (*(uint8_t)((c).payload+1)) -#define ZERO_STREAM "\0\0\0\0\0\0\0\0" +/* relay length is how many bytes are used in the cell payload past relay_header_size */ +#define CELL_RELAY_LENGTH(c) (*(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) = (len)) + +#define CELL_PAYLOAD_SIZE 509 +#define CELL_NETWORK_SIZE 512 + +/* cell definition */ +typedef struct { + circ_id_t circ_id; + unsigned char command; + 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 buf_t buf_t; typedef struct socks_request_t socks_request_t; -struct connection_t { +struct connection_t { uint8_t type; uint8_t state; @@ -476,6 +489,7 @@ typedef struct { int loglevel; } or_options_t; +/* XXX are these good enough defaults? */ #define MAX_SOCKS_REPLY_LEN 256 /* Not 256; addresses must fit in a begin cell. */ #define MAX_SOCKS_ADDR_LEN 200 |