[tor-commits] [tor/master] Actually send back correctly-formed IPv6 CONNECTED cells

nickm at torproject.org nickm at torproject.org
Thu Nov 15 19:47:53 UTC 2012


commit 882b389668067a29bb539d0f5bd5cb2f83b93012
Author: Nick Mathewson <nickm at torproject.org>
Date:   Wed Nov 14 10:48:58 2012 -0500

    Actually send back correctly-formed IPv6 CONNECTED cells
    
    We had some old code to send back connected cells for IPv6 addresses,
    but it was wrong.  Fortunately, it was also unreachable.
---
 src/or/connection_edge.c     |   79 +++++++++++++++++++++++++++--------------
 src/or/connection_edge.h     |    4 ++-
 src/test/test_cell_formats.c |   40 ++++++++++++++++++++-
 3 files changed, 94 insertions(+), 29 deletions(-)

diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 4f3dda2..fbba172 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -392,6 +392,38 @@ connection_edge_finished_flushing(edge_connection_t *conn)
   return 0;
 }
 
+/** DOCDOC */
+#define MAX_CONNECTED_CELL_PAYLOAD_LEN 25
+
+/** DOCDOC */
+/* private */int
+connected_cell_format_payload(uint8_t *payload_out,
+                              const tor_addr_t *addr,
+                              uint32_t ttl)
+{
+  const sa_family_t family = tor_addr_family(addr);
+  int connected_payload_len;
+
+  if (family == AF_INET) {
+    set_uint32(payload_out, tor_addr_to_ipv4n(addr));
+    connected_payload_len = 4;
+  } else if (family == AF_INET6) {
+    set_uint32(payload_out, 0);
+    set_uint8(payload_out + 4, 6);
+    memcpy(payload_out + 5, tor_addr_to_in6_addr8(addr), 16);
+    connected_payload_len = 21;
+  } else {
+    return -1;
+  }
+
+  set_uint32(payload_out + connected_payload_len, htonl(dns_clip_ttl(ttl)));
+  connected_payload_len += 4;
+
+  tor_assert(connected_payload_len <= MAX_CONNECTED_CELL_PAYLOAD_LEN);
+
+  return connected_payload_len;
+}
+
 /** Connected handler for exit connections: start writing pending
  * data, deliver 'CONNECTED' relay cells as appropriate, and check
  * any pending data that may have been received. */
@@ -423,22 +455,16 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn)
                                      RELAY_COMMAND_CONNECTED, NULL, 0) < 0)
       return 0; /* circuit is closed, don't continue */
   } else {
-    char connected_payload[20];
-    int connected_payload_len;
-    if (tor_addr_family(&conn->addr) == AF_INET) {
-      set_uint32(connected_payload, tor_addr_to_ipv4n(&conn->addr));
-      set_uint32(connected_payload+4,
-                 htonl(dns_clip_ttl(edge_conn->address_ttl)));
-      connected_payload_len = 8;
-    } else {
-      memcpy(connected_payload, tor_addr_to_in6_addr8(&conn->addr), 16);
-      set_uint32(connected_payload+16,
-                 htonl(dns_clip_ttl(edge_conn->address_ttl)));
-      connected_payload_len = 20;
-    }
+    uint8_t connected_payload[MAX_CONNECTED_CELL_PAYLOAD_LEN];
+    int connected_payload_len =
+      connected_cell_format_payload(connected_payload, &conn->addr,
+                                    edge_conn->address_ttl);
+    if (connected_payload_len < 0)
+      return -1;
+
     if (connection_edge_send_command(edge_conn,
-                                 RELAY_COMMAND_CONNECTED,
-                                 connected_payload, connected_payload_len) < 0)
+                        RELAY_COMMAND_CONNECTED,
+                        (char*)connected_payload, connected_payload_len) < 0)
       return 0; /* circuit is closed, don't continue */
   }
   tor_assert(edge_conn->package_window > 0);
@@ -2554,21 +2580,20 @@ connection_exit_connect(edge_connection_t *edge_conn)
                                  RELAY_COMMAND_CONNECTED,
                                  NULL, 0);
   } else { /* normal stream */
-    char connected_payload[20];
-    int connected_payload_len;
-    if (tor_addr_family(&conn->addr) == AF_INET) {
-      set_uint32(connected_payload, tor_addr_to_ipv4n(&conn->addr));
-      connected_payload_len = 4;
-    } else {
-      memcpy(connected_payload, tor_addr_to_in6_addr8(&conn->addr), 16);
-      connected_payload_len = 16;
+    uint8_t connected_payload[MAX_CONNECTED_CELL_PAYLOAD_LEN];
+    int connected_payload_len =
+      connected_cell_format_payload(connected_payload, &conn->addr,
+                                    edge_conn->address_ttl);
+    if (connected_payload_len < 0) {
+      connection_edge_end(edge_conn, END_STREAM_REASON_INTERNAL);
+      circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn);
+      connection_free(conn);
     }
-    set_uint32(connected_payload+connected_payload_len,
-               htonl(dns_clip_ttl(edge_conn->address_ttl)));
-    connected_payload_len += 4;
+
     connection_edge_send_command(edge_conn,
                                  RELAY_COMMAND_CONNECTED,
-                                 connected_payload, connected_payload_len);
+                                 (char*)connected_payload,
+                                 connected_payload_len);
   }
 }
 
diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h
index acfa52d..95bc29c 100644
--- a/src/or/connection_edge.h
+++ b/src/or/connection_edge.h
@@ -109,7 +109,9 @@ typedef struct begin_cell_t {
 
 int begin_cell_parse(const cell_t *cell, begin_cell_t *bcell,
                      uint8_t *end_reason_out);
-
+int connected_cell_format_payload(uint8_t *payload_out,
+                                  const tor_addr_t *addr,
+                                  uint32_t ttl);
 #endif
 
 #endif
diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c
index 3fac745..4222c79 100644
--- a/src/test/test_cell_formats.c
+++ b/src/test/test_cell_formats.c
@@ -231,6 +231,7 @@ test_cfmt_connected_cells(void *arg)
   cell_t cell;
   tor_addr_t addr;
   int ttl, r;
+  char *mem_op_hex_tmp = NULL;
   (void)arg;
 
   /* Let's try an oldschool one with nothing in it. */
@@ -332,8 +333,45 @@ test_cfmt_connected_cells(void *arg)
   r = connected_cell_parse(&rh, &cell, &addr, &ttl);
   tt_int_op(r, ==, -1);
 
+  /* Now make sure we can generate connected cells correctly. */
+  /* Try an IPv4 address */
+  memset(&rh, 0, sizeof(rh));
+  memset(&cell, 0, sizeof(cell));
+  tor_addr_parse(&addr, "30.40.50.60");
+  rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE,
+                                            &addr, 128);
+  tt_int_op(rh.length, ==, 8);
+  test_memeq_hex(cell.payload+RELAY_HEADER_SIZE, "1e28323c" "00000080");
+
+  /* Try parsing it. */
+  tor_addr_make_unspec(&addr);
+  r = connected_cell_parse(&rh, &cell, &addr, &ttl);
+  tt_int_op(r, ==, 0);
+  tt_int_op(tor_addr_family(&addr), ==, AF_INET);
+  tt_str_op(fmt_addr(&addr), ==, "30.40.50.60");
+  tt_int_op(ttl, ==, 128);
+
+  /* Try an IPv6 address */
+  memset(&rh, 0, sizeof(rh));
+  memset(&cell, 0, sizeof(cell));
+  tor_addr_parse(&addr, "2620::6b0:b:1a1a:0:26e5:480e");
+  rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE,
+                                            &addr, 3600);
+  tt_int_op(rh.length, ==, 25);
+  test_memeq_hex(cell.payload + RELAY_HEADER_SIZE,
+                 "00000000" "06"
+                 "2620000006b0000b1a1a000026e5480e" "00000e10");
+
+  /* Try parsing it. */
+  tor_addr_make_unspec(&addr);
+  r = connected_cell_parse(&rh, &cell, &addr, &ttl);
+  tt_int_op(r, ==, 0);
+  tt_int_op(tor_addr_family(&addr), ==, AF_INET6);
+  tt_str_op(fmt_addr(&addr), ==, "2620:0:6b0:b:1a1a:0:26e5:480e");
+  tt_int_op(ttl, ==, 3600);
+
  done:
-  ;
+  tor_free(mem_op_hex_tmp);
 }
 
 #define TEST(name, flags)                                               \





More information about the tor-commits mailing list