mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
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.
This commit is contained in:
parent
6b36142bcc
commit
882b389668
@ -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)
|
|||||||
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)
|
|||||||
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 {
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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) \
|
||||||
|
Loading…
Reference in New Issue
Block a user