Factor out cell packing and unpacking

svn:r240
This commit is contained in:
Nick Mathewson 2003-04-16 17:44:33 +00:00
parent 1bbea670bc
commit 97d847b9e3
4 changed files with 67 additions and 38 deletions

View File

@ -281,12 +281,6 @@ which reveals the downstream node.
The value of Version is currently 2.
The forward and backward ciphers fields can take the following values:
0: Identity
1: Single DES in OFB
2: RC4
3: Triple DES (encrypt-decrypt-encrypt) in OFB
The port and address field denote the IPV4 address and port of
the next onion router in the circuit, or are set to 0 for the
last hop.
@ -316,7 +310,7 @@ which reveals the downstream node.
D. Encrypt the first 128 bytes of M with the RSA key of
OR_I, using no padding. Encrypt the remaining portion of
M with DES/OFB, using K1_I as a key and an all-0 IV.
M with 3DES/OFB, using K1_I as a key and an all-0 IV.
3. M is now the onion.
@ -365,7 +359,7 @@ which reveals the downstream node.
in the past, then tear down the circuit (see section 4.2).
Compute K1 through K3 as above. Use K1 to decrypt the rest
of the onion using DES/OFB.
of the onion using 3DES/OFB.
If we are not the exit node, remove the first layer from the
decrypted onion, and send the remainder to the next OR
@ -403,14 +397,14 @@ which reveals the downstream node.
Otherwise, if the OR is not at the OP edge of the circuit (that is,
either an 'exit node' or a non-edge node), it de/encrypts the length
field and the payload with DES/OFB, as follows:
field and the payload with 3DES/OFB, as follows:
'Forward' data cell (same direction as onion):
Use K2 as key; encrypt.
'Back' data cell (opposite direction from onion):
Use K3 as key; decrypt.
Otherwise, if the data cell has arrived to the OP edge of the circuit,
the OP de/encrypts the length and payload fields with DES/OFB as
the OP de/encrypts the length and payload fields with 3DES/OFB as
follows:
OP sends data cell:
For I=1...N, decrypt with K2_I.

View File

@ -543,7 +543,6 @@ void connection_send_cell(connection_t *conn) {
*/
conn->outbuf_flushlen += sizeof(cell_t); /* instruct it to send a cell */
connection_start_writing(conn);
}
void connection_increment_send_timeval(connection_t *conn) {
@ -584,12 +583,7 @@ int connection_write_cell_to_buf(const cell_t *cellp, connection_t *conn) {
char networkcell[CELL_NETWORK_SIZE];
char *n = networkcell;
memset(n,0,CELL_NETWORK_SIZE); /* zero it out to start */
*(aci_t *)n = htons(cellp->aci);
*(n+2) = cellp->command;
*(n+3) = cellp->length;
/* seq is reserved, leave zero */
memcpy(n+8,cellp->payload,CELL_PAYLOAD_SIZE);
cell_pack(n, cellp);
if(connection_encrypt_cell(n,conn)<0) {
return -1;
@ -676,7 +670,7 @@ repeat_connection_package_raw_inbuf:
* compressing.
* 2)
*/
len = connection_compress_from_buf(cell.payload + TOPIC_HEADER_SIZE,
len = connection_compress_from_buf(cell.payload,
CELL_PAYLOAD_SIZE - TOPIC_HEADER_SIZE,
conn, Z_SYNC_FLUSH);
if (len < 0)
@ -690,7 +684,7 @@ repeat_connection_package_raw_inbuf:
cell.length = amount_to_process;
}
if(connection_fetch_from_buf(cell.payload+TOPIC_HEADER_SIZE, cell.length, conn) < 0)
if(connection_fetch_from_buf(cell.payload, cell.length, conn) < 0)
return -1;
#endif
@ -702,10 +696,11 @@ repeat_connection_package_raw_inbuf:
log(LOG_DEBUG,"connection_package_raw_inbuf(): (%d) Packaging %d bytes (%d waiting).",conn->s,cell.length, conn->inbuf_datalen);
*(uint16_t *)(cell.payload+2) = htons(conn->topic_id);
*cell.payload = TOPIC_COMMAND_DATA;
cell.length += TOPIC_HEADER_SIZE;
cell.command = CELL_DATA;
cell.topic_command = TOPIC_COMMAND_DATA;
cell.topic_id = conn->topic_id;
cell.length += TOPIC_HEADER_SIZE;
if(conn->type == CONN_TYPE_EXIT) {
cell.aci = circ->p_aci;
@ -756,10 +751,10 @@ int connection_consider_sending_sendme(connection_t *conn, int edge_type) {
}
memset(&cell, 0, sizeof(cell_t));
*(uint16_t *)(cell.payload+2) = htons(conn->topic_id);
*cell.payload = TOPIC_COMMAND_SENDME;
cell.length += TOPIC_HEADER_SIZE;
cell.command = CELL_DATA;
cell.topic_command = TOPIC_COMMAND_SENDME;
cell.topic_id = conn->topic_id;
cell.length += TOPIC_HEADER_SIZE;
if(edge_type == EDGE_EXIT) { /* we're at an exit */
if(conn->p_receive_topicwindow < TOPICWINDOW_START - TOPICWINDOW_INCREMENT) {
@ -850,11 +845,7 @@ int connection_process_cell_from_inbuf(connection_t *conn) {
#endif
/* retrieve cell info from outbuf (create the host-order struct from the network-order string) */
memset(&cell,0,sizeof(cell_t)); /* zero it out to start */
cell.aci = ntohs(*(aci_t *)outbuf);
cell.command = *(outbuf+2);
cell.length = *(outbuf+3);
memcpy(cell.payload, outbuf+8, CELL_PAYLOAD_SIZE);
cell_unpack(&cell, outbuf);
// log(LOG_DEBUG,"connection_process_cell_from_inbuf(): Decrypted cell is of type %u (ACI %u).",cellp->command,cellp->aci);
command_process_cell(&cell, conn);
@ -862,6 +853,40 @@ int connection_process_cell_from_inbuf(connection_t *conn) {
return connection_process_inbuf(conn); /* process the remainder of the buffer */
}
void
cell_pack(char *dest, const cell_t *src)
{
*(uint16_t*)dest = htons(src->aci);
*(uint8_t*)(dest+2) = src->command;
*(uint8_t*)(dest+3) = src->length;
*(uint32_t*)(dest+4) = 0; /* Reserved */
if (src->command != CELL_DATA) {
memcpy(dest+8, src->payload, CELL_PAYLOAD_SIZE);
} else {
*(uint8_t*)(dest+8) = src->topic_command;
*(uint8_t*)(dest+9) = 0;
*(uint16_t*)(dest+10) = htons(src->topic_id);
memcpy(dest+12, src->payload, CELL_PAYLOAD_SIZE - TOPIC_HEADER_SIZE);
}
}
void
cell_unpack(cell_t *dest, const char *src)
{
dest->aci = ntohs(*(uint16_t*)(src));
dest->command = *(uint8_t*)(src+2);
dest->length = *(uint8_t*)(src+3);
dest->seq = ntohl(*(uint32_t*)(src+4));
if (dest->command != CELL_DATA) {
memcpy(dest->payload, src+8, CELL_PAYLOAD_SIZE);
} else {
dest->topic_command = *(uint8_t*)(src+8);
/* zero = *(uint8_t*)(src+9); */
dest->topic_id = ntohs(*(uint16_t*)(src+10));
memcpy(dest->payload, src+12, CELL_PAYLOAD_SIZE - TOPIC_HEADER_SIZE);
}
}
/*
Local Variables:
mode:c

View File

@ -27,9 +27,10 @@ int connection_edge_process_inbuf(connection_t *conn) {
memset(&cell, 0, sizeof(cell_t));
cell.command = CELL_DATA;
cell.length = TOPIC_HEADER_SIZE;
*(uint16_t *)(cell.payload+2) = htons(conn->topic_id);
*cell.payload = TOPIC_COMMAND_END;
cell.topic_command = TOPIC_COMMAND_END;
cell.topic_id = conn->topic_id;
cell.aci = circ->n_aci;
if (circuit_deliver_data_cell_from_edge(&cell, circ, conn->type) < 0) {
log(LOG_DEBUG,"connection_edge_process_inbuf: circuit_deliver_data_cell_from_edge failed. Closing");
circuit_close(circ);
@ -75,8 +76,9 @@ int connection_edge_send_command(connection_t *conn, circuit_t *circ, int topic_
else
cell.aci = circ->p_aci;
cell.command = CELL_DATA;
*(uint16_t *)(cell.payload+2) = htons(conn->topic_id);
*cell.payload = topic_command;
cell.topic_command = topic_command;
cell.topic_id = conn->topic_id;
cell.length = TOPIC_HEADER_SIZE;
log(LOG_INFO,"connection_edge_send_command(): delivering %d cell %s.", topic_command, conn->type == CONN_TYPE_AP ? "forward" : "backward");
@ -98,8 +100,8 @@ int connection_edge_process_data_cell(cell_t *cell, circuit_t *circ, int edge_ty
assert(cell && circ);
topic_command = *cell->payload;
topic_id = ntohs(*(uint16_t *)(cell->payload+2));
topic_command = cell->topic_command;
topic_id = cell->topic_id;
log(LOG_DEBUG,"connection_edge_process_data_cell(): command %d topic %d", topic_command, topic_id);
num_seen++;
log(LOG_DEBUG,"connection_edge_process_data_cell(): Now seen %d data cells here.", num_seen);
@ -151,7 +153,7 @@ int connection_edge_process_data_cell(cell_t *cell, circuit_t *circ, int edge_ty
}
#ifdef USE_ZLIB
if(connection_decompress_to_buf(cell->payload + TOPIC_HEADER_SIZE,
if(connection_decompress_to_buf(cell->payload,
cell->length - TOPIC_HEADER_SIZE,
conn, Z_SYNC_FLUSH) < 0) {
log(LOG_INFO,"connection_edge_process_data_cell(): write to buf failed. Marking for close.");
@ -159,7 +161,7 @@ int connection_edge_process_data_cell(cell_t *cell, circuit_t *circ, int edge_ty
return 0;
}
#else
if(connection_write_to_buf(cell->payload + TOPIC_HEADER_SIZE,
if(connection_write_to_buf(cell->payload,
cell->length - TOPIC_HEADER_SIZE, conn) < 0) {
conn->marked_for_close = 1;
return 0;

View File

@ -197,6 +197,11 @@ typedef struct {
unsigned char command;
unsigned char length; /* of payload if data cell, else value of sendme */
uint32_t seq; /* sequence number */
/* The following 2 fields are only set when command is CELL_DATA */
unsigned char topic_command;
uint16_t topic_id;
unsigned char payload[CELL_PAYLOAD_SIZE];
} cell_t;
@ -614,6 +619,9 @@ int connection_process_cell_from_inbuf(connection_t *conn);
int connection_consider_sending_sendme(connection_t *conn, int edge_type);
int connection_finished_flushing(connection_t *conn);
void cell_pack(char *dest, const cell_t *src);
void cell_unpack(cell_t *dest, const char *src);
/********************************* connection_ap.c ****************************/
int ap_handshake_process_socks(connection_t *conn);