diff options
author | Nick Mathewson <nickm@torproject.org> | 2007-10-30 18:31:30 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2007-10-30 18:31:30 +0000 |
commit | 57f7c852f809b9332fc7a52058a24713b1385c14 (patch) | |
tree | bb4ecf69033a0a2552442999fc1db087a28ea8b8 /src/or/command.c | |
parent | c0c2001a5b8fd3907c7ba93eccbd536786f57594 (diff) | |
download | tor-57f7c852f809b9332fc7a52058a24713b1385c14.tar.gz tor-57f7c852f809b9332fc7a52058a24713b1385c14.zip |
r16282@catbus: nickm | 2007-10-30 14:28:58 -0400
Implement lots of proposal 105. None of it is enabled yet.
svn:r12285
Diffstat (limited to 'src/or/command.c')
-rw-r--r-- | src/or/command.c | 165 |
1 files changed, 135 insertions, 30 deletions
diff --git a/src/or/command.c b/src/or/command.c index d89581216b..4fa098d9a7 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -25,12 +25,16 @@ uint64_t stats_n_create_cells_processed = 0; uint64_t stats_n_created_cells_processed = 0; uint64_t stats_n_relay_cells_processed = 0; uint64_t stats_n_destroy_cells_processed = 0; +uint64_t stats_n_versions_cells_processed = 0; +uint64_t stats_n_netinfo_cells_processed = 0; -/* These are the main four functions for processing cells */ +/* These are the main functions for processing cells */ static void command_process_create_cell(cell_t *cell, or_connection_t *conn); static void command_process_created_cell(cell_t *cell, or_connection_t *conn); static void command_process_relay_cell(cell_t *cell, or_connection_t *conn); static void command_process_destroy_cell(cell_t *cell, or_connection_t *conn); +static void command_process_versions_cell(cell_t *cell, or_connection_t *conn); +static void command_process_netinfo_cell(cell_t *cell, or_connection_t *conn); #ifdef KEEP_TIMING_STATS /** This is a wrapper function around the actual function that processes the @@ -99,6 +103,16 @@ command_process_cell(cell_t *cell, or_connection_t *conn) } #endif +#ifdef KEEP_TIMING_STATS +#define PROCESS_CELL(tp, cl, cn) STMT_BEGIN { \ + ++num ## tp; \ + command_time_process_cell(cl, cn, & tp ## time , \ + command_process_ ## tp ## _cell); \ + } STMT_END +#else +#define PROCESS_CELL(tp, cl, cn) command_process_ ## tp ## _cell(cl, cn) +#endif + switch (cell->command) { case CELL_PADDING: ++stats_n_padding_cells_processed; @@ -107,47 +121,31 @@ command_process_cell(cell_t *cell, or_connection_t *conn) case CELL_CREATE: case CELL_CREATE_FAST: ++stats_n_create_cells_processed; -#ifdef KEEP_TIMING_STATS - ++num_create; - command_time_process_cell(cell, conn, &create_time, - command_process_create_cell); -#else - command_process_create_cell(cell, conn); -#endif + PROCESS_CELL(create, cell, conn); break; case CELL_CREATED: case CELL_CREATED_FAST: ++stats_n_created_cells_processed; -#ifdef KEEP_TIMING_STATS - ++num_created; - command_time_process_cell(cell, conn, &created_time, - command_process_created_cell); -#else - command_process_created_cell(cell, conn); -#endif + PROCESS_CELL(created, cell, conn); break; case CELL_RELAY: ++stats_n_relay_cells_processed; -#ifdef KEEP_TIMING_STATS - ++num_relay; - command_time_process_cell(cell, conn, &relay_time, - command_process_relay_cell); -#else - command_process_relay_cell(cell, conn); -#endif + PROCESS_CELL(relay, cell, conn); break; case CELL_DESTROY: ++stats_n_destroy_cells_processed; -#ifdef KEEP_TIMING_STATS - ++num_destroy; - command_time_process_cell(cell, conn, &destroy_time, - command_process_destroy_cell); -#else - command_process_destroy_cell(cell, conn); -#endif + PROCESS_CELL(destroy, cell, conn); + break; + case CELL_VERSIONS: + ++stats_n_versions_cells_processed; + PROCESS_CELL(versions, cell, conn); + break; + case CELL_NETINFO: + ++stats_n_netinfo_cells_processed; + PROCESS_CELL(netinfo, cell, conn); break; default: - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + log_fn(LOG_INFO, LD_PROTOCOL, "Cell of unknown type (%d) received. Dropping.", cell->command); break; } @@ -389,3 +387,110 @@ command_process_destroy_cell(cell_t *cell, or_connection_t *conn) } } +/** Process a 'versions' cell. The current link protocol version must be 0 + * to indicate that no version has yet been negotiated. DOCDOC say more. */ +static void +command_process_versions_cell(cell_t *cell, or_connection_t *conn) +{ + uint16_t versionslen; + int highest_supported_version = 0; + const char *cp, *end; + if (conn->link_proto != 0) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Received a VERSIONS cell on a connection with its version " + "already set to %d; dropping", (int) conn->link_proto); + return; + } + 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) { + if (v > highest_supported_version) + highest_supported_version = v; + } + } + if (!versionslen) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Couldn't find a version in common; defaulting to v1."); + /*XXXX020 or just break the connection?*/ + conn->link_proto = 1; + return; + } +} + +/** Process a 'netinfo' cell. DOCDOC say more. */ +static void +command_process_netinfo_cell(cell_t *cell, or_connection_t *conn) +{ + time_t timestamp; + uint8_t my_addr_type; + uint8_t my_addr_len; + const char *my_addr_ptr; + const char *cp, *end; + uint8_t n_other_addrs; + time_t now = time(NULL); + + /*XXXX020 reject duplicat netinfos. */ + + if (conn->link_proto < 2) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Received a NETINFO cell on %s connection; dropping.", + conn->link_proto == 0 ? "non-versioned" : "a v1"); + return; + } + /* Decode the cell. */ + timestamp = ntohl(get_uint32(cell->payload)); + my_addr_type = (uint8_t) cell->payload[4]; + my_addr_len = (uint8_t) cell->payload[5]; + my_addr_ptr = cell->payload + 6; + /* Possibly learn my address. XXXX020 */ + end = cell->payload + CELL_PAYLOAD_SIZE; + cp = cell->payload + 6 + my_addr_len; + if (cp >= end) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Address too long in netinfo cell; dropping."); + return; + } + + /*XXXX020 magic number 3600 */ + if (abs(timestamp - now) > 3600 && + router_get_by_digest(conn->identity_digest)) { + long delta = now - timestamp; + char dbuf[64]; + /*XXXX020 not always warn!*/ + format_time_interval(dbuf, sizeof(dbuf), delta); + log_fn(LOG_WARN, LD_HTTP, "Received NETINFO cell with skewed time from " + "server at %s:%d. It seems that our clock is %s by %s, or " + "that theirs is %s. Tor requires an accurate clock to work: " + "please check your time and date settings.", + conn->_base.address, (int)conn->_base.port, + delta>0 ? "ahead" : "behind", dbuf, + delta>0 ? "behind" : "ahead"); + control_event_general_status(LOG_WARN, + "CLOCK_SKEW SKEW=%ld SOURCE=OR:%s:%d", + delta, conn->_base.address, conn->_base.port); + } + + n_other_addrs = (uint8_t) *cp++; + while (n_other_addrs && cp < end-2) { + /* Consider all the other addresses; if any matches, this connection is + * "canonical." */ + uint8_t other_addr_type = (uint8_t) *cp++; + uint8_t other_addr_len = (uint8_t) *cp++; + if (cp + other_addr_len >= end) + break; /*XXXX020 protocol warn. */ + if (other_addr_type == RESOLVED_TYPE_IPV4 && other_addr_len == 4) { + uint32_t addr = ntohl(get_uint32(cp)); + if (addr == conn->real_addr) { + conn->is_canonical = 1; + break; + } + } + cp += other_addr_len; + --n_other_addrs; + } +} + |