Commit 882b3896 authored by Nick Mathewson's avatar Nick Mathewson 🎨
Browse files

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.
parent 6b36142b
...@@ -392,6 +392,38 @@ connection_edge_finished_flushing(edge_connection_t *conn) ...@@ -392,6 +392,38 @@ connection_edge_finished_flushing(edge_connection_t *conn)
return 0; 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 /** Connected handler for exit connections: start writing pending
* data, deliver 'CONNECTED' relay cells as appropriate, and check * data, deliver 'CONNECTED' relay cells as appropriate, and check
* any pending data that may have been received. */ * any pending data that may have been received. */
...@@ -423,22 +455,16 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn) ...@@ -423,22 +455,16 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn)
RELAY_COMMAND_CONNECTED, NULL, 0) < 0) RELAY_COMMAND_CONNECTED, NULL, 0) < 0)
return 0; /* circuit is closed, don't continue */ return 0; /* circuit is closed, don't continue */
} else { } else {
char connected_payload[20]; uint8_t connected_payload[MAX_CONNECTED_CELL_PAYLOAD_LEN];
int connected_payload_len; int connected_payload_len =
if (tor_addr_family(&conn->addr) == AF_INET) { connected_cell_format_payload(connected_payload, &conn->addr,
set_uint32(connected_payload, tor_addr_to_ipv4n(&conn->addr)); edge_conn->address_ttl);
set_uint32(connected_payload+4, if (connected_payload_len < 0)
htonl(dns_clip_ttl(edge_conn->address_ttl))); return -1;
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;
}
if (connection_edge_send_command(edge_conn, if (connection_edge_send_command(edge_conn,
RELAY_COMMAND_CONNECTED, RELAY_COMMAND_CONNECTED,
connected_payload, connected_payload_len) < 0) (char*)connected_payload, connected_payload_len) < 0)
return 0; /* circuit is closed, don't continue */ return 0; /* circuit is closed, don't continue */
} }
tor_assert(edge_conn->package_window > 0); tor_assert(edge_conn->package_window > 0);
...@@ -2554,21 +2580,20 @@ connection_exit_connect(edge_connection_t *edge_conn) ...@@ -2554,21 +2580,20 @@ connection_exit_connect(edge_connection_t *edge_conn)
RELAY_COMMAND_CONNECTED, RELAY_COMMAND_CONNECTED,
NULL, 0); NULL, 0);
} else { /* normal stream */ } else { /* normal stream */
char connected_payload[20]; uint8_t connected_payload[MAX_CONNECTED_CELL_PAYLOAD_LEN];
int connected_payload_len; int connected_payload_len =
if (tor_addr_family(&conn->addr) == AF_INET) { connected_cell_format_payload(connected_payload, &conn->addr,
set_uint32(connected_payload, tor_addr_to_ipv4n(&conn->addr)); edge_conn->address_ttl);
connected_payload_len = 4; if (connected_payload_len < 0) {
} else { connection_edge_end(edge_conn, END_STREAM_REASON_INTERNAL);
memcpy(connected_payload, tor_addr_to_in6_addr8(&conn->addr), 16); circuit_detach_stream(circuit_get_by_edge_conn(edge_conn), edge_conn);
connected_payload_len = 16; 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, connection_edge_send_command(edge_conn,
RELAY_COMMAND_CONNECTED, RELAY_COMMAND_CONNECTED,
connected_payload, connected_payload_len); (char*)connected_payload,
connected_payload_len);
} }
} }
......
...@@ -109,7 +109,9 @@ typedef struct begin_cell_t { ...@@ -109,7 +109,9 @@ typedef struct begin_cell_t {
int begin_cell_parse(const cell_t *cell, begin_cell_t *bcell, int begin_cell_parse(const cell_t *cell, begin_cell_t *bcell,
uint8_t *end_reason_out); uint8_t *end_reason_out);
int connected_cell_format_payload(uint8_t *payload_out,
const tor_addr_t *addr,
uint32_t ttl);
#endif #endif
#endif #endif
......
...@@ -231,6 +231,7 @@ test_cfmt_connected_cells(void *arg) ...@@ -231,6 +231,7 @@ test_cfmt_connected_cells(void *arg)
cell_t cell; cell_t cell;
tor_addr_t addr; tor_addr_t addr;
int ttl, r; int ttl, r;
char *mem_op_hex_tmp = NULL;
(void)arg; (void)arg;
/* Let's try an oldschool one with nothing in it. */ /* Let's try an oldschool one with nothing in it. */
...@@ -332,8 +333,45 @@ test_cfmt_connected_cells(void *arg) ...@@ -332,8 +333,45 @@ test_cfmt_connected_cells(void *arg)
r = connected_cell_parse(&rh, &cell, &addr, &ttl); r = connected_cell_parse(&rh, &cell, &addr, &ttl);
tt_int_op(r, ==, -1); 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: done:
; tor_free(mem_op_hex_tmp);
} }
#define TEST(name, flags) \ #define TEST(name, flags) \
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment