diff --git a/doc/TODO b/doc/TODO index eec7dc7a49..bdd83e40c7 100644 --- a/doc/TODO +++ b/doc/TODO @@ -32,7 +32,8 @@ Things we'd like to do in 0.2.0.x: - Variable-length cells o Add structure o Add parse logic - - Make CERT and VERSIONS variable. + - Make CERT variable. + o Make VERSIONS variable. - CERT cells - functions to parse x509 certs - functions to validate a single x509 cert against a TLS connection diff --git a/src/or/buffers.c b/src/or/buffers.c index e4ee8dc5c7..8c988f84c8 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -1015,9 +1015,8 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out) length = ntohs(get_uint16(hdr+3)); if (buf->datalen < (size_t)(VAR_CELL_HEADER_SIZE+length)) return 1; - result = tor_malloc(sizeof(var_cell_t)+length-1); + result = var_cell_new(length); result->command = command; - result->payload_len = length; result->circ_id = ntohs(*(uint16_t*)hdr); buf_remove_from_front(buf, VAR_CELL_HEADER_SIZE); diff --git a/src/or/command.c b/src/or/command.c index d46012ade5..100f1c379f 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -454,7 +454,6 @@ command_process_destroy_cell(cell_t *cell, or_connection_t *conn) static void command_process_versions_cell(var_cell_t *cell, or_connection_t *conn) { - uint16_t versionslen; int highest_supported_version = 0; const char *cp, *end; if (conn->link_proto != 0 || @@ -466,13 +465,10 @@ command_process_versions_cell(var_cell_t *cell, or_connection_t *conn) return; } tor_assert(conn->handshake_state); - versionslen = ntohs(get_uint16(cell->payload)); - end = cell->payload + 2 + versionslen; - if (end > cell->payload + CELL_PAYLOAD_SIZE) - end = cell->payload + CELL_PAYLOAD_SIZE; /*XXXX020 warn?*/ - for (cp = cell->payload + 2; cp < end; ++cp) { - uint8_t v = *cp; - if (v == 1) { + end = cell->payload + cell->payload_len; + for (cp = cell->payload; cp+1 < end; ++cp) { + uint16_t v = ntohs(get_uint16(cp)); + if (v == 1 || v == 2) { if (v > highest_supported_version) highest_supported_version = v; } diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 0645e3eb4e..7842d8da9e 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -149,13 +149,24 @@ cell_unpack(cell_t *dest, const char *src) /** DOCDOC */ void -var_cell_pack_header(var_cell_t *cell, char *hdr_out) +var_cell_pack_header(const var_cell_t *cell, char *hdr_out) { *(uint16_t*)(hdr_out) = htons(cell->circ_id); *(uint8_t*)(hdr_out+2) = cell->command; set_uint16(hdr_out+3, htons(cell->payload_len)); } +/* DOCDOC*/ +var_cell_t * +var_cell_new(uint16_t payload_len) +{ + var_cell_t *cell = tor_malloc(sizeof(var_cell_t)+payload_len-1); + cell->payload_len = payload_len; + cell->command = 0; + cell->circ_id = 0; + return cell; +} + /** DOCDOC */ void var_cell_free(var_cell_t *cell) @@ -841,6 +852,19 @@ connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn) connection_write_to_buf(networkcell.body, CELL_NETWORK_SIZE, TO_CONN(conn)); } +/**DOCDOC*/ +void +connection_or_write_var_cell_to_buf(const var_cell_t *cell, + or_connection_t *conn) +{ + char hdr[VAR_CELL_HEADER_SIZE]; + tor_assert(cell); + tor_assert(conn); + var_cell_pack_header(cell, hdr); + connection_write_to_buf(hdr, sizeof(hdr), TO_CONN(conn)); + connection_write_to_buf(cell->payload, cell->payload_len, TO_CONN(conn)); +} + /** DOCDOC */ static int connection_fetch_var_cell_from_buf(or_connection_t *conn, var_cell_t **out) @@ -924,22 +948,21 @@ connection_or_send_destroy(uint16_t circ_id, or_connection_t *conn, int reason) static int connection_or_send_versions(or_connection_t *conn) { - cell_t cell; - uint8_t versions[] = { 1 }; + var_cell_t *cell; + uint16_t versions[] = { 1, 2 }; int n_versions = sizeof(versions) / sizeof(uint8_t); int i; tor_assert(conn->handshake_state && !conn->handshake_state->sent_versions_at); - memset(&cell, 0, sizeof(cell_t)); - cell.command = CELL_VERSIONS; - set_uint16(cell.payload, htons(n_versions)); + /*XXXX020 docdoc 2-byte versions */ + cell = var_cell_new(n_versions * 2); + cell->command = CELL_VERSIONS; for (i = 0; i < n_versions; ++i) { - uint8_t v = versions[i]; - tor_assert(v > 0 && v < 128); - cell.payload[2+i] = v; + uint16_t v = versions[i]; + set_uint16(cell->payload+(2*i), htons(v)); } - connection_or_write_cell_to_buf(&cell, conn); + connection_or_write_var_cell_to_buf(cell, conn); conn->handshake_state->sent_versions_at = time(NULL); return 0; @@ -1054,3 +1077,4 @@ connection_or_send_link_auth(or_connection_t *conn) * authenticated. */ return 0; } + diff --git a/src/or/or.h b/src/or/or.h index abc3916581..93c054241d 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2790,6 +2790,8 @@ void or_handshake_state_free(or_handshake_state_t *state); int connection_or_set_state_open(or_connection_t *conn); void connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn); +void connection_or_write_var_cell_to_buf(const var_cell_t *cell, + or_connection_t *conn); int connection_or_send_destroy(uint16_t circ_id, or_connection_t *conn, int reason); int connection_or_send_netinfo(or_connection_t *conn); @@ -2799,7 +2801,8 @@ int connection_or_compute_link_auth_hmac(or_connection_t *conn, char *hmac_out); void cell_pack(packed_cell_t *dest, const cell_t *src); -void var_cell_pack_header(var_cell_t *cell, char *hdr_out); +void var_cell_pack_header(const var_cell_t *cell, char *hdr_out); +var_cell_t *var_cell_new(uint16_t payload_len); void var_cell_free(var_cell_t *cell); /********************************* control.c ***************************/