diff options
author | Nick Mathewson <nickm@torproject.org> | 2012-11-14 10:48:58 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2012-11-14 23:16:41 -0500 |
commit | 882b389668067a29bb539d0f5bd5cb2f83b93012 (patch) | |
tree | 867e692b6b15922a361633106e48aa46ebd9937d /src/or/connection_edge.c | |
parent | 6b36142bcc6f268a5312e197c4c3397065b3414e (diff) | |
download | tor-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.c | 79 |
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); } } |