Skip to content
Snippets Groups Projects
Commit 882b3896 authored by Nick Mathewson's avatar Nick Mathewson :game_die:
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
No related branches found
No related tags found
No related merge requests found
......@@ -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);
}
}
......
......@@ -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
......
......@@ -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) \
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment