aboutsummaryrefslogtreecommitdiff
path: root/src/or/connection_edge.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2012-11-14 10:48:58 -0500
committerNick Mathewson <nickm@torproject.org>2012-11-14 23:16:41 -0500
commit882b389668067a29bb539d0f5bd5cb2f83b93012 (patch)
tree867e692b6b15922a361633106e48aa46ebd9937d /src/or/connection_edge.c
parent6b36142bcc6f268a5312e197c4c3397065b3414e (diff)
downloadtor-882b389668067a29bb539d0f5bd5cb2f83b93012.tar.gz
tor-882b389668067a29bb539d0f5bd5cb2f83b93012.zip
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.
Diffstat (limited to 'src/or/connection_edge.c')
-rw-r--r--src/or/connection_edge.c79
1 files changed, 52 insertions, 27 deletions
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 4f3dda2842..fbba172b3d 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);
}
}