[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [tor/master] core/or: Support IPv6 EXTEND2 cells
commit bd6ab90ad4b40a64c604c1a4b6b37da6991fad9e
Author: teor <teor@xxxxxxxxxxxxxx>
Date: Tue Apr 14 15:08:42 2020 +1000
core/or: Support IPv6 EXTEND2 cells
Allow clients and relays to send dual-stack and IPv6-only EXTEND2 cells.
Parse dual-stack and IPv6-only EXTEND2 cells on relays.
Relays do not make connections or extend circuits via IPv6: that's the
next step.
Closes ticket 33901.
---
changes/ticket33901 | 4 ++++
src/core/or/onion.c | 41 ++++++++++++++++++++++++++++++++++-------
src/lib/net/address.c | 14 ++++++++++++++
src/lib/net/address.h | 1 +
src/test/test_cell_formats.c | 39 ++++++++++++++++++++++++++-------------
5 files changed, 79 insertions(+), 20 deletions(-)
diff --git a/changes/ticket33901 b/changes/ticket33901
new file mode 100644
index 000000000..b824cc5b0
--- /dev/null
+++ b/changes/ticket33901
@@ -0,0 +1,4 @@
+ o Minor features (IPv6, relay):
+ - Allow clients and relays to send dual-stack and IPv6-only EXTEND2 cells.
+ Parse dual-stack and IPv6-only EXTEND2 cells on relays.
+ Closes ticket 33901.
diff --git a/src/core/or/onion.c b/src/core/or/onion.c
index 45144b5e6..543d9f3e4 100644
--- a/src/core/or/onion.c
+++ b/src/core/or/onion.c
@@ -240,11 +240,21 @@ created_cell_parse(created_cell_t *cell_out, const cell_t *cell_in)
static int
check_extend_cell(const extend_cell_t *cell)
{
+ const bool is_extend2 = (cell->cell_type == RELAY_COMMAND_EXTEND2);
+
if (tor_digest_is_zero((const char*)cell->node_id))
return -1;
- /* We don't currently allow EXTEND2 cells without an IPv4 address */
- if (tor_addr_family(&cell->orport_ipv4.addr) == AF_UNSPEC)
- return -1;
+ if (tor_addr_family(&cell->orport_ipv4.addr) == AF_UNSPEC) {
+ /* EXTEND cells must have an IPv4 address. */
+ if (!is_extend2) {
+ return -1;
+ }
+ /* EXTEND2 cells must have at least one IP address.
+ * It can be IPv4 or IPv6. */
+ if (tor_addr_family(&cell->orport_ipv6.addr) == AF_UNSPEC) {
+ return -1;
+ }
+ }
if (cell->create_cell.cell_type == CELL_CREATE) {
if (cell->cell_type != RELAY_COMMAND_EXTEND)
return -1;
@@ -364,7 +374,12 @@ extend_cell_from_extend2_cell_body(extend_cell_t *cell_out,
}
}
- if (!found_rsa_id || !found_ipv4) /* These are mandatory */
+ /* EXTEND2 cells must have an RSA ID */
+ if (!found_rsa_id)
+ return -1;
+
+ /* EXTEND2 cells must have at least one IP address */
+ if (!found_ipv4 && !found_ipv6)
return -1;
return create_cell_from_create2_cell_body(&cell_out->create_cell,
@@ -620,12 +635,13 @@ extend_cell_format(uint8_t *command_out, uint16_t *len_out,
break;
case RELAY_COMMAND_EXTEND2:
{
- uint8_t n_specifiers = 2;
+ uint8_t n_specifiers = 1;
*command_out = RELAY_COMMAND_EXTEND2;
extend2_cell_body_t *cell = extend2_cell_body_new();
link_specifier_t *ls;
- {
- /* IPv4 specifier first. */
+ if (tor_addr_port_is_valid_ap(&cell_in->orport_ipv4, 0)) {
+ /* Maybe IPv4 specifier first. */
+ ++n_specifiers;
ls = link_specifier_new();
extend2_cell_body_add_ls(cell, ls);
ls->ls_type = LS_IPV4;
@@ -651,6 +667,17 @@ extend_cell_format(uint8_t *command_out, uint16_t *len_out,
ls->ls_len = 32;
memcpy(ls->un_ed25519_id, cell_in->ed_pubkey.pubkey, 32);
}
+ if (tor_addr_port_is_valid_ap(&cell_in->orport_ipv6, 0)) {
+ /* Then maybe IPv6 specifier. */
+ ++n_specifiers;
+ ls = link_specifier_new();
+ extend2_cell_body_add_ls(cell, ls);
+ ls->ls_type = LS_IPV6;
+ ls->ls_len = 18;
+ tor_addr_get_ipv6_bytes((char *)ls->un_ipv6_addr,
+ &cell_in->orport_ipv6.addr);
+ ls->un_ipv6_port = cell_in->orport_ipv6.port;
+ }
cell->n_spec = n_specifiers;
/* Now, the handshake */
diff --git a/src/lib/net/address.c b/src/lib/net/address.c
index 5dbef6a79..5fe9abca1 100644
--- a/src/lib/net/address.c
+++ b/src/lib/net/address.c
@@ -903,6 +903,20 @@ tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6)
tor_addr_from_ipv6_bytes(dest, (const char*)in6->s6_addr);
}
+/** Set the 16 bytes at <b>dest</b> to equal the IPv6 address <b>src</b>.
+ * <b>src</b> must be an IPv6 address, if it is not, log a warning, and clear
+ * <b>dest</b>. */
+void
+tor_addr_get_ipv6_bytes(char *dest, const tor_addr_t *src)
+{
+ tor_assert(dest);
+ tor_assert(src);
+ memset(dest, 0, 16);
+ IF_BUG_ONCE(src->family != AF_INET6)
+ return;
+ memcpy(dest, src->addr.in6_addr.s6_addr, 16);
+}
+
/** Copy a tor_addr_t from <b>src</b> to <b>dest</b>.
*/
void
diff --git a/src/lib/net/address.h b/src/lib/net/address.h
index 498449493..f1c223310 100644
--- a/src/lib/net/address.h
+++ b/src/lib/net/address.h
@@ -303,6 +303,7 @@ void tor_addr_from_ipv6_bytes(tor_addr_t *dest, const char *bytes);
#define tor_addr_from_in(dest, in) \
tor_addr_from_ipv4n((dest), (in)->s_addr);
void tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6);
+void tor_addr_get_ipv6_bytes(char *dest, const tor_addr_t *src);
int tor_addr_is_null(const tor_addr_t *addr);
int tor_addr_is_loopback(const tor_addr_t *addr);
diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c
index 8d6d1940f..3d3f151fc 100644
--- a/src/test/test_cell_formats.c
+++ b/src/test/test_cell_formats.c
@@ -713,16 +713,20 @@ test_cfmt_extend_cells(void *arg)
tt_mem_op(cc->onionskin,OP_EQ, b, 99+20);
tt_int_op(0, OP_EQ, extend_cell_format(&p2_cmd, &p2_len, p2, &ec));
tt_int_op(p2_cmd, OP_EQ, RELAY_COMMAND_EXTEND2);
- /* We'll generate it minus the IPv6 address and minus the konami code */
- tt_int_op(p2_len, OP_EQ, 89+99-34-20);
+ /* We'll generate it minus the konami code */
+ tt_int_op(p2_len, OP_EQ, 89+99-34);
test_memeq_hex(p2,
- /* Two items: one that same darn IP address. */
- "02000612F40001F0F1"
- /* The next is a digest : anthropomorphization */
- "0214616e7468726f706f6d6f727068697a6174696f6e"
+ /* Three items */
+ "03"
+ /* IPv4 address */
+ "0006" "12F40001" "F0F1"
+ /* The next is an RSA digest: anthropomorphization */
+ "0214" "616e7468726f706f6d6f727068697a6174696f6e"
+ /*IPv6 address */
+ "0112" "20020000000000000000000000f0c51e" "1112"
/* Now the handshake prologue */
"01050063");
- tt_mem_op(p2+1+8+22+4,OP_EQ, b, 99+20);
+ tt_mem_op(p2+1+8+22+20+4, OP_EQ, b, 99+20);
tt_int_op(0, OP_EQ, create_cell_format_relayed(&cell, cc));
/* Now let's add an ed25519 key to that extend2 cell. */
@@ -732,22 +736,31 @@ test_cfmt_extend_cells(void *arg)
/* As before, since we aren't extending by ed25519. */
get_options_mutable()->ExtendByEd25519ID = 0;
tt_int_op(0, OP_EQ, extend_cell_format(&p2_cmd, &p2_len, p2, &ec));
- tt_int_op(p2_len, OP_EQ, 89+99-34-20);
+ tt_int_op(p2_len, OP_EQ, 89+99-34);
test_memeq_hex(p2,
- "02000612F40001F0F1"
+ "03"
+ "000612F40001F0F1"
"0214616e7468726f706f6d6f727068697a6174696f6e"
+ "011220020000000000000000000000f0c51e1112"
"01050063");
/* Now try with the ed25519 ID. */
get_options_mutable()->ExtendByEd25519ID = 1;
tt_int_op(0, OP_EQ, extend_cell_format(&p2_cmd, &p2_len, p2, &ec));
- tt_int_op(p2_len, OP_EQ, 89+99-34-20 + 34);
+ tt_int_op(p2_len, OP_EQ, 89+99);
test_memeq_hex(p2,
- "03000612F40001F0F1"
+ /* Four items */
+ "04"
+ /* IPv4 address */
+ "0006" "12F40001" "F0F1"
+ /* The next is an RSA digest: anthropomorphization */
"0214616e7468726f706f6d6f727068697a6174696f6e"
- // ed digest follows:
+ /* Then an ed public key: brownshoesdontmakeit/brownshoesd */
"0320" "62726f776e73686f6573646f6e746d616b656"
"9742f62726f776e73686f657364"
+ /*IPv6 address */
+ "0112" "20020000000000000000000000f0c51e" "1112"
+ /* Now the handshake prologue */
"01050063");
/* Can we parse that? Did the key come through right? */
memset(&ec, 0, sizeof(ec));
@@ -816,7 +829,7 @@ test_cfmt_extend_cells(void *arg)
memcpy(p+1, "\x02\x14" "anarchoindividualist", 22);
memcpy(p+23, "\x01\x12" "xxxxxxxxxxxxxxxxYY", 18);
memcpy(p+41, "\xff\xff\x00\x20", 4);
- tt_int_op(-1, OP_EQ, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND2,
+ tt_int_op(0, OP_EQ, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND2,
p, sizeof(p)));
/* Running out of space in specifiers */
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits