summaryrefslogtreecommitdiff
path: root/src/or/command.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2007-10-30 18:31:30 +0000
committerNick Mathewson <nickm@torproject.org>2007-10-30 18:31:30 +0000
commit57f7c852f809b9332fc7a52058a24713b1385c14 (patch)
treebb4ecf69033a0a2552442999fc1db087a28ea8b8 /src/or/command.c
parentc0c2001a5b8fd3907c7ba93eccbd536786f57594 (diff)
downloadtor-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.c165
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;
+ }
+}
+