move cell size to 512 bytes

move length to 2 bytes, put it in the relay header
remove 4 reserved bytes in cell
add 4 bytes to relay header for the integrity check


svn:r942
This commit is contained in:
Roger Dingledine
2003-12-16 09:48:17 +00:00
parent 961ecf7abf
commit 8712a30e91
6 changed files with 74 additions and 78 deletions
+16 -23
View File
@@ -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);
+2 -8
View File
@@ -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);
}
}
+25 -25
View File
@@ -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;
}
+2 -6
View File
@@ -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);
}
/**************************************************************/
-1
View File
@@ -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;
+29 -15
View File
@@ -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